MFC DoModal对话

时间:2011-06-30 00:14:18

标签: c++ mfc

好的,所以我承认我不了解Windows API甚至MFC。

当事情变得毛茸茸(文件名字符串中的非法字符)时,我会弹出一个错误窗口,并且我希望错误框是模态的。

对于我的生活,我无法弄清楚为什么它会在击中doModal时崩溃。

以下是我认为可以修复的代码。此代码位于主窗口中按钮的事件处理程序中。

CDialog *BadFileD = new CDialog();
BadFileD->Create(IDD_STATUS, this); 
BadFileD->DoModal();

我只是处于临界状态?

3 个答案:

答案 0 :(得分:19)

MFC对话框分为两个模式,模态对话框和无模式对话框。

(1)模态对话框用法:

CDialog dlg;
dlg.DoModal();

(2)无模式对话框使用:

CMyDialog *pDlg = new CMyDialog();
pDlg->Create(ID_DLG, this);
pDlg->ShowWindows(SW_SHOW);

如您所见,我们需要新的指针,但不能删除它。因此,您需要在我们的CMyDialg课程中执行以下操作:

  1. DestroyWindow()OnOk()和<{li>中添加OnCancel()。{/ li>
  2. delete this;方法中添加“PostNcDestroy()”。
  3. 如果不这样做,您的代码可能会导致内存泄漏。 BadFileD是类成员,您在析构函数中删除。我建议使用无模式对话框。

答案 1 :(得分:7)

对于显示模式对话框,您应该只使用DoModal方法

CDialog *BadFileD = new CDialog(IDD_STATUS, this);
BadFileD->DoModal();

您可以阅读article

的评论

答案 2 :(得分:1)

如果您只想显示错误消息,则可能只是使用AfxMessageBox()而不是创建自己的对话框。参见Microsoft Developer Network - AfxMessageBox

如果通常要使用MFC项目创建自己的对话框,则通常:

  • 使用资源编辑器创建对话框模板
  • 使用实现所需行为的类向导创建一个封装对话框的类
  • 将代码插入以创建对话框并将其显示在适当的位置

但是,通过一个简单的对话框,该对话框不需要用于复杂行为的支持类,您可以跳过使用类向导创建封装类的步骤,而直接使用CDialog

需要回答的一个问题是对话框的生存期以及它是模态的还是无模的。模态对话框要求用户做一些事情,使应用程序继续经过模态对话框。无模式对话框不会像模式对话框那样阻止应用程序。还有一个系统模式对话框样式。

由于您说这将是一个模态对话框,所以生存期将很短,因此整个构造,显示和销毁可能都在一系列代码行中。例如,在带有命令处理程序的CView类中,该命令处理程序显示模式对话框,

void CViewThing::OnCommandMenuItem ()
{
    CDialog BadFileD(IDD_STATUS);
    int iRetStatus = BadFileD.DoModal();
    // check for status such as IDOK, etc.
    // do whatever is necessary.
}

上述操作是使用对话框资源模板IDD_STATUS创建一个对话框并将其显示为模式对话框。由于它是本地对象,因此当变量BadFileD超出范围时,将触发对话框析构函数并为您清除资源。

您还可以有一个无模式对话框。对于无模式对话框,您需要考虑变量的生存期,因为一旦变量超出范围,析构函数将立即触发,对话框将消失。

因此,对于与某个视图类一起使用的无模式对话框(也许提供某种工具箱),CDialog变量将是使用它的CView类的成员。创建无模式对话框后,通过使用ShowWindow()类的CDialog成员函数(实际上是CWnd类的成员,CDialog的成员函数来显示该对话框)派生)。

void CViewThing::OnCommandMenuItem ()
{
    BadFileD.Create(IDD_STATUS, this);
    BadFileD.ShowWindow(SW_SHOW);   // display the dialog
}

,在CViewThing类中,您将有一个成员变量CDialog BadFileD;

其他注意事项

在以上所有示例中,我们都没有使用指针,因此当CDialog变量超出范围时(退出成员函数或使用该对话框的对象被销毁),该对话框就会消失。也一样该对象管理已为我们完成。

对于无模式对话框,您必须考虑的一件事是如何在不再需要它时将其销毁。

由于模式对话框通常是一个短期对象,通常是在堆栈上作为局部变量创建的,因此通常只允许它超出范围以处理与破坏有关的所有事情。

但是,无模式对话框的生存期要求DestroyWindow()方法用于在不再需要该对话框时将其销毁。参见Microsoft Developer Network - Destroying the Dialog Box

第三种使用情况-嵌入对话框

对话框的第三种用法有时会派上用场,它将对话框作为控件嵌入到另一个窗口中。

在以上示例中,对话框模板为对话框指定WS_POPUP样式,这是对话框的标准样式,因为使用对话框的通常方式是显示为单独的窗口。

但是,如果将WS_POPUP样式更改为WS_CHILD,则可以将对话框作为控件嵌入到另一个窗口中。您可以删除其他样式设置,例如WS_SYSMENUDS_MODALFRAMEWS_CAPTION,并从对话框模板中删除CAPTION行,以进一步更改对话框。所以您最终会得到类似的东西:

IDD_STATUS DIALOGEX 0, 0, 435, 266
STYLE DS_SETFONT | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    LTEXT           "this is some static text to display on this dialog.",IDC_STATIC,81,63,200,32
END

然后只使用生成的对话框,就像使用ShowWindow()创建无模式对话框一样。

如果需要在容器对话框中重新定位嵌入式对话框,则可以使用SetWindowPos()方法。例如,以下操作会将对话框窗口从其包含的窗口中移到包含窗口的左侧20像素和顶部10像素的位置。

BadFileD.SetWindowPos(NULL, 20, 10, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER)