在等待对DoModal()的调用返回时,对话框如何响应?

时间:2015-06-11 14:52:01

标签: winapi com mfc modal-dialog

对话框上的按钮会导致创建子对话框,并以模态方式显示。

e.g:

void ParentDialog::OnButton()
{
 ChildDialog dlg;
 int ret = dlg.DoModal();
}

父对话框最初未按预期响应。但是,子对话框也使COM调用服务器模块,这导致服务器将COM调用回到父对话框...更新显示的数据等。在一种情况下,这会导致父对话框突然变为响应即使子对话框仍在屏幕上,也会再次显示。即使父对话仍在耐心地等待OnButton()返回,现在两个对话框都可以进行交互。

这怎么可能发生?我正在搜索代码,但有什么具体的我应该寻找吗?

2 个答案:

答案 0 :(得分:3)

对话框有自己的消息泵/循环,在调用内部有一个循环,它继续接收和分派窗口消息。这包括COM相关消息工作器窗口接收并转换为您正在看到的COM回调。关闭对话框后,各个窗口将被销毁,该函数将从循环中退出并将控制权返回给您的代码。

也就是说,如果不立即将控制权返回给您的代码,窗口消息调度仍然会保持正常工作,并且UI会响应。

MSDN

  

...该函数显示对话框,禁用所有者窗口,并启动自己的消息循环以检索和分派对话框的消息。

     

当对话框过程调用EndDialog函数时,DialogBox会破坏对话框,结束消息循环,启用所有者窗口(如果先前已启用),并在调用EndDialog时返回对话框过程指定的nResult参数。

答案 1 :(得分:0)

您可以创建无模式对话框并使用RunModalLoop等待对话框完成,有点类似于DoModal()

void CMyWnd::foo()
{
    static BOOL isOpen = FALSE;
    if (isOpen) return;//optional, prevents opening multiple dialogs

    CDialog dlg;
    dlg.Create(IDD_DIALOG1, this);
    dlg.ShowWindow(SW_SHOW);
    isOpen = TRUE;

    int result = dlg.RunModalLoop(0);
    dlg.DestroyWindow();
    isOpen = 0;

    TRACE("res:%d\n", result);
}

问题:请注意,在上面的示例中,您可以关闭程序,但对话框仍然会启动。你必须强制关闭对话框,上面的函数不会处理它。

或者您可以通常的方式创建无模式对话框:

if (m_Dlg) return;
m_Dlg = new CDialog
m_Dlg.Create(IDD_DIALOG1, this);
m_Dlg.ShowWindow(SW_SHOW);

但是在此示例中,如果用户单击“确定/取消”然后您不知道它,则必须覆盖OnOK()/OnCancel,然后将消息发送到父窗口/对话框,处理消息,然后手动销毁对话框。