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. 【转】 PreTranslateMessage作用和使用方法

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

  2. JAVA 注解的几大作用及使用方法详解

    JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释 ...

  3. serialVersionUID的作用以及设置方法(转)

    声明:本篇文章是转载的 http://blog.csdn.net/kakaxi_77/article/details/8129070 http://snowlotus.iteye.com/blog/2 ...

  4. PreTranslateMessage作用和用法

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

  5. 在Android开发中替换资源图片不起作用的解决方法

    现象 在android开发中,经常会需要替换res\drawable中的图片,打开res\layout下的文件预览布局页面发现图片已经被替换,但在模拟器或者真实机器上运行时发现该图片并没有被替换,还是 ...

  6. Linux中PATH环境变量的作用和使用方法

    关于PATH的作用:PATH说简单点就是一个字符串变量,当输入命令的时候LINUX会去查找PATH里面记录的路径.比如在根目录/下可以输入命令ls,在/usr目录下也可以输入ls,但其实ls这个命令根 ...

  7. PHP trim()函数的作用和使用方法

    PHP trim()函数一般是用来去除字符串首尾处的空白字符(或者其他字符),一般在用在服务端对接收的用户数据进行处理,以免把用户误输入的空格存储到数据库,下次对比数据时候出错. 该函数有两个参数,第 ...

  8. C++ "#"的作用和使用方法

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/48879093 1 #和##的作用和使用 ...

  9. header中Content-Disposition的作用与使用方法

    下载文件的时候会使用: Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件.Content-disposition其实可以控制用 ...

随机推荐

  1. 福昕阅读器打开PDF文档速度慢

    RT---------------- 操作如下两步可加快打开速度: 1.Program Files\Foxit Software\Foxit Reader下面的Shell Extensions文件夹删 ...

  2. Android项目页面跳转小Demo

    近期在做Android项目的开发,刚刚接触会有非常多新东西须要学习,从环境的搭建到语言的熟悉都是须要一步步完毕的,接下来就拿一个页面跳转的样例来和大家分享一下自己的心得体会. 採用的架构: Demo中 ...

  3. 生产者——消费者模型的java代码实现

    生产者 import java.util.Random; public class Producer extends Thread { private Storage<Product> s ...

  4. 【BZOJ3083/3306】遥远的国度/树 树链剖分+线段树

    [BZOJ3083]遥远的国度 Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了 ...

  5. <2013 07 31> 没有必然的理由

    <2013 07 31> 没有必然的理由 没有必然的理由 人类从野蛮走向文明 也可能,从野蛮走向更野蛮 没有必然的理由 人群从疯狂走向理智 也可能,从疯狂走向更疯狂 没有必然的理由 你我从 ...

  6. python系列十五:Python3 错误和异常

    #!/usr/bin/python #-*-coding:gbk-*- #Python3 错误和异常'''Python 语法错误或者称之为解析错语法分析器指出了出错的一行,并且在最先找到的错误的位置标 ...

  7. 解决Mysql报错缺少libaio.so.1

    解决Mysql报错缺少libaio.so.1 报错如上图,需要安装libaio.so.1 64位系统安装: wget http://mirror.centos.org/centos/6/os/x86_ ...

  8. AJAX 入门

    1. 同步交互与异步交互 1.1 同步交互 客户端发送一个请求, 需要等待服务器的响应结束,才能发送第二个请求! 刷新的是整个页面. 1.2 异步交互 客户端发送一个请求,无需等待服务器的响应,然后就 ...

  9. 解决Vue的表格中,expand只有某些行需要展开的问题。

    element UI里的表格里,type="expand"的话,所有行都有展开的选项,然而实际中有些行根据判断不需要展开,而element目前对这个问题还不是很友好,现在有个可以通 ...

  10. Python里面如何拷贝一个对象?

    import copy lst=[1,2,3,4,[1,2]] # 复制列表lst,命名lst2 lst2=copy.copy(lst) print(f'这是lst3:{lst2}') # 深拷贝 l ...