PreTranslateMessage作用和用法

 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用,当须要在MFC之前处理某些消息时,经常要在这里加入代码.  
       MFC消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage(),通过重载这个函数,能够改变MFC的消息控制流程,甚至能够作一个全新的控制流出来。仅仅有穿过消息队列的消息才受PreTranslateMessage()影响,採用SendMessage()或其它相似的方式向窗体直接发送的而不经过消息队列的消息根本不会理睬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)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息 放到一个系统消息队列中去. 而应用程序须要有自己的消息队列,也就是线程消息队列,每个线程有自己的消息队列,对于多线程的应用程序就有和线程数目相等的线程消息队列.  
  windows消息队列把得到的消息发送到线程消息队列,线程消息队列每次取出一条消息发送到指定窗体,不断循环直到程序退出.这个循环就是靠消息环(while(GetMessage()) TranslateMessage();DispatchMessage();实现的.GetMessage()仅仅是从线程消息中取出一条消息,TranslateMessage()把virtue key消息转化成character消息,如VK_F1会转化成WM_HELP,而DispatchMessage  则把取出的消息发送到目的窗体.假设收到WM_CLOSE消息则结束循环,发送postqiutmessage(0),处理WM_DESTROY销毁窗体!
 
 while (GetMessage(&msg, NULL, 0, 0))          //C++ code
 {  
        TranslateMessage(&msg);
        DispatchMessage(&msg);
 }
 
 

PreTranslateMessage作用和用法的更多相关文章

  1. serialVersionUID, ObjectInputStream与ObjectOutputStream类,Serializable接口,serialVersionUID的作用和用法

    ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入 Ser ...

  2. Oracle函数over(),rank()over()作用及用法--分区(分组)求和& 不连续/连续排名

    (1)   函数:  over()的作用及用法:    -- 分区(分组)求和. RANK ( ) OVER ( [query_partition_clause] order_by_clause )D ...

  3. Linq中关键字的作用及用法

    Linq中关键字的作用及用法 1.All:确定序列中的所有元素是否都满足条件.如果源序列中的每个元素都通过指定谓词中的测试,或者序列为空,则为 true:否则为 false. Demo: 此示例使用 ...

  4. JSP九大内置对象的作用和用法总结?

    JSP九大内置对象的作用和用法总结? 1.request对象javax.servlet.http.HttpServletRequest request对象代表了客户端的请求信息,主要用于接受通过HTT ...

  5. (转载)MySQL数据类型中DECIMAL的作用和用法

    (转载)http://database.51cto.com/art/201005/201651.htm 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都 ...

  6. ViewHolder的作用和用法

    一直都看别人用ViewHolder,自己也用过,却不知道它的作用是什么?但知道肯定很有用,而且现在android studio应该有直接生产Viewholder的插件, 不过博主我是个新手,就没尝试去 ...

  7. Oracle分析函数及常用函数: over(),rank()over()作用及用法--分区(分组)求和& 不连续/连续排名

    (1)   函数:  over()的作用及用法:    -- 分区(分组)求和. sum() over( partition by column1 order by column2 )主要用来对某个字 ...

  8. og标签对SEO的作用及用法

    meta property=og标签对SEO的作用及用法,如果你仔细观察会发现本站点<head>代码中有一段:"property="og:image"这段代码 ...

  9. 【转】 PreTranslateMessage作用和使用方法

    PreTranslateMessage作用和使用方法  PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用, ...

随机推荐

  1. jQuery API中文文档

    jQuery API中文文档 http://www.css88.com/jqapi-1.9/category/events/event-handler-attachment/ jQuery UI AP ...

  2. nav

    $(document).ready(function() { $(window).resize(function(){ var need=0; var ul_max_width = $(window) ...

  3. DEDECMS重要文件

    DEDECMS 重要文件dedecms/include/common.inc.php全局变量文件dedecms/include/extend.func.php自定义函数文件

  4. python进度条代码

    import sys import time def view_bar(num,total): rate = num / total rate_num = int(rate * 100) r = ' ...

  5. C语言学习笔记(二):指针的用法

    与其说指针是一种工具,不如先说指针是一种数据类型. -------------------------------------------------------------华丽的分割线------- ...

  6. 小A项目为什么加班

    1.负责架构搭建的人搭建完成架构后,没有进行落地性验证:导致真正要用到的时候才发现spring没有配置:需要对架构人员的进度和内容进行跟踪,在跟踪进度的时候需要强调落地性: 2.负责架构搭建的人没有提 ...

  7. 使用c语言编写cgi程序

    http://blog.chinaunix.net/uid-22566367-id-3109877.html 简单的说,cgi是沟通HTML表单和服务器端程序的接口,是可以被其他语言所应用的一个规范集 ...

  8. ha666_go运行环境配置

    项目地址:http://git.oschina.net/ha666/ha666_go 服务器配置: CPU: 1核 内存: 1024 MB 操作系统: CentOS 7.0 64位 内网IP: 10. ...

  9. Rss web 工具 大对比

    今天终于神受不了 feedly的链接死掉了..有时候挂代理就好了..但是麻烦. 于是: AOL reader Digg  reader feedly 对比下.使用了一天 1.feedly 优: 效果最 ...

  10. 单例模式在Unity中的应用

    起因:每个游戏场景中都会有许多的游戏对象,而各个游戏场景之间也是同等的关系.如何去管理它们,是我们要解决的问题. 场景中各脚本间的直接访问,会在各脚本间形成一个巨大而又混乱的网络,这给以后代码的维护带 ...