MFC 如何添加快捷键
添加的函数:
2 hAccel = LoadAccelerators(AfxGetresourceHandle(),MAKEINRESOURCE(IDR_ACCELERATOR1));
3
4 BOOL CtestDlg::PreTanslateMessage(MSG* pMsg)
5 {
6 if(WM_KEYFIRST<=pMsg->message && pMsg->message <= WM_KEYLAST)
7 {
8 if(hAccel && ::TranslateAccelerator(m_hWnd,hAccel,pMsg))
9 return TRUE;
10 }
11 return CDialog::PreTranslateMessage(pMsg);
12 }
// 解释说明
MFC对话框不自动处理加速键,你必须自己编写代码来做这件事情。为了理解弄清楚这是为什么,让我们回首Windows开发的历程,
在使用C和原始的Windows API的年代,每一个Windows程序中都有一个叫做消息泵的中枢循环:
while (GetMessage(...)) {
TranslateMessage(...);
DispatchMessage(...);
}
在这里细节不是最重要的,最重要的是消息并不到达程序的流程,你必须请求消息。这是一种人为的非抢先式多任务方法,这种方法通过每一个任务精诚协作来仿造多任务环境,随着增加的功能越来越多,有人想到了加速键表的主意,这个表用来映射按键和命令IDs。为了实现这个目的,微软发明了一个叫TranslateAccelerator()的函数。现在这个消息泵变成了如下的样子:
while (GetMessage(...)) {
if (TranslateAccelerator(hAccel...)) {
// handled, continue looping
} else {
TranslateMessage(...);
DispatchMessage(...);
}
}
hAccel是个加速键表句柄,在这里细节同样不是重要的,重要的是如何利用加速键表,也就是要有一个专门的函数将按键消息解释为WM_COMMAND消息。TranslateAccelerator()函数寻找WM_KEYDOWN,WM_CHAR,WM_KEYUP序列与表中键值匹配的字符。如果找到,它插入一条WM_COMMAND到消息队列,在消息队列中的命令ID可以是加速键表定义的任何入口。这样你只要设置加速键表(在资源中)并记住调用对应的函数TranslateAccelerator(),就什么都不用担心了。
随着Visual C++和MFC的日臻成熟,现在几乎整个消息循环(但不是全部)都被隐藏到了MFC中,为了能让任何窗口都有机会获得一点消息泵的行为,MFC提供了一个专门的虚函数PreTranslateMessage(),如果你有足够的勇气去探究CWinThread中的消息处理机制的话,你会遇到类似如下的代码:
// 简化后的 CWinThread
while (GetMessage(...)) {
if (PreTranslateMessage(...)) {
// continue looping
} else {
TranslateMessage(...);
DispatchMessage(...);
}
}
CWinThread::PreTranslateMessage()是个虚函数,在应用中,其缺省的实现以相同的名字调用另一个虚函数CWnd::PreTranslateMessage()。因此,如果需要在消息循环中做些什么的话,如解释加速键,只要重载PreTranslateMessage()函数即可。实际上,这就是程序的框架CFrameWnd类处理加速键的方法。
BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg)
{
......
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
{
::TranslateAccelerator(m_hAccelTable,...);
}
}
CFrameWnd类是从哪里获得加速键表呢?当加载框架时,CFrameWnd::LoadFrame()函数使用与文档模板相同的ID(如IDR_MAINFRAME)查找加速键表,并将它加载到m_hAccelTable变量中。所有的处理细节在MFC中都是自动的、隐蔽的,读者朋友不用去操心。但是上述内容仅仅是对主框架而言,如果是对话框,则是另外一种情况,因为CDialog不是从CFrameWnd派生而来,所以不继承任何有关加速键的内容。对于这个问题不用担心,我们可以模仿CFrameWnd的工作,很容易为对话框增加加速键的功能。第一步是加载加速键,加载加速键最好的地方是在对话框的OnInitDialog函数中:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
......
// Load accelerators
m_hAccel = ::LoadAccelerators(AfxGetResourceHandle(), m_lpszTemplateName);
ASSERT(m_hAccel);
return TRUE;
}
在加速键表中,可以使用任何ID。例如上面的代码使用的是对话框本身的ID,(m_lpszTemplateName既可以是一个串名,也可以是一个MAKEINTRESOURCE使用的整型ID)。
// 本文例子中的加速键(In DlgKeys.rc )
IDD_MYDIALOG ACCELERATORS DISCARDABLE
BEGIN
VK_RETURN, ID_MY_ENTER, VIRTKEY, NOINVERT
END
一旦已经加载加速键,剩下的事情是重载PreTranslateMessage函数,进行消息映射了:
BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
{
HACCEL hAccel = m_hAccel;
if (hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg))
return TRUE;
}
return CDialog::PreTranslateMessage(pMsg);
}
之所以要检查按键类的消息(从WM_ KEYFIRST 到 WM_KEYLAST)是为了提高速度。如果你知道不是一个按键消息,你就不用浪费时间去调用TranslateAccelerator()。再说TranslateAccelerator()是一个虚拟函数,不用增加一个消息映射入口。仅仅写这个函数就可以了。
添加的函数:
2 hAccel = LoadAccelerators(AfxGetresourceHandle(),MAKEINRESOURCE(IDR_ACCELERATOR1));
3
4 BOOL CtestDlg::PreTanslateMessage(MSG* pMsg)
5 {
6 if(WM_KEYFIRST<=pMsg->message && pMsg->message <= WM_KEYLAST)
7 {
8 if(hAccel && ::TranslateAccelerator(m_hWnd,hAccel,pMsg))
9 return TRUE;
10 }
11 return CDialog::PreTranslateMessage(pMsg);
12 }
// 解释说明
MFC对话框不自动处理加速键,你必须自己编写代码来做这件事情。为了理解弄清楚这是为什么,让我们回首Windows开发的历程,
在使用C和原始的Windows API的年代,每一个Windows程序中都有一个叫做消息泵的中枢循环:
while (GetMessage(...)) {
TranslateMessage(...);
DispatchMessage(...);
}
在这里细节不是最重要的,最重要的是消息并不到达程序的流程,你必须请求消息。这是一种人为的非抢先式多任务方法,这种方法通过每一个任务精诚协作来仿造多任务环境,随着增加的功能越来越多,有人想到了加速键表的主意,这个表用来映射按键和命令IDs。为了实现这个目的,微软发明了一个叫TranslateAccelerator()的函数。现在这个消息泵变成了如下的样子:
while (GetMessage(...)) {
if (TranslateAccelerator(hAccel...)) {
// handled, continue looping
} else {
TranslateMessage(...);
DispatchMessage(...);
}
}
hAccel是个加速键表句柄,在这里细节同样不是重要的,重要的是如何利用加速键表,也就是要有一个专门的函数将按键消息解释为WM_COMMAND消息。TranslateAccelerator()函数寻找WM_KEYDOWN,WM_CHAR,WM_KEYUP序列与表中键值匹配的字符。如果找到,它插入一条WM_COMMAND到消息队列,在消息队列中的命令ID可以是加速键表定义的任何入口。这样你只要设置加速键表(在资源中)并记住调用对应的函数TranslateAccelerator(),就什么都不用担心了。
随着Visual C++和MFC的日臻成熟,现在几乎整个消息循环(但不是全部)都被隐藏到了MFC中,为了能让任何窗口都有机会获得一点消息泵的行为,MFC提供了一个专门的虚函数PreTranslateMessage(),如果你有足够的勇气去探究CWinThread中的消息处理机制的话,你会遇到类似如下的代码:
// 简化后的 CWinThread
while (GetMessage(...)) {
if (PreTranslateMessage(...)) {
// continue looping
} else {
TranslateMessage(...);
DispatchMessage(...);
}
}
CWinThread::PreTranslateMessage()是个虚函数,在应用中,其缺省的实现以相同的名字调用另一个虚函数CWnd::PreTranslateMessage()。因此,如果需要在消息循环中做些什么的话,如解释加速键,只要重载PreTranslateMessage()函数即可。实际上,这就是程序的框架CFrameWnd类处理加速键的方法。
BOOL CFrameWnd::PreTranslateMessage(MSG* pMsg)
{
......
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
{
::TranslateAccelerator(m_hAccelTable,...);
}
}
CFrameWnd类是从哪里获得加速键表呢?当加载框架时,CFrameWnd::LoadFrame()函数使用与文档模板相同的ID(如IDR_MAINFRAME)查找加速键表,并将它加载到m_hAccelTable变量中。所有的处理细节在MFC中都是自动的、隐蔽的,读者朋友不用去操心。但是上述内容仅仅是对主框架而言,如果是对话框,则是另外一种情况,因为CDialog不是从CFrameWnd派生而来,所以不继承任何有关加速键的内容。对于这个问题不用担心,我们可以模仿CFrameWnd的工作,很容易为对话框增加加速键的功能。第一步是加载加速键,加载加速键最好的地方是在对话框的OnInitDialog函数中:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
......
// Load accelerators
m_hAccel = ::LoadAccelerators(AfxGetResourceHandle(), m_lpszTemplateName);
ASSERT(m_hAccel);
return TRUE;
}
在加速键表中,可以使用任何ID。例如上面的代码使用的是对话框本身的ID,(m_lpszTemplateName既可以是一个串名,也可以是一个MAKEINTRESOURCE使用的整型ID)。
// 本文例子中的加速键(In DlgKeys.rc )
IDD_MYDIALOG ACCELERATORS DISCARDABLE
BEGIN
VK_RETURN, ID_MY_ENTER, VIRTKEY, NOINVERT
END
一旦已经加载加速键,剩下的事情是重载PreTranslateMessage函数,进行消息映射了:
BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
{
HACCEL hAccel = m_hAccel;
if (hAccel && ::TranslateAccelerator(m_hWnd, hAccel, pMsg))
return TRUE;
}
return CDialog::PreTranslateMessage(pMsg);
}
之所以要检查按键类的消息(从WM_ KEYFIRST 到 WM_KEYLAST)是为了提高速度。如果你知道不是一个按键消息,你就不用浪费时间去调用TranslateAccelerator()。再说TranslateAccelerator()是一个虚拟函数,不用增加一个消息映射入口。仅仅写这个函数就可以了。
MFC 如何添加快捷键相关推荐
- MFC程序添加快捷键
MFC里使用快捷键的原理:按键组合成一个COMMAND/COMMAND_UI消息放入消息队列,然后程序对该消息进行处理. 1.添加Accelerator表(按键组合与消息的对应表) 编辑Acceler ...
- C# WinForm给Button按钮或其它控件添加快捷键响应
就在这介绍三种添加快捷键的方式. 第一种Alt + *(按钮快捷键) 在大家给button.label.menuStrip等控件设置Text属性时在名字后边加&键名就可以了,比如button1 ...
- vs2017开发ActiveX(主讲OCX)(十一)、类向导中MFC ActiveX添加方法、添加函数、添加变量、添加事件、添加属性、添加方法的区别
本文我们就来说说类向导中MFC ActiveX添加方法.添加函数.添加变量.添加事件.添加属性.添加方法的区别.这个问题曾经困扰过我. 此处是向CCreateOcxDemoApp类中添加成员变量,及成 ...
- 【Windows】回收站添加快捷键B
引言 win7 的回收站绑定的有快捷键 B,鼠标右击回收站并按下键盘上的 B,即可快速清空回收站,而 win10 或 win11 等取消了这一快捷键.上一篇文章中,已经教会了大家如何给右键菜单添加快捷 ...
- idea常用快捷键图文_如何在Word中的自动图文集词条中添加快捷键
idea常用快捷键图文 AutoText entries are reusable chunks of text you can insert into documents using just a ...
- 给网页的按钮添加快捷键
在使用windows应用程序的过程中我们都知道,很多按钮不需要我们点击鼠标选择,只需要按Alt+字母就能直接访问了,是不是很专业呢?其实这在网页当中一样能实现,不知道您以前是否注意过. 要实现这样的功 ...
- dw cc 2019如何为命令添加快捷键
dw cc 2019 Mac是一款使用广泛的网页设计软件,丰富的网页设计工具,简化的编码引擎,可以更快的实现网站设计.编码和发布,为命令添加快捷,可以提高Dreamweaver CC 2019 for ...
- Typora:修改高亮字体的样式和添加快捷键
我想在文档中高亮显示关键字,搜了一些教程,主要有[安装AutoHotKey].[使用html代码]和[使用内联样式]等方法. 但本着不想装多余软件.尽可能的方便快捷的原则,我最后选择了修改主题的css ...
- word 给设定样式添加快捷键
word 给设定样式添加快捷键 1.格式>样式 样式窗口 2.修改 修改样式窗口 选择添加到模板,这样之后默认打开文档都可以使用这些快捷键. 3.格式>快捷键 自定义键盘窗口 指定新的快捷 ...
最新文章
- ElasticSearch是什么?为什么快?倒排索引是什么?ElasticSearch的应用?
- CentOS系统设置开机自启动
- html显示php值,HTML窗体加载显示通过PHP的十六进制值
- matplotlib基础函数函数 plot, figure
- 了解JavaScript中的循环缺点和迭代协议
- gitee创建ssh公钥
- vim粘贴后格式错乱解决办法
- freeswitch安装步骤(源码编译安装)
- (一)hadoop 权威指南---气象数据获取
- 一图读懂3GPP R16(附思维导图下载)
- nas文件服务器 迁移,换新机器啦,超简单NAS数据迁移方法
- 拼图复原_玩过上百款拼图后,我总结出这份超详细的拼图年龄对照表!(收藏贴)...
- LM4890功放电路的分析
- 如何在WordPress中显示链接的实时预览
- HTML5网页设计制作基础大二dreamweaver作业、使用HTML+CSS技术制作博客网站(5个页面)...
- 域用户登录方法在计算机上不被允许,域管理员不允许本地交互式登陆的解决方法...
- 适合设计电话号码的一款字体
- 【闲谈】我为什么不想回答你的问题
- 2022最新HTML生成国庆头像网页源码+打开即用
- 论文的正确打开方式—如何细读一篇论文分享
热门文章
- struts2文件上传和下载
- odoo:开源 ERP/CRM 入门与实践 -- 上海嘉冰信息技术公司提供咨询服务
- continue在c语言中什么作用,continue在c语言中什么意思?
- Windform C# Graphics绘图,消除锯齿
- 【二维码】艺术二维码生成
- 旷视科技 CVPR部分文章
- 通用人工智能:我们还有多远?
- 读书笔记-别做正常的傻瓜
- 服务器开通网站来宾帐户,IIS 增加Internet来宾用户权限
- 解决:return _compile(pattern, flags).search(string) TypeError: expected string or buffer