如何从外部关闭cdialog派生窗口



比如说,我在我的上下文菜单中创建了一个对话框窗口,可以通过右键单击我的应用程序的托盘图标来调用:

CDialogDerivedClass dlg;
dlg.DoModal();

如果用户再次右键单击我的上下文菜单并选择另一个命令,我需要关闭该对话框窗口并显示另一个。我认为简单地向第一个窗口发送WM_CLOSE就可以达到目的:

dlg.SendMessage(WM_CLOSE);

,但显然它在MFC类里面搞砸了一些东西,因为那个对话框的CDialogDerivedClass::OnDestroy()方法在那一刻从未被调用。只有当我的应用程序或它的进程退出时才会发生这种情况。

所以我很好奇,你如何关闭MFC的CDialog派生类从外面(从相同的/主线程)?

我想你可以模拟点击取消:::EndDialog(dlg.m_hWnd, IDCANCEL);

很抱歉我误解了你的问题。

你可以在你的主类中为你想要从系统托盘菜单开始的每个对话创建一个指针:

在你的主类头中为你的对话添加指针:

CDialog1 *m_pDialog1;
CDialog2 *m_pDialog2;

不要忘记在你的主类构造函数中将它们初始化为NULL。

添加MAP来处理菜单选项:

ON_COMMAND(ID_DIALOG1, &CSystemTrayApp::OnDialog1)
ON_COMMAND(ID_DIALOG2, &CSystemTrayApp::OnDialog2)

然后,在开始新对话之前,使用指针为任何已开始的对话调用"EndDialog":

void CSystemTrayApp::OnDialog1()
{
    if ( m_pDialog2 != NULL && m_pDialog2->GetSafeHwnd() )
    {
        m_pDialog2->EndDialog(IDCANCEL);
        delete m_pDialog2;
        m_pDialog2 = NULL;
    }
    m_pDialog1 = new CDialog1();
    m_pDialog1->DoModal();
}

void CSystemTrayApp::OnDialog2()
{
    if ( m_pDialog1 != NULL && m_pDialog1->GetSafeHwnd() )
    {
        m_pDialog1->EndDialog(IDCANCEL);
        delete m_pDialog1;
        m_pDialog1 = NULL;
    }
    m_pDialog2 = new CDialog2();
    m_pDialog2->DoModal();
}

在主类的解构器上,如果需要,清理对话框:

if ( m_pDialog1 != NULL ) delete m_pDialog1;
if ( m_pDialog2 != NULL ) delete m_pDialog2;

通过对某个窗口的句柄,应用程序可以向该窗口发送/发布任何类型的消息。因此,这里有一个可能的解决方案,您可能想要尝试一下。

简单地说,当第一个非模态窗口(调用DoModel()的窗口)创建后,将其句柄保存为全局变量或另一个Static变量。当你想关闭非模态时,你可以post一个WM_CLOSE消息到那个窗口。

重要的是传递WM_CLOSE消息的API。正如官方文档所描述的:
    sendmessage()函数调用指定窗口的窗口过程,直到窗口过程处理完消息才返回。postmessage()函数只是在与创建指定窗口的线程关联的消息队列中放置(发布)消息,然后返回,而不等待线程处理该消息。

简单来说,首先要保存句柄;第二,传递WM_CLOSE(或某种类型的消息)到该窗口。

Try

EndDialog (IDCANCEL);或EndDialog (IDOK);

希望有帮助,

费尼

最新更新