小弟想自己封装GDialog类,包括模态的和非模态的。 GDialog 类为基类, 然后自己只要继承GDialog,然后实现OnCommand等方法就可以了。但是小弟,遇到一个问题,就是如果一个非模态父窗口创建了一个非模态子窗口,直接关闭父窗口,子窗口虽然能够关闭,但是主程序没有办法退出。下面是我的代码://GDialog.h
#pragma onceclass GDialog
{
public:
   virtual ~GDialog();
   INT_PTR ShowModalDialog(HINSTANCE hInst, HWND hwndParent);
   HWND ShowDialog(HINSTANCE hInst, HWND hwndParent);protected:
         GDialog(DWORD dwResID, UINT uMenuID, LPCTSTR szTitle);
static  LRESULT CALLBACK DialogFunc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CloseWindow();
void DistroyWindow(); virtual BOOL OnInitDialog(HWND hwndFocus, LPARAM lParam);
virtual BOOL OnCommand(int id, HWND hwndCtl, UINT codeNotify);
protected:
DWORD m_dwResID;
HWND m_hwndParent;
         HWND m_hwnd;
         HINSTANCE m_hInstance;
         UINT m_uMenuID;
         HWND m_hwndMenu;
         LPCTSTR m_szTitle;
BOOL m_fmodal;}; 
//GDialog.cpp
#include "stdafx.h"
#include "GDialog.h"GDialog::GDialog(DWORD dwResID, UINT uMenuID, LPCTSTR szTitle):
m_dwResID(dwResID),
m_uMenuID(uMenuID),
m_szTitle(szTitle),
m_fmodal(FALSE),
m_hwndParent(NULL),
m_hInstance(NULL),
m_hwnd(NULL)
{};GDialog::~GDialog()
{
MessageBox(NULL,L"~GDialog",0,MB_OK);
};HWND GDialog::ShowDialog(HINSTANCE hInst, HWND hwndParent)
{
MSG msg;
m_fmodal = FALSE;
m_hInstance = hInst;
m_hwndParent = hwndParent; m_hwnd = CreateDialogParam(hInst, MAKEINTRESOURCE(m_dwResID),  hwndParent, (DLGPROC)DialogFunc,(LPARAM)this);    ShowWindow(m_hwnd,SW_SHOW); while(GetMessage(&msg,NULL,0,0))   
{   
if(!m_hwnd||!IsDialogMessage(m_hwnd,&msg))   
{   
TranslateMessage(&msg);   
DispatchMessage(&msg);   
}   
}   return m_hwnd;
};INT_PTR GDialog::ShowModalDialog(HINSTANCE hInst, HWND hwndParent)
{
m_fmodal = TRUE;
m_hInstance = hInst;
m_hwndParent = hwndParent; return DialogBoxParam(hInst, MAKEINTRESOURCE(m_dwResID), hwndParent, (DLGPROC)DialogFunc,(LPARAM)this);
}void GDialog::CloseWindow()
{
if(m_fmodal)
{
EndDialog(m_hwnd,1);
}
else
{
DestroyWindow(m_hwnd);
}
}void GDialog::DistroyWindow()
{
PostQuitMessage(WM_QUIT);
}
LRESULT GDialog::DialogFunc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
GDialog * this_ptr = (GDialog *) GetWindowLong(hWnd, DWL_USER);    switch (uMsg) {
        case WM_INITDIALOG:
{
this_ptr = (GDialog *) lParam;
if(this_ptr->m_fmodal)
{
    this_ptr->m_hwnd = hWnd;
}
SetWindowLong(hWnd, DWL_USER, (LONG) this_ptr);
return this_ptr->OnInitDialog((HWND)wParam,lParam);
}        case WM_ACTIVATE:
            if (WA_INACTIVE != LOWORD(wParam)) {
                SetFocus(hWnd);
            }
            return TRUE;        case WM_CLOSE:
            this_ptr->CloseWindow();
            return TRUE;        case WM_COMMAND:
            return  this_ptr->OnCommand(
LOWORD(wParam),
(HWND) lParam,
                HIWORD(wParam)); case WM_DESTROY:
if(!this_ptr->m_fmodal)
{
   MessageBox(NULL,this_ptr->m_szTitle,0,MB_OK);
               this_ptr->DistroyWindow();
}
             break;    }
   return FALSE;
};BOOL GDialog::OnCommand(int id, HWND hwndCtl, UINT codeNotify)
{
UNREFERENCED_PARAMETER(id);
UNREFERENCED_PARAMETER(hwndCtl);
UNREFERENCED_PARAMETER(codeNotify);
return TRUE;
};BOOL GDialog::OnInitDialog(HWND hwndFocus, LPARAM lParam)
{
UNREFERENCED_PARAMETER(hwndFocus);
UNREFERENCED_PARAMETER(lParam);
return TRUE;
};
//MainDialog.h
#pragma once#include "GDialog.h"class MainDialog : public GDialog
{
public:
MainDialog(DWORD dwResID, UINT uMenuID, LPCTSTR szTitle);
virtual ~MainDialog();protected:
BOOL OnInitDialog(HWND hwndFocus, LPARAM lParam);
BOOL OnCommand(int id, HWND hwndCtl, UINT codeNotify);};
//MainDialog.cpp
MainDialog::MainDialog(DWORD dwResID, UINT uMenuID, LPCTSTR szTitle):
GDialog(dwResID,uMenuID,szTitle),indx(0)
{
memset(m_childDlg, 0, sizeof(m_childDlg));
};MainDialog::~MainDialog()
{};BOOL MainDialog::OnCommand(int id, HWND hwndCtl, UINT codeNotify)
{
MsgDialog* msgDlg = NULL;
switch (id) { case IDC_BTN_CLOSE:
CloseWindow();
return TRUE; case IDC_BTN_NEW: msgDlg = new MsgDialog(IDD_DLG_MSG,0,L"MsgDialogString");
msgDlg->ShowDialog(m_hInstance,m_hwnd);
            
                           delete msgDlg; return TRUE; } return FALSE;
};BOOL MainDialog::OnInitDialog(HWND hwndFocus, LPARAM lParam)
{
return TRUE;
};
//MsgDialog.h
class MsgDialog : public GDialog
{
public:
MsgDialog(DWORD dwResID, UINT uMenuID, LPCTSTR szTitle);
virtual ~MsgDialog();protected:
BOOL OnInitDialog(HWND hwndFocus, LPARAM lParam);
BOOL OnCommand(int id, HWND hwndCtl, UINT codeNotify);
};
//MsgDialog.cpp
MsgDialog::MsgDialog(DWORD dwResID, UINT uMenuID, LPCTSTR szTitle):
GDialog(dwResID,uMenuID,szTitle)
{
};MsgDialog::~MsgDialog()
{};BOOL MsgDialog::OnCommand(int id, HWND hwndCtl, UINT codeNotify)
{
switch (id) {
case IDCANCEL:
CloseWindow();
return TRUE;
} return FALSE;
};BOOL MsgDialog::OnInitDialog(HWND hwndFocus, LPARAM lParam)
{
return TRUE;
};//Main.cpp
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); MainDialog* mainDlg = new MainDialog(IDD_DLG_MAIN,0,L"MainDialogString");
mainDlg->ShowDialog(hInstance,0); delete mainDlg;
return 1;
}

解决方案 »

  1.   

    MessageBox(NULL,this_ptr->m_szTitle,0,MB_OK); 
                  this_ptr->DistroyWindow(); 关闭主窗口,上面两句代码执行到了没有?
      

  2.   

    应该是都执行了,但是只是show出来“MsgDialogString”。
    我跟断点进去看,实际上WM_DESTROY 执行了两次
    先执行“MsgDialogString”; this_ptr->DistroyWindow(); 
    然后执行“MainDialogString”;this_ptr->DistroyWindow(); 但是“MainDialogString”没有show出来两个窗口都消失了,但是主程序没有退出
      

  3.   

    你在GDialog::ShowDialog函数中创建了对话框并执行消息循环,其效果与模态对话框基本相同,只是没有禁用父窗口而已。在弹出一个新窗口时,程序处于嵌套的两个消息循环之中,这种情况应该先关闭弹出窗口,使内层消息循环退出,然后再关闭主窗口。可以改成在窗口关闭时检查是否有弹出窗口,如果有,则先将其关闭。