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作用和用法的更多相关文章
- serialVersionUID, ObjectInputStream与ObjectOutputStream类,Serializable接口,serialVersionUID的作用和用法
ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入 Ser ...
- Oracle函数over(),rank()over()作用及用法--分区(分组)求和& 不连续/连续排名
(1) 函数: over()的作用及用法: -- 分区(分组)求和. RANK ( ) OVER ( [query_partition_clause] order_by_clause )D ...
- Linq中关键字的作用及用法
Linq中关键字的作用及用法 1.All:确定序列中的所有元素是否都满足条件.如果源序列中的每个元素都通过指定谓词中的测试,或者序列为空,则为 true:否则为 false. Demo: 此示例使用 ...
- JSP九大内置对象的作用和用法总结?
JSP九大内置对象的作用和用法总结? 1.request对象javax.servlet.http.HttpServletRequest request对象代表了客户端的请求信息,主要用于接受通过HTT ...
- (转载)MySQL数据类型中DECIMAL的作用和用法
(转载)http://database.51cto.com/art/201005/201651.htm 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都 ...
- ViewHolder的作用和用法
一直都看别人用ViewHolder,自己也用过,却不知道它的作用是什么?但知道肯定很有用,而且现在android studio应该有直接生产Viewholder的插件, 不过博主我是个新手,就没尝试去 ...
- Oracle分析函数及常用函数: over(),rank()over()作用及用法--分区(分组)求和& 不连续/连续排名
(1) 函数: over()的作用及用法: -- 分区(分组)求和. sum() over( partition by column1 order by column2 )主要用来对某个字 ...
- og标签对SEO的作用及用法
meta property=og标签对SEO的作用及用法,如果你仔细观察会发现本站点<head>代码中有一段:"property="og:image"这段代码 ...
- 【转】 PreTranslateMessage作用和使用方法
PreTranslateMessage作用和使用方法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用, ...
随机推荐
- iPhone、iPad默认按钮样式问题
iPhone.iPad默认按钮样式问题 解决方法给按钮元素添加一个-webkit-appearance: none;具体代码 input[type="button"], input ...
- chdir 改变当前目录为起始目录
<?php chdir(dirname(__FILE__));//把当前目录设置为当前目录?> 将 PHP 的当前目录改为 directory. 参数 directory 新的当前目录 返 ...
- DB2JAVIT:RC=9505解决方案
DB2JAVIT:RC=9505解决方案 题记:WIN7下装DB2,启动任务中心.控制中心报DB2JAVIT:RC=9505. 解决方案:进入(计算机—>管理—>本地用户和组)把用户加入到 ...
- js 的其它运算符和优先级
三元运算符: 语法为 exp1? exp2:exp3 判断 exp1是true 和 false 如果true,则返回exp2 ,如果false ,则返回exp3 <script> if ...
- 百度的一个Ajax跨域方法 JavaScript是没有域的限制
baidu的通行证处理都是在二级域名passport.baidu.com中处理的,但是baidu很多地方登录都好像是用ajax处理的,他是怎么做的呢?研究了一下,发现一个小技巧. 在http://zh ...
- #module-django.db.models
Models A model is the single, definitive source of information about your data. It contains the esse ...
- WCF返回JSON的详细配置
开发环境:VS2008,c# 1.新建个WCF服务网站 文件-新建-网站-WCF服务 2,运行一下,提示配置WEB.CONFIG,点击确认. 3,打开web.config增加如下节点: <ser ...
- java项目导出jar文件时指定main方法的类
需要先运行一下main函数,eclipse的Export-->Runnable JAR File ---> 下的Launch configuration下拉列表才会有记录.如果想要删除下拉 ...
- 【转】Spring注解详解
http://blog.csdn.net/xyh820/article/details/7303330/ 概述 注释配置相对于 XML 配置具有很多的优势: 它可以充分利用 Java 的反射机制获取类 ...
- windows系统安装ubuntu后,grub中没有windows启动项
我的问题: 安装系统时候,选择grub安装在sdb磁盘 http://forum.ubuntu.org.cn/viewtopic.php?f=139&t=474289&start=15 ...