[MFC] 创建(非)模态对话框以及可能出现的问题

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指针失效,因此,再次运行创建时,程序会直接崩溃。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yy_xzz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值