s1、创建新项目
s2、资源视图找Dialog 右键 插入 生成一个新的Dialog 重复操作 再生成一个
s3、主Dialog拖两个button
s4、创建模态对话框 双击创建第一个button
注意点1
此处,创建一个名为 dlg
的 CDialog
对象,并关联到资源标识符ID为 IDD_DIALOG1
的对话框模板。进而可以使用 dlg
对象的方法和属性进行对话框的操作,显示对话框。DoModal()
方法会将对话框(dlg
)作为模态对话框显示。
由于模态窗口程序会停留在dlg.DoModal()处,因此dlg对象不会在窗口关闭前销毁!!!!(区别于非模态)
运行测试一下。
s5、给模态窗口添加类
注意点2
此处基类可选CDialogEx或者CDialog,
CDialogEx是VS2003之后出现的,VC++6.0没有。这个类是CDialog的扩展类,基类就是CDialog.
但是,如果主窗口类继承的是CDialog,CMoTi类继承CDialogEx,运行可能会报错。全部修改为ex即可。
非以上情况不会报错。
s6、修改之前的Button响应事件代码
运行测试一下
s7、有了类之后 可以为对话框添加交互操作
拖一个编辑框,右键窗口选择类向导 虚函数
在虚函数中添加初始化 爆红不影响运行 强迫症患者可以添加一下头文件resource.h
测试一下
s8、开始操作非模态窗口
添加编辑框 右键窗口 添加类
s9 、双击 创建非模态的Button
添加代码(可改进,重复点击创建button会出错,可在添加类成员isCreate(Bool)避免。)
注意点3
类对象fmt_dlg需要定义在函数外部,由于非模态窗口在代码运行时不会阻塞,因此如果对象创建在内部则会被瞬间销毁。窗口闪退。如下图(错误示范).
注意点4 非模态窗口重复创建时报错
如下图,已经创建了一个非模态窗口,再次创建时,异常。原因:一个对象只能create一个。
在MFC中,通过调用Create()
方法来创建一个对话框实例。但是,每个对话框实例在创建后只能显示一次。尝试再次调用Create()
方法创建同一对话框的实例会引发错误。
如果代码中出现了两次调用fmt_dlg.Create(IDD_DIALOG2)
的情况,第二次调用会导致程序抛出异常或者错误。这是因为第一个对话框实例已经创建并显示,无法再次创建。
如果需要在程序运行过程中多次显示同一对话框,可以考虑使用DoModal()
方法代替Create()
方法。DoModal()
方法会一直执行,直到对话框被关闭,然后程序可以再次调用DoModal()
方法以显示对话框。
另外,如果你确实需要创建多个相同类型的对话框实例,可以考虑使用不同的变量来保存和管理每个实例。比如,声明多个对话框类的对象,分别创建和显示不同的实例。
总之,要避免多次调用Create()
方法来创建同一对话框的实例,因为这样会导致错误。
s10、修改代码
由于使用了new,需要在程序结束时delete,回收资源。
在非模态dialog右键->类向导 添加虚函数
注意点5 PostNcDestroy()
虚拟函数,用于在对话框销毁后执行一些清理操作。
当一个对话框被销毁时(比如对话框关闭),MFC 框架会自动调用 PostNcDestroy()
函数。该函数会在对话框的非客户区(non-client area)销毁后立即被调用,用于执行一些善后工作,比如释放资源、删除对象等。
s11、重写PostNcDestroy()函数
s12、添加DestroyWindow()函数(此处不建议添加,添加会报错 TODO:待改进)
DestroyWindow()函数是一个Windows API函数,用于销毁指定的窗口。当调用该函数时,它会向窗口发送WM_DESTROY消息来使窗口失效,并从窗口中移除键盘焦点。此外,该函数还会销毁窗口的菜单、定时器,移除剪贴板所有权,并打破剪贴板查看器链(如果该窗口位于查看器链的顶部)。在非模态对话框下,调用OnOk()或者OnCancel函数(EndDialog)不会触发WM_DESTROY消息,因此不会调用上述函数。这也是为什么很多书籍上强调无模态对话框不要调用OnOk()或者OnCancel函数来销毁而要调用DestroyWindow函数来销毁的原因。
注意点6 添加后,以上程序会崩溃,原因在于:
#include "CFMoTiDlg.h"
void CDialogCreatePraDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
static CFMoTiDlg* pfmt_dlg = NULL;
if (!pfmt_dlg) {
pfmt_dlg = new CFMoTiDlg;
pfmt_dlg->Create(IDD_DIALOG2,this);
}
pfmt_dlg->ShowWindow(SW_SHOW);
}
该段代码中,我们静态声明了一个指针变量,首次运行时指向CFMoTiDlg类new的一段内存地址,当关闭一个非模态窗口时, DestroyWindow()函数回收所有该类的资源,pfmt_dlg指针失效,因此,再次运行创建时,程序会直接崩溃。