【问题标题】:Two dialogs in one MFC application一个 MFC 应用程序中的两个对话框
【发布时间】: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()

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

【问题讨论】:

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

标签: winapi mfc


【解决方案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 框架完成的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多