C++ MFC DoModal 对话框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6528694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:19:04  来源:igfitidea点击:

MFC DoModal Dialog

c++mfc

提问by Russbear

Okay, so I will admit I have no knowledge of windows API or even MFC.

好的,所以我承认我对 Windows API 甚至 MFC 一无所知。

I've got an error window popping up when things go hairy (illegal character in a filename string) and I want the error box to be modal.

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

For the life of me I can't figure out why it crashes when it hits doModal.

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

Here is the code where I think this can be fixed. This code is in the event handler of a button in the main window.

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

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

Am I just being borderline retarded?

我只是边缘性智障吗?

回答by Jerry Zhang

MFC dialog divides two pattern, modal dialog and modeless dialog.

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

(1) Modal dialog usage:

(1) 模态对话框用法:

CDialog dlg;
dlg.DoModal();

(2) Modeless dialog usage:

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

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

As you can see, we need new a pointer, but not delete it. So you need to do the following in our CMyDialgclass:

如您所见,我们需要 new 一个指针,而不是删除它。所以你需要在我们的CMyDialg类中做到以下几点:

  1. Add DestroyWindow()methed in OnOk()and OnCancel().
  2. Add "delete this;" in PostNcDestroy()method.
  1. DestroyWindow()OnOk()和 中添加方法OnCancel()
  2. delete this;PostNcDestroy()方法中添加“ ” 。

If you do not, your code may cause a memory leak. BadFileDis a class member, and you delete in destructor. I suggest use Modeless dialog.

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

回答by Victor

For display modal dialog you should use DoModal method only

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

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

You can read remarks from article

您可以阅读文章中的评论

回答by Richard Chambers

If you desire to just display an error message, it may be that rather than creating your own dialog you can just use AfxMessageBox(). See Microsoft Developer Network - AfxMessageBox.

如果您只想显示错误消息,那么您可以使用AfxMessageBox(). 请参阅Microsoft 开发人员网络 - AfxMessageBox

If you want to do your own dialog box typically with an MFC project you would normally:

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

  • create a dialog box template using the resource editor
  • create a class encapsulating the dialog box with the class wizard implementing the behavior desired
  • insert the code to create and display the dialog box into the appropriate place
  • 使用资源编辑器创建对话框模板
  • 创建一个类封装对话框,类向导实现所需的行为
  • 在适当的地方插入创建和显示对话框的代码

However with a simple dialog box that requires no supporting class for complex behavior you can skip the step of creating the encapsulating class with the class wizard and just use CDialogdirectly.

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

One question that needs to be answered is the lifetime of the dialog as well as whether it is to be modal or modeless. A modal dialog box requires the user to do something for the application to continue past the modal dialog box. A modeless dialog box does not block the application the way a modal dialog box does. There is also a system modal dialog box style.

需要回答的一个问题是对话的生命周期以及它是模态的还是非模态的。模态对话框要求用户为应用程序执行某些操作以继续通过模态对话框。无模式对话框不会像模式对话框那样阻塞应用程序。还有一个系统模态对话框样式。

Since you say it will be a modal dialog then the lifetime will be short so the entire construction, display, and destruction will probably be in a series of lines of code. For instance in a CViewclass with a command handler displaying a modal dialog box you might have:

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

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

What the above does is create a dialog box using the dialog resource template IDD_STATUSand displays it as a modal dialog box. Since it is local object, when the variable BadFileDgoes out of scope, the dialog box destructor will be triggered and resources cleaned up for you.

上面所做的是使用对话框资源模板创建一个对话框IDD_STATUS并将其显示为模态对话框。由于它是本地对象,当变量BadFileD超出范围时,将触发对话框析构函数并为您清理资源。

You can also have a modeless dialog box. In the case of a modeless dialog box you need to consider the variable lifetime because as soon as the variable goes out of scope, the destructor will trigger and the dialog box will disappear.

您还可以拥有一个无模式对话框。在无模式对话框的情况下,您需要考虑变量生命周期,因为一旦变量超出范围,析构函数就会触发,对话框就会消失。

So for a modeless dialog box being used with some view class, perhaps providing a tool box of some kind, the CDialogvariable will be a member of the CViewclass which is using it. After the modeless dialog box is created, it is displayed or not by using the ShowWindow()member function of the CDialogclass (actually a member of the CWndclass from which CDialogis derived).

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

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

and in the CViewThingclass you would have a member variable CDialog BadFileD;.

CViewThing课堂上你会有一个成员变量CDialog BadFileD;

Additional considerations

其他注意事项

In all of the above examples we are not using pointers so that when the CDialogvariable goes out of scope, either from exiting a member function or when the object using the dialog box is destroyed then the dialog box is as well. This object management is done for us.

在上述所有示例中,我们都没有使用指针,因此当CDialog变量超出范围时,无论是退出成员函数还是使用对话框的对象被销毁时,对话框也是如此。这个对象管理是为我们完成的。

One thing that you must take into consideration with a modeless dialog box is how to destroy it when you no longer need it.

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

Since a modal dialog box is usually a short term object, often created as a local variable on the stack, you normally just let it go out of scope to take care of everything dealing with destruction.

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

However the lifetime of a modeless dialog box requires that the DestroyWindow()method be used to destroy the dialog box when it is no longer needed. See Microsoft Developer Network - Destroying the Dialog Box.

然而,无模式对话框的生命周期要求在DestroyWindow()不再需要对话框时使用该方法销毁对话框。请参阅Microsoft Developer Network - 销毁对话框

A third usage scenario - embedding a dialog box

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

There is a third usage of a dialog box that sometimes comes in handy, embedding the dialog box into another window as a control.

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

In the above examples, the dialog box template specifies the WS_POPUPstyle for the dialog which is the standard style for a dialog box since the normal way that a dialog box is used is to display as a separate window.

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

However if you change the WS_POPUPstyle to WS_CHILDyou can then embed the dialog box into another window as a control. You can remove the other style settings such as WS_SYSMENU, DS_MODALFRAME, and WS_CAPTIONand remove the CAPTIONline from the dialog template to further change the dialog box. So you will end up with something like:

但是,如果将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

Then just use the resulting dialog box similar to how you would a modeless dialog box with ShowWindow().

然后只需使用生成的对话框,类似于使用ShowWindow().

If you need to reposition the embedded dialog box within its container window, you can use the SetWindowPos()method to do so. For instance the following would move the dialog box window within its containing window to be 20 pixels from the left and 10 pixels from the top of the containing window.

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

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