一个 MFC 应用程序中的两个对话框

Posted

技术标签:

【中文标题】一个 MFC 应用程序中的两个对话框【英文标题】:Two dialogs in one MFC application 【发布时间】:2013-04-13 09:35:05 【问题描述】:

我正在尝试制作一个基于对话框的 MFC 应用程序,其中两个对话框需要按顺序显示。

这意味着,一旦第一个对话框(模态)显示并关闭(按确定),就需要调出第二个对话框。我的要求是第二个对话框应该是无模式的。

但我观察到的是显示了第二个对话框,但没有调用任何消息处理函数来响应用户消息。我认为消息映射本身不起作用,而被覆盖的函数(如 OnInitdialog)正在被调用.我尝试用模态对话框替换这个无模式对话框,唉,doModal() 本身失败了。 这是小代码:

    CFirstDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    
        // TODO: Place code here to handle when the dialog is
        //  dismissed with OK
        // TODO: Place code here to handle when the dialog is
        //  dismissed with Cancel

        CSecondDlg *dlgModeLess = new CSecondDlg();
        dlgModeLess->Create(CSecondDlg::IDD,NULL);

        m_pMainWnd = dlgModeLess;

        dlgModeLess->ShowWindow(SW_SHOW);
        dlgModeLess->UpdateWindow();
         

这是第二个对话框的消息映射:

BEGIN_MESSAGE_MAP(CSecondDlg, CDialog)
    ON_MESSAGE(TRAY_MESSAGE,OnTrayMessage)
    ON_BN_CLICKED(IDOK, &CSecongDlg::OnBnClickedOk)
    ON_BN_CLICKED(IDC_RADIO1, &CSecondDlg::OnBnClickedRadio1)
END_MESSAGE_MAP()

我认为我在做一些概念上的错误。请分享您对解决这种情况需要做些什么的想法。

【问题讨论】:

你为什么不带上另一个模态对话框?当除了该对话框之外没有其他窗口时,对话框是模态的还是非模态的并不重要。 【参考方案1】:

正如我在上一篇文章中提到的,第二个对话框没有必要是非模态的。

只要做这样的事情:

BOOL CMyTestApp::InitInstance()

  CMyTestDlg dlg;
  m_pMainWnd = &dlg;
  int nResponse = dlg.DoModal();
  if (nResponse == IDOK)
  
      COtherDlg Dlg ;
      m_pMainWnd = &dlg;
      if (Dlg.DoModal() == IDCANCEL)
      
      ...
      
  
  else if (nResponse == IDCANCEL)
  
    ...
  

  return FALSE;

【讨论】:

您是否尝试运行该程序?由于我不知道的原因,当我在我的环境中运行该程序时。你的回答会很有帮助。 是的,它可以在我的 Windows 7 计算机上运行。当您运行它时,您的计算机上究竟发生了什么?你有什么操作系统?看看 Pastebin 上的代码:pastebin.com/TPegYKqW,pastebin.com/PVqw68f8 当我从第一个对话框的 OnOK() 调用第二个对话框时,此代码确实有效。但是从 CMyTestApp::InitInstance() 调用第二个对话框的代码崩溃了。你确定吗 ?我也在寻找它背后的原因。 好的,所以它没有崩溃,但给出了几个调试断言失败,发布版本工作正常。我进一步发现调试断言是因为语句 m_pMainWnd = &dlg 在这种情况下似乎没有必要。但即便如此,它也不起作用。我们必须在 doModal 之前使用 PM_REMOVE 调用 PeekMessage() 以使其工作 究竟哪些断言失败了?【参考方案2】:

当您创建一个无模式对话框时,控制将立即返回到您的调用函数,因此您需要在全局范围内声明变量dlgModeLess,并确保您的程序/范围在对话框结束之前仍然处于活动状态

【讨论】:

【参考方案3】:

我已经解决了这个问题,结果证明这很有趣。

似乎 Cdialog::Create() 本身不足以创建一个完全可操作的无模式对话框。我们必须为其提供一个 win32 样式的消息循环。 所以这有效地在程序中产生了两个消息循环,一个提供我的 MFC 框架,另一个是我从 IDOK 返回后编写的。这是修改后的代码。

CSecondDlg *dlgModeLess = new CSecondDlg();
    dlgModeLess->Create(CSecondDlg::IDD,NULL);



    CTrayIconDlg dlg;
    m_pMainWnd = &dlg;
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    
        // TODO: Place code here to handle when the dialog is
        //  dismissed with OK
        // TODO: Place code here to handle when the dialog is
        //  dismissed with Cancel

        MSG leftmsg;
        PeekMessage(&leftmsg,m_pMainWnd->m_hWnd,0,0,PM_REMOVE);
        MSG msg;
        BOOL bRet;
        while ((bRet = GetMessage(&msg, dlgModeLess->m_hWnd, 0, 0)) != 0) 
         
            if (bRet == -1)
            
                // Handle the error and possibly exit
            
            else if (!IsWindow(hWnd) || !IsDialogMessage(hWnd, &msg)) 
             
                TranslateMessage(&msg); 
                DispatchMessage(&msg); 
             
         



    

此代码按预期工作,这里要注意的有趣之处是 PeekMessage 函数,该函数会在第一个对话框被解除后删除插入线程的消息队列中的 WM_QUIT 消息,因为我们不想在那个时间点完全关闭.我相信这是由 MFC 框架完成的。

【讨论】:

以上是关于一个 MFC 应用程序中的两个对话框的主要内容,如果未能解决你的问题,请参考以下文章

MFC 对话框显示在任务栏中

如何在单独的 mfc 控制台应用程序中使用 mfc 应用程序的对话框?

在 mfc 中打开另一个表单

MFC如何获取控件在对话框上的位置坐标

将 MainApp 从 MFC 应用程序转换为辅助对话框

非 MFC 应用程序中的 MFC 对话框