PreTranslateMessage作用和使用方法
PreTranslateMessage作用和使用方法
是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。
传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。可以在该函数中使用(pMsg->wParam==VK_RETURN)来拦截回车键。wParam中存放的是键盘上字符的虚拟码。
PeekMessage和GetMessage的区别:
GetMessage在没有消息的时候等待消息,cpu当然低
PeekMessage没有消息的时候立刻返回,所以cpu占用率高。
因为游戏不能靠windows消息驱动,所以要用PeekMessage();
PretranslateMessage的实现,不得不谈到MFC消息循环的实现。MFC通过CWinApp类中的Pumpmessage函数实现消息循环,但是实际的消息循环代码位于CWinThread中,CWinApp只是从CWinThread继承过来。其简化后的代码大概如下:
BOOL CWinThread::PumpMessage()
{
_AFX_THREAD_STATE *pState = AfxGetThreadState();
::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL))
if (!AfxPreTranslateMessage(&(pState->m_msgCur)))
{
::TranslateMessage(&(pState->m_msgCur));
::DispatchMessage(&(pState->m_msgCur));
}
return TRUE;
}
可以看到,PumpMessage在实际的TranslateMessage和DispatchMessage发生之前会调用AfxPreTranslateMessage,AfxPreTranslateMessage又会调用CWnd::WalkPreTranslateTree(虽然也会调用其他函数,但是这个最为关键),其代码如下:
BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
{
ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
ASSERT(pMsg != NULL);
// walk from the target window up to the hWndStop window checking
// if any window wants to translate this message
for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
{
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL)
{
// target window is a C window
if (pWnd->PreTranslateMessage(pMsg))
return TRUE; // trapped by target window (eg: accelerators)
}
// got to hWndStop window without interest
if (hWnd == hWndStop)
break;
}
return FALSE; // no special processing
}
可以看到,代码还是很直接的。从接受到消息的窗口层层往上遍历,并调用PretranslateMessage看是否返回TRUE,是则结束,否则继续。
这里有一个地方非常关键:CWnd *pWnd = CWnd::FromHandlePermanent(hWnd) 这一句代码从当前AfxModuleThreadState拿到Permanent句柄表,从而找到hWnd对应的CWnd
MFC中PreTranslateMessage是GetMessage(...)函数的下一级操作,即GetMessage(...)从消息队列中获取消息后,交由PreTranslateMessage()处理,若其返回FALSE则再交给TranslateMessage和DispatchMessage处理(进入WindowProc);
如果用SendMessage, 则消息直接交到WindowProc处理,所以GetMessage不会取得SendMessage的消息,当然PreTranslateMessage也就不会被调用。 [Page]
如果用PostMessage,则消息进入消息队列,由GetMessage取得,PreTranslateMessage就有机会进行处理。
首先系统(也就是windows)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息 放到一个系统消息队列中去. 而应用程序需要有自己的消息队列,也就是线程消息队列,每一个线程有自己的消息队列,对于多线程的应用程序就有和线程数目相等的线程消息队列.
windows消息队列把得到的消息发送到线程消息队列,线程消息队列每次取出一条消息发送到指定窗口,不断循环直到程序退出.这个循环就是靠消息环(while(GetMessage()) TranslateMessage();DispatchMessage();实现的.GetMessage()只是从线程消息中取出一条消息,TranslateMessage()把virtue key消息转化成character消息,如VK_F1会转化成WM_HELP,而DispatchMessage 则把取出的消息发送到目的窗口.如果收到WM_CLOSE消息则结束循环,发送postqiutmessage(0),处理WM_DESTROY销毁窗口!
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
PreTranslateMessage作用和使用方法的更多相关文章
- 【转】 PreTranslateMessage作用和使用方法
PreTranslateMessage作用和使用方法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用, ...
- JAVA 注解的几大作用及使用方法详解
JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释 ...
- serialVersionUID的作用以及设置方法(转)
声明:本篇文章是转载的 http://blog.csdn.net/kakaxi_77/article/details/8129070 http://snowlotus.iteye.com/blog/2 ...
- PreTranslateMessage作用和用法
PreTranslateMessage作用和用法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用, ...
- 在Android开发中替换资源图片不起作用的解决方法
现象 在android开发中,经常会需要替换res\drawable中的图片,打开res\layout下的文件预览布局页面发现图片已经被替换,但在模拟器或者真实机器上运行时发现该图片并没有被替换,还是 ...
- Linux中PATH环境变量的作用和使用方法
关于PATH的作用:PATH说简单点就是一个字符串变量,当输入命令的时候LINUX会去查找PATH里面记录的路径.比如在根目录/下可以输入命令ls,在/usr目录下也可以输入ls,但其实ls这个命令根 ...
- PHP trim()函数的作用和使用方法
PHP trim()函数一般是用来去除字符串首尾处的空白字符(或者其他字符),一般在用在服务端对接收的用户数据进行处理,以免把用户误输入的空格存储到数据库,下次对比数据时候出错. 该函数有两个参数,第 ...
- C++ "#"的作用和使用方法
本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/48879093 1 #和##的作用和使用 ...
- header中Content-Disposition的作用与使用方法
下载文件的时候会使用: Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件.Content-disposition其实可以控制用 ...
随机推荐
- 音频处理之去噪算法---基于pcm和g711的音频16000hz、8bit去噪声算法
(1)应用背景 (2)主要降噪算法原理 (3)算法流程 (4)算法实现 (5) ------------author:pkf -------------------time:2-6 --------- ...
- shell学习五十八天----/proc文件系统
/proc文件系统 前言:linux中的/proc文件系统,由一组文件夹和文件组成,挂载(mount)与/proc文件夹下. /proc文件系统是一种虚拟文件系统,以文件系统文件夹和文件形式,提供一个 ...
- POJ3694-Network(Tarjan缩点+LCA)
题目链接 题意:给你一个连通图.然后再给你n个询问,每一个询问给一个点u,v表示加上u,v之后又多少个桥. 思路:用Tarjan缩点后,形成一棵树,所以树边都是桥了.然后增加边以后,查询LCA,LCA ...
- 使用.NET Reflector 查看Unity引擎里面的DLL文件
转载标注来源哦! 原地址在这里!在这里. 当你查看unity里面API的时候.是不是有时候追踪了一两步就碰到DLL文件走不下去了呢?非常是不爽吧. 这样的问题我也是常常碰到.这是人家商业引擎不想让你看 ...
- try git
Git allows groups of people to work on the same documents (often code) at the same time, and without ...
- Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器解析)
make解析 服务容器对对象的自动解析是服务容器的核心功能,make 函数.build 函数是实例化对象重要的核心,先大致看一下代码: public function make($abstract) ...
- 第11章 Docker Registry 相关问题
11.1 我 docker push 的时候怎么报 authentication required 错误? 因为你没有登录.如果是向 Docker Hub 推送镜像,需要在注册一个用户: https: ...
- Win MYSQL5.7.19压缩版安装
最近需要在wins上安装MYSQL,发现最新的版本和之前的有点差距,再次记录一下 1.下载:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5. ...
- Android开发:《Gradle Recipes for Android》阅读笔记1.1
第一章1.1节 注:下面都是用android studio新建出来的默认项目配置,没有修改 1.settings.gradle记录了哪些子目录包含了它们自己的工程,例如:include':app',如 ...
- python中json操作
1.写操作.json文件dumps().dump()函数 d = { 'zll': { 'addr': '北京', 'age': 28 }, 'ljj': { 'addr': '北京', 'age': ...