1、启动VS2017软件,然后新建一个名为“MFCDemo1”的对话框MFC应用程序。当MFC对话框程序创建完毕后,点击VS2017工具栏上的“本地Windows调试器按钮”编译运行该程序;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/ff5c88d818196120d008ccda70f202b374d7df19.jpg)
3、在MFC创建的对话框中,按下“ESC键”退出(关闭)对话框属于默认行为。这一点对于非主窗口的对话框而言,是非常好的功能,但是对于充当主窗口的对话框则属于BUG(测试时对主窗口按“ESC”是最基本的测试项);
4、关闭“MFCDemo1对话框”返回到VS2017界面中,展开“解决方案资源管理器”中的“MFCDemo1项目”,在其“资源文件”目录下,找到“MFCDemo1.rc”文件并双击打开;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/50a010f85856d53d22e1185d47d2bb665059ca19.jpg)
6、双击对话框资源编辑界面中的“确定按钮”,为该按钮添加“单击通知事件(BN_CLICKED)”消息响应代码(VS为我们添加了:茇坍酮踪消息响应函数声明、消息映射和消息响应函数实现的代码)。在Visual Studio中,每个控件都内定了一个默认的通知类型。只要在对话框资源编辑器中双击该控件,Visual Studio就会自动帮我们在对话框派生类的源代码中加入该事件的响应代码;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/35fa07efa25f0c145ebe12360d89a146b6b1381e.jpg)
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/c8373cbc7dc5cf67859a15f28e96b814f5d0261e.jpg)
7、在VS中开发MFC程序时,添加消息响应函数的工作通过VS完成是最便利的途径。但是,前提是你必须要懂它的基本逻辑。VS提供的种种便利,仅仅只是为了让我们提高开发效率,懂原理仍然是我们需要努力的方向;
8、回到“MFCDemo1Dlg.罕铞泱殳cpp”文件中,将OnBnClickedOk()函数中的”CDialog:多唉捋胝:OnOk()”语句注释掉。这样,点击“确定按钮”应该就没有任何反应了。这里可以验证一下:保存修改后的代码,然后调试运行程序。在弹出的对话框中点击“确定按钮”,确定对话框并没有关闭;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/cf6d451b1edef4dc68fcd3ab45ecd3d968750c1e.jpg)
9、结束程序调试,返回到VS2017界面。然后按照同样的方法,为“取消按钮”添加默认的“单击通知事件”响应函数。同时,在该函数的响应代码中,注释掉“CDialog::OnCancel();”语句;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/bf6e59704618dfda3bfefb3289214f579256771e.jpg)
11、返回到“C怡觎现喾MFCDemo1Dlg”的资源标记窗口中,点击对话框标题栏或者对话框外的空白处将其选中,然后打开“属性面板”(没有的话请通过“视图 > 其他轻拔吴悃窗口 > 属性窗口”(或者ALT + Enter)将其打开,定制VS开发界面请参考引用的文章)。点击面板工具栏中的“消息按钮”打开所选目标(对话框)支持响应的消息列表,从中找到“WM_CLOSE”(关闭按钮被点击时就会发送这个消息),然后通过其右侧的下拉列表,选择“<Add> OnClose”,添加WM_CLOSE消息的响应函数;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/031231632385e0361854875cb8e039723c035a1e.jpg)
13、通过以上的尝试可知,CDialog::OnClose()函数中并没有调用结束对话框的操作,即调用WinAPI函数EndDialog()。这个函数应该是由OnOK()和OnCancel()调用的。为了确定这一点,可以看看MFC的源代码(安装VS2017企业版时,已经给了MFC源码);
14、右键单击调用的“OnOK()函数”,在弹出菜单中,选择“转到定义”,跳转到该函数的定义。可惜,由于当前项目中不存在该函数的源码。VS仅仅只是给出了该函数的所在的头文件列表。注意,我们实际要找的是“CDialog::OnOk()”,查看“查找符号结果”列表,可以确定这个头文件所在的文件目录;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/27725684cde34b2c4528bbcb0d0e7c75e4f4431e.jpg)
15、根据头文件的目录,在磁盘上找到MFC的源代码目录。进入该目录后,通过“文件夹选项”,选择“始终搜索文件名和内容”;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/777f3fc2bbd6e1d04a2e5ad50d254193cfe8af1e.jpg)
17、在打开的“dlgcore.cpp”源码中,查看“OnOk”和“OnCancel”函墙绅褡孛数的实现代码。发禊耗髻编现这两个函数中都调用了“CDialog::EndDialog()”方法。跳转到“CDialog::EndDialog()”的定义代码中,可以见到它最终是调用WinAPI中的“EndDialog()”函数关闭对话框的;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/4080a927ac530688afea657e57e8904801fc961e.jpg)
18、查看CDialog源码中的消息映射代码,你会发现CDialog默认响应ID为“IDOK”和“IDCANCEL”的控件发送的消息;
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/95bd4e8c9bcec7f8d1b19d69034ce54a2e27fb1e.jpg)
![[MFC开发经验(1)] 禁用ESC键关闭对话框[TZZ]](https://exp-picture.cdn.bcebos.com/979906196120a7cd74a83b4689b375d7987bdc1e.jpg)
20、最后总结一下,去掉对话框默认的ESC关闭功能,只需要在对话框派生类中重载一个空的OnCancel()响应函数,然后响应WM_CLOSE消息,在其处理函数中调用CDialog::OnOk()或CDialog::OnCancel()或EndDialog(0)即可。Enjoy!