繁体   English   中英

MFC DoModal 对话框

[英]MFC DoModal Dialog

好的,所以我承认我不知道 windows API 甚至 MFC。

当 go 多毛(文件名字符串中的非法字符)时弹出错误 window 并且我希望错误框是模态的。

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

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

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

我只是边缘性智障吗?

MFC 对话框分两种模式,模态对话框和非模态对话框。

(1) 模态对话框用法:

CDialog dlg;
dlg.DoModal();

(2) 无模式对话用法:

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

如您所见,我们需要一个新指针,但不要删除它。 因此,您需要在我们的CMyDialog class 中执行以下操作:

  1. OnOk()OnCancel()中添加DestroyWindow()方法。
  2. PostNcDestroy()方法中添加“ delete this; ”。

如果不这样做,您的代码可能会导致 memory 泄漏。 BadFileD是 class 成员,您在析构函数中将其删除。 我建议使用无模式对话框。

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

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

您可以阅读文章中的备注

如果您只想显示一条错误消息,那么您可以使用AfxMessageBox()而不是创建自己的对话框。 请参阅Microsoft 开发人员网络 - AfxMessageBox

如果您想使用 MFC 项目来创建自己的对话框,您通常会:

  • 使用资源编辑器创建对话框模板
  • 创建一个 class 封装对话框,使用 class 向导实现所需的行为
  • 将用于创建和显示对话框的代码插入到适当的位置

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

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

既然你说这将是一个模态对话框,那么生命周期就会很短,所以整个构建、显示和销毁可能都在一系列代码行中。 例如,在带有显示模式对话框的命令处理程序的CView class 中,您可能有:

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

上面所做的是使用对话框资源模板IDD_STATUS创建一个对话框并将其显示为模式对话框。 由于是本地object,当变量BadFileD走出scope时,会触发对话框析构函数,为你清理资源。

你也可以有一个无模式的对话框。 在无模式对话框的情况下,您需要考虑变量的生命周期,因为一旦变量超出 scope,析构函数将触发并且对话框将消失。

因此,对于与某些视图 class 一起使用的无模式对话框,可能提供某种工具箱, CDialog变量将是正在使用它的CView class 的成员。 无模式对话框创建后,通过使用CDialog class的ShowWindow()成员function(实际上是CWnd CDialog的成员)的成员来显示或不显示。

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

CViewThing class 中,您将拥有一个成员变量CDialog BadFileD; .

其他注意事项

在上述所有示例中,我们都没有使用指针,因此当CDialog变量退出 scope 时,要么退出成员 function,要么当 object 使用对话框被破坏时。 这个 object 管理是为我们完成的。

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

由于模态对话框通常是一个短期的 object,通常作为堆栈上的局部变量创建,因此您通常只需将 go 放在 scope 之外,以处理所有与破坏有关的事情。

但是,无模式对话框的生命周期要求在不再需要对话框时使用DestroyWindow()方法来销毁对话框。 请参阅Microsoft 开发人员网络 - 销毁对话框

第三种使用场景——嵌入对话框

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

在上面的示例中,对话框模板指定了对话框的WS_POPUP样式,这是对话框的标准样式,因为使用对话框的正常方式是显示为单独的 window。

但是,如果您将WS_POPUP样式更改为WS_CHILD ,您可以将对话框嵌入到另一个 window 作为控件。 您可以删除其他样式设置,例如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()的无模式对话框。

如果您需要在其容器 window 中重新定位嵌入对话框,您可以使用SetWindowPos()方法来执行此操作。 例如,以下内容会将对话框 window 在其包含的 window 内移动到距包含 window 的左侧 20 个像素和距顶部 10 个像素的位置。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM