1.创建项目
在vs2019中选择MFC应用,点击下一步
输入项目名称后,选择存储位置,并勾选将解决方案和项目放在同一目录中,点击创建
在弹出的消息框内,选择单个文档,点击完成。
2.对话框创建
创建好项目后,在解决方案资源管理器中找到资源视图,找到其中的menu.rc,双击进入资源视图。
之后打开Dialog项,鼠标右键点击Dialog,选择添加资源,单击新建,这样一个新的对话框就创建好了。
接下来需要创建一个类与这个新建的对话框资源相关联,双击打开刚刚创建的对话框,右键窗体,选择添加类。
添加一个新类 CTestDlg,对话框选择我们之前添加的 IDD_DIALOG1
点击确定后,可以在类视图中找到新创建的CTestDlg类
现在,就有一个类(CTestDlg)与IDD_DIALOG1这个对话框资源相关联了,接下来需要在程序中显示这个对话框窗口,可以增加一个菜单项,当单击菜单项时就显示这个新的对话框窗口。
3.增加菜单项
在资源视图中找到Menu,并双击打开其下的 IDR_MAINFRAME
在帮助后面添加新的菜单栏,命名为对话框。
运行程序,得到如下窗口,可见刚刚添加的对话框也在窗口中。
接下来创建模态对话框
4.模态对话框创建
创建模态对话框需要调用CDialog类的成员函数:DoModal
首先到刚刚创建的菜单栏“对话框”处,鼠标右键点击“对话框”,选择添加事件处理程序选项。
在弹出来的窗口中选择xxxView类,消息类型选择COMMAND,这样就完成了对消息框的配置,只需要在VS自动生成的代码中配置创建模态对话框即可。
由于在视类中并不知道CTestDlg对话框是什么样是数据类型,所以在View的源文件中必须包含CTestDlg的头文件。
void CChildView::OnDialog()
{
// TODO: 在此添加命令处理程序代码
CTestDlg dlg;
dlg.DoModal();
}
运行之后即可出现对话框。
5.非模态对话框创建
如果要创建非模态对话框,则需要利用CDialog类的Create成员函数。
void CChildView::OnDialog()
{
// TODO: 在此添加命令处理程序代码
CTestDlg dlg;
//dlg.DoModal();
dlg.Create(IDD_DIALOG1, this);//第一个参数可以是对话框的ID也可以是对话框模板的名称 第二个参数制定了对话框的父窗口
dlg.ShowWindow(SW_SHOW);//当利用Create函数创建非模态对话框时,还需要调用ShowWindow函数将对话框显示出来
}
上述程序在运行时,对话框出现的情况是一闪而过。因为此时的dlg是一个局部对象,当执行完OnDialog函数时,dlg的生命周期也就结束了。
针对上述问题,有以下两种方法:
1.把对话框对象定义为视类成员变量;
2.将它定义为指针
方法1
在视类的.h头文件中添加如下代码:
private:
CTestDlg dlg;
并添加对CTestDlg.h的引用
然后将void CChildView::OnDialog()函数中的CTestDlg dlg;语句注释掉即可。
void CChildView::OnDialog()
{
// TODO: 在此添加命令处理程序代码
//CTestDlg dlg;
//dlg.DoModal();
dlg.Create(IDD_DIALOG1, this);//第一个参数可以是对话框的ID也可以是对话框模板的名称 第二个参数制定了对话框的父窗口
dlg.ShowWindow(SW_SHOW);//当利用Create函数创建非模态对话框时,还需要调用ShowWindow函数将对话框显示出来
}
这样运行代码之后对话框就可以完整显示。
但上述代码仍存在问题,对话框显示之后,如果点击确定对话框会消失,但是如果再次打开对话框程序就会崩溃。这是因为非模态对话框在单击OK后并没有被销毁而是隐藏起来了,因此,对于非模态对话框来说,如果有一个ID为IDOK的按钮,就必须重写基类的OnOK这个虚函数,并在重写的函数中调用DestoryWindows函数,以销毁对话框。
在资源视图中打开之前创建的对话框,双击确定和取消按钮,VS会自动生成点击他们的代码
void CTestDlg::OnBnClickedCancel()
{
// TODO: 在此添加控件通知处理程序代码
CDialog::OnCancel();
}
在其中加入DestoryWindows函数
void CTestDlg::OnBnClickedCancel()
{
// TODO: 在此添加控件通知处理程序代码
CDialog::OnCancel();
DestroyWindow();
}
这样再运行代码,点击确定和取消再打开对话框程序就不会崩溃。
方法2
将其定义为指针
void CChildView::OnDialog()
{
// TODO: 在此添加命令处理程序代码
CTestDlg *dlg= new CTestDlg;
//dlg.DoModal();
dlg->Create(IDD_DIALOG1, this);//第一个参数可以是对话框的ID也可以是对话框模板的名称 第二个参数制定了对话框的父窗口
dlg->ShowWindow(SW_SHOW);//当利用Create函数创建非模态对话框时,还需要调用ShowWindow函数将对话框显示出来
}
最后需要在CTestDlg类中重载PostNcDestroy虚函数,释放this指针所指向的内存(需要在.h中声明PostNcDestroy函数)
void CTestDlg::PostNcDestroy()
{
CDialog::PostNcDestroy();
delete this;
}
(参考孙鑫老师《VC++深入详解》)