MFC去掉ESC和回车键退出的方法

本文详细介绍了如何在Windows应用程序中通过重载PreTranslateMessage函数来取消按ESC和Enter键后程序退出功能,并演示了如何使回车键响应特定控件(如编辑框)。此外,提供了将回车后光标放置在当前编辑框或当前对话框上的代码示例。

重载PreTranslateMessage函数:

在Class Wizard里,重载该函数,要重载哪个类就选该类下的Virtual Functions:

重载PreTranslateMessage函数如下:

BOOL CPIToolDlg::PreTranslateMessage(MSG* pMsg)
{
	// TODO: Add your specialized code here and/or call the base class

	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) return TRUE;
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) return TRUE;

	return CDialogEx::PreTranslateMessage(pMsg);
}

上面代码就是取消按 ESC 和 Enter 键后程序退出功能。

如果要回车键相应某个控件(如编辑框的相应),参考如下:

BOOL CConfigure::PreTranslateMessage(MSG* pMsg)
{
	if ((WM_KEYFIRST <= pMsg->message) && (pMsg->message<=WM_KEYLAST))
	{
		if (pMsg->wParam == VK_RETURN)
		{
			HWND hWnd = ::GetFocus();
			int iID = ::GetDlgCtrlID(hWnd);
			if (iID == IDC_EDIT_CFGDATA)
			{
				CString sData;
				sData.Empty();
				int lenData = 0;
				GetDlgItemText(IDC_EDIT_CFGDATA,sData);
				sData += "\r\n";
				SetDlgItemTextA(IDC_EDIT_CFGDATA,sData);
				lenData = sData.GetLength();
				((CEdit*)GetDlgItem((IDC_EDIT_CFGDATA))) -> SetSel(lenData,lenData);
			}	
			else
				::SetFocus(hWnd);
			return TRUE;
		}
	}
	return FALSE;
}

上例中,将回车后的光标放置在当前编辑框控件上,如果要将光标放置在当前对话框上,不要在某个控件上,只需将else下面的::SetFocus(hWnd)更改为::SetFocus(m_hWnd)即可。

hWnd是自己定义获取的控件句柄,m_hWnd是系统自带固定的句柄。
 

参考:不能响应回车键的原因分析_Phenixyf的博客-优快云博客

<think>我们正在讨论的是在VS2017 MFC对话框中取消ESC键的默认退出功能。根据用户引用之前的回答,有几种方法可以实现。用户特别关注如何禁止ESC退出程序。 从引用内容来看: 引用[1][2]提到可以通过重载PreTranslateMessage函数来屏蔽ESC键。 引用[3]提到可以通过重写OnCancel函数(并去掉基类调用)来阻止ESC退出。 因此,我们可以提供两种方法方法一:重载PreTranslateMessage函数(在消息预处理阶段拦截ESC键) 步骤: 1. 在对话框类中,通过类向导(Class Wizard)重载PreTranslateMessage虚函数。 2. 在PreTranslateMessage函数中添加对ESC键的拦截。 示例代码: ```cpp BOOL CYourDialog::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) { return TRUE; // 拦截ESC键,不传递给默认处理 } return CDialogEx::PreTranslateMessage(pMsg); } ``` 方法二:重写OnCancel函数(阻止默认的取消行为) 步骤: 1. 在对话框类中,通过类向导重写OnCancel虚函数。 2. 在OnCancel函数中,不调用基类的OnCancel(即注释掉CDialogEx::OnCancel()),这样ESC键按下时就不会关闭对话框。 示例代码: ```cpp void CYourDialog::OnCancel() { // 这里可以什么都不做,或者添加自定义处理 // 注意:一定不要调用基类的OnCancel,否则对话框仍会关闭 // CDialogEx::OnCancel(); } ``` 两种方法的比较: - 方法一:在消息预处理阶段就拦截了ESC键,所以ESC键不会触发OnCancel函数。 - 方法二:允许ESC键触发OnCancel函数,但我们在OnCancel中阻止了关闭操作。 根据用户需求(禁止ESC退出程序),两种方法都可行。但需要注意: - 如果希望完全屏蔽ESC键(即ESC键按下后不做任何事情),使用方法一。 - 如果希望在ESC键按下时执行一些自定义操作(但不关闭对话框),使用方法二。 此外,引用[3]还提到,如果没有重写OnOK函数,则Enter键会调用OnOK函数导致对话框关闭。同理,我们可以用类似方法处理Enter键(如果需要): - 重载PreTranslateMessage函数拦截Enter键(VK_RETURN) - 或者重写OnOK函数并去掉基类调用。 现在,针对用户的问题(禁止ESC退出程序),我们给出详细步骤(以方法一为例,因为方法一可以同时处理多个按键,且拦截更早): 步骤详解(方法一): 1. 打开类向导:在VS2017中,打开对话框类的头文件,右键选择“类向导”(Class Wizard)。 2. 在“虚函数”选项卡中,找到“PreTranslateMessage”,点击“添加函数”。 3. 编辑生成的函数,添加上述代码。 注意:如果对话框基类是CDialog,则基类函数为CDialog::PreTranslateMessage;如果是CDialogEx,则为CDialogEx::PreTranslateMessage。 如果使用方法二,步骤类似: 1. 在类向导的“虚函数”选项卡中,找到“OnCancel”,添加函数。 2. 在函数体中不调用基类的OnCancel。 最后,考虑到用户可能还需要禁用其他按键(如F1)或者自定义按键功能,我们可以在相关问题中列出。 生成的相关问题: 1. 如何同时禁用ESCEnter键的默认关闭功能? 2. 如何在MFC对话框中为ESC键设置自定义功能? 3. 如何禁用Alt+F4关闭MFC对话框? 4. 如何在MFC对话框中添加自定义热键(如Ctrl+S)? 5. 如何恢复被禁用的默认对话框按键功能? 注意:在回答中,我们引用了用户提供的引用[1][2][3],在末尾添加引用标识。 </think>### VS2017 MFC项目中禁止ESC退出程序的两种方法 根据引用内容[1][2][3],禁止ESC退出程序主要有以下两种实现方案: #### ✅ 方法一:重载PreTranslateMessage函数(推荐) ```cpp BOOL CYourDialog::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) { return TRUE; // 直接拦截ESC键消息 } return CDialogEx::PreTranslateMessage(pMsg); } ``` **实现步骤**: 1. 在解决方案资源管理器中右击对话框类 → 选择"类向导" 2. 在"虚函数"选项卡中找到`PreTranslateMessage` → 点击"添加函数" 3. 在生成的函数中添加上述拦截代码 4. 编译运行后,ESC键将被完全禁用[^1][^2] #### ✅ 方法二:重写OnCancel虚函数 ```cpp void CYourDialog::OnCancel() { // 1. 完全禁用退出: // 空实现(不调用基类方法) // 2. 自定义功能(示例): // if(MessageBox("确定要执行自定义操作吗?", "提示", MB_YESNO) == IDYES) // { // // 添加自定义逻辑 // } } ``` **实现步骤**: 1. 在类向导的"虚函数"选项卡中选择`OnCancel` 2. 点击"添加函数"生成重写 3. **关键**:删除或注释掉`CDialogEx::OnCancel()`调用 4. 按需添加自定义逻辑或保持空实现[^3] --- ### 两种方案对比 | **特性** | 方法一 (PreTranslateMessage) | 方法二 (OnCancel) | |----------------|----------------------------------|--------------------------------| | 拦截阶段 | 消息预处理阶段(更早) | 命令执行阶段 | | 代码侵入性 | 低 | 中 | | 自定义扩展 | 可添加按键响应逻辑 | 可替换为自定义功能 | | 适用场景 | 需完全禁用ESC键 | 需改变ESC键行为 | > ⚠️ **重要提示**: > 若同时存在`OnCancel``PreTranslateMessage`实现,优先执行`PreTranslateMessage`。推荐使用方法一,因其能更彻底地阻止ESC键的默认行为[^2][^3]。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值