头文件:
#pragma once#include "StdRes.h"class CMainDialog : public CDialogImpl<CMainDialog>,
                    public CDialogResize<CMainDialog>
{
public:
    enum { IDD = IDD_DIALOG };
    enum
    {
        ID_BTN1 = 2000,
        ID_BTN2,
        ID_EDT1
    };    BEGIN_MSG_MAP(CMainDialog)
        MSG_WM_INITDIALOG(OnInitDialog)
        MSG_WM_CLOSE(OnClose)
        MSG_WM_DESTROY(OnDestroy)
        COMMAND_ID_HANDLER_EX(ID_BTN1, OnButton1Click)
        COMMAND_ID_HANDLER_EX(ID_BTN2, OnButton2Click)
        CHAIN_MSG_MAP(CDialogResize<CMainDialog>)
    END_MSG_MAP()    BEGIN_DLGRESIZE_MAP(CMainDialog)
        DLGRESIZE_CONTROL(ID_BTN1, DLSZ_SIZE_X | DLSZ_SIZE_Y)
        DLGRESIZE_CONTROL(ID_BTN2, DLSZ_SIZE_X | DLSZ_MOVE_Y)
        DLGRESIZE_CONTROL(ID_EDT1, DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOVE_Y)
    END_DLGRESIZE_MAP()    BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam);
    void OnClose();
    void OnDestroy();
    void OnButton1Click(UINT uNotifyCode, int nID, CWindow wndCtl);
    void OnButton2Click(UINT uNotifyCode, int nID, CWindow wndCtl);protected:
    std::list<CWindow *> m_wndList;
};源文件:
#include "StdAfx.h"
#include "MainDialog.h"BOOL CMainDialog::OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
{
    MoveWindow(CRect(0, 0, 0, 160), FALSE);    CButton* btn = new CButton;
    btn->Create(m_hWnd, CRect(8, 8, 96, 38), _T("按钮一"), WS_CHILD, 0, ID_BTN1);
    m_wndList.push_back(btn);    CEdit* edt = new CEdit;
    edt->Create(m_hWnd, CRect(8, 48, 96, 78), _T("文本"), WS_CHILD, 0, ID_EDT1);
    m_wndList.push_back(edt);    btn = new CButton;
    btn->Create(m_hWnd, CRect(8, 88, 96, 118), _T("按钮二"), WS_CHILD, 0, ID_BTN2);
    m_wndList.push_back(btn);    std::for_each(m_wndList.begin(), m_wndList.end(), [this](CWindow *p)
    {
        p->ShowWindow(SW_SHOW);
        p->SetFont(GetFont());
    });    DlgResize_Init();
    CenterWindow();
    SetMsgHandled(FALSE);
    return TRUE;
}void CMainDialog::OnClose()
{
    EndDialog(IDOK);
    SetMsgHandled(FALSE);
}void CMainDialog::OnDestroy()
{
    std::for_each(m_wndList.begin(), m_wndList.end(), [this](CWindow *p)
    {
        p->DestroyWindow();
        delete p;
    });
    m_wndList.clear();
    SetMsgHandled(FALSE);
}void CMainDialog::OnButton1Click(UINT uNotifyCode, int nID, CWindow wndCtl)
{
    MessageBox(_T("OnButton1Click"));
}void CMainDialog::OnButton2Click(UINT uNotifyCode, int nID, CWindow wndCtl)
{
    MessageBox(_T("OnButton2Click"));
}
疑问一:基于CDialogImpl创建对话框时,我将被迫使用一个对话框资源:
#include <Windows.h>#define IDD_DIALOG 1000IDD_DIALOG DIALOGEX 0,0,160,100
FONT 8,"Ms Shell Dlg",0,0,0
STYLE WS_VISIBLE|WS_OVERLAPPEDWINDOW
BEGIN
END不知道ATL或WTL有没有内置的对话框资源ID可用?疑问二:
void CMainDialog::OnDestroy()
{
    std::for_each(m_wndList.begin(), m_wndList.end(), [this](CWindow *p)
    {
        p->DestroyWindow();
        delete p;
    });
    m_wndList.clear();
    SetMsgHandled(FALSE);
}
在这个函数中,我调用了DestroyWindow()以销毁动态创建的子窗口:不知道是否有这个必要?
我查了CWindow的源码,在析构函数中并没有调用DestroyWindow()。
但由于这个控件是以当前对话框为父窗口的。
不知道在父窗口销毁的时候,是否会销毁所有子窗口?

解决方案 »

  1.   

    1、貌似没有
    2、不需要,销毁窗口时会自动销毁其全部子窗口(具有WS_CHILD风格)。
      

  2.   

    WTL销毁窗口是有些问题。delete的时候,在这里delete即可。void CXXXWnd::OnFinalMessage(HWND)
    {
        delete this;
    }OnFinalMessage是个虚函数。
      

  3.   

    WTL的子窗口由父窗口负责销毁~,父窗口的delete按照我说的做即可。
      

  4.   

    用CWindowImpl,自己处理IsDialogMessage()
     可以参考MFC的一些代码。
      

  5.   

    我也是猜的,我最近也遇到类似问题了,MFC的IsDialogMessage里面做了一些事情,你可以研究一下啊~
      

  6.   

    1.“不知道ATL或WTL有没有内置的对话框资源ID可用”,应该没有吧,没有这种需求嘛。你只是不想用资源文件吧?
    既不想用资源文件,你干脆不用对话框,把CDialogImpl换成CWindowImpl,直接用普通窗口。(普通窗口也可以容得下你所有的控件)
    2.父窗口在要挂之前,会把它的child统统Destroy掉
      

  7.   

    对话框还有一个内置的CResizeDialog,非常酷,省了很多事。
    还没试过能否把这个类用在CWindowImpl上。
      

  8.   

    我可没那水平。
    重新学习WTL,还没入门。发现CDialogResize可以应用在CWindowImpl上的。
    头文件:
    #pragma onceclass CMainFrame : public CFrameWindowImpl<CMainFrame>,
                       public CDialogResize<CMainFrame>
    {
    public:
        DECLARE_FRAME_WND_CLASS(_T("Wtl Window Class"), 0)    enum
        {
            ID_BTN1 = 2000,
            ID_BTN2,
            ID_EDT1
        };    BEGIN_MSG_MAP(CMainFrame)
            MSG_WM_CREATE(OnCreate)
            MSG_WM_DESTROY(OnDestroy)
            CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
            CHAIN_MSG_MAP(CDialogResize<CMainFrame>)
        END_MSG_MAP()    BEGIN_DLGRESIZE_MAP(CMainFrame)
            DLGRESIZE_CONTROL(ID_BTN1, DLSZ_SIZE_X | DLSZ_SIZE_Y)
            DLGRESIZE_CONTROL(ID_BTN2, DLSZ_SIZE_X | DLSZ_MOVE_Y)
            DLGRESIZE_CONTROL(ID_EDT1, DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOVE_Y)
        END_DLGRESIZE_MAP()    int OnCreate(LPCREATESTRUCT lpCreateStruct);
        void OnDestroy();
        void OnFinalMessage(HWND hWnd);protected:
        std::list<CWindow *> m_wndList;
    };源文件:
    #include "StdAfx.h"
    #include "MainFrame.h"int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        MoveWindow(CRect(0, 0, 0, 160), FALSE);    CButton* btn = new CButton;
        btn->Create(m_hWnd, CRect(8, 8, 96, 38), _T("按钮一"), WS_CHILD, 0, ID_BTN1);
        m_wndList.push_back(btn);    CEdit* edt = new CEdit;
        edt->Create(m_hWnd, CRect(8, 48, 96, 78), _T("文本"), WS_CHILD, 0, ID_EDT1);
        m_wndList.push_back(edt);    btn = new CButton;
        btn->Create(m_hWnd, CRect(8, 88, 96, 118), _T("按钮二"), WS_CHILD, 0, ID_BTN2);
        m_wndList.push_back(btn);    std::for_each(m_wndList.begin(), m_wndList.end(), [this](CWindow *p)
        {
            p->ShowWindow(SW_SHOW);
            p->SetFont(AtlGetDefaultGuiFont());
        });    DlgResize_Init(false);
        CenterWindow();
        SetMsgHandled(FALSE);
        return 0;
    }void CMainFrame::OnDestroy()
    {
        MessageBox(_T("OnDestroy"));
        SetMsgHandled(FALSE);
    }void CMainFrame::OnFinalMessage(HWND hWnd)
    {
        std::for_each(m_wndList.begin(), m_wndList.end(), [](CWindow *p)
        {
            delete p;
        });
        m_wndList.clear();
    }
    区别:
    DlgResize_Init(false); // 这里传false,因为背景色不一样[/code
    另:
    [code=C/C++]std::for_each(m_wndList.begin(), m_wndList.end(), [this](CWindow *p)
        {
            p->ShowWindow(SW_SHOW);
            p->SetFont(AtlGetDefaultGuiFont());
        });
    要用AtlGetDefaultGuiFont()来获取字体。
      

  9.   

    原来WTL已经有这样的类了:CIndirectDialogImpl
    标记一下!!