PreTranslateMessage作用和用法

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作用和用法

时间: 2024-08-30 04:05:29

PreTranslateMessage作用和用法的相关文章

C++ "#"的作用和用法

本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/48879093 1 #和##的作用和用法 C/C++ 的宏中,#的功能是将其后面的宏参数进行字符串化操作,简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号.##连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串联接起来,从而形成一个新的子串.但它不可以是第一个或者最后一个子串. #include <iostrea

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

ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入 Serializable其实是一个空接口 package java.io; public interface Serializable { } Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化. 什么情况下需要序列化 a)当你想把的内存中的对象写入到硬

AFNetwork 作用和用法详解

AFNetworking是一个轻量级的iOS网络通信类库.它建立在NSURLConnection和NSOperation等类库的基础上,让很多网络通信功能的实现变得十分简单.它支持HTTP请求和基于REST的网络服务(包括GET.POST. PUT.DELETE等).支持ARC. Github地址:https://github.com/AFNetworking/AFNetworking // // MJViewController.m // 03.AFN演练 // // Created by a

java中import、package作用和用法

  有些人写了一阵子 Java,可是对於 Java 的 package 跟 import 还是不 太了解很多人以為原始码 .java 档案中的 import 会让编译器把所 import 的程式通通写到编译好的 .class 档案中,或是认為 import 跟 C/C++ 的 #include 相似,实际上,这是错误的观念. 让我们先了解一下,Java 的 package 到底有何用处. 其实,package 名称就像是我们的姓,而 class 名称就像是我们的名字 .package 名称有很多

ifndef /define/ endif 作用和用法

问题:ifndef/define/endif”主要目的是防止头文件的重复包含和编译========================================================用法: .h文件,如下:#ifndef XX_H#define XX_H...#endif 这样如果有两个地方都包含这个头文件,就不会出现两次包含的情况 ..因为在第二次包含时 XX_H 已经有定义了,所以就不再 include了--------------------------------------

typeof的作用及用法

typeof的作用及用法 1.检查一个变量是否存在,是否有值. typeof在两种情况下会返回"undefined":一个变量没有被声明的时候,和一个变量的值是undefined的时候.例如: 1. alert(typeof undeclaredVariable === "undefined");    // true 2. var declaredVariable; alert(typeof declaredVariable);    // 'undefined'

JSP九大内置对象的作用和用法总结【转】

JSP九大内置对象的作用和用法总结? JSP中一共预先定义了9个这样的对象,分别为:request.response.session.application.out.pagecontext.config.page.exception 1.request对象javax.servlet.http.HttpServletRequest request对象代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据.(包括头信息.系统信息.请求方式以及请求参数等).request对 象的作用域

SQL over的作用及用法

sql over的作用及用法 RANK ( ) OVER ( [query_partition_clause] order_by_clause ) DENSE_RANK ( ) OVER ( [query_partition_clause] order_by_clause ) 可实现按指定的字段分组排序,对于相同分组字段的结果集进行排序, 其中PARTITION BY 为分组字段,ORDER BY 指定排序字段 over不能单独使用,要和分析函数:rank(),dense_rank(),row_

Java中static作用及用法详解

1.1概述: static是静态修饰符,什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在.这样做有什么意义呢?在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是用static修饰的成员可以通过类名加".&q