zoukankan      html  css  js  c++  java
  • MFC PreTranslateMessage

    转载自:http://www.zxbc.cn/html/20080418/33430.html

      PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当需要在MFC之前处理某些消息时,常常要在这里添加代码.        
          MFC 消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage(),通过重载这个函数,可以改变MFC的消息控制流程,甚至可 以作一个全新的控制流出来。只有穿过消息队列的消息才受PreTranslateMessage()影响,采用SendMessage()或其他类似的方 式向窗口直接发送的而不经过消息队列的消息根本不会理睬PreTranslateMessage()的存在。 
           是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。截获键盘鼠标消息,常用此方法来做。

    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就有机会进行处理。  

  • 相关阅读:
    详细描述一下 Elasticsearch 索引文档的过程 ?
    elasticsearch 索引数据多了怎么办,如何调优,部署 ?
    elasticsearch 了解多少,说说你们公司 es 的集群架构,索 引数据大小,分片有多少,以及一些调优手段 ?
    Dubbo 和 Dubbox 之间的区别?
    Dubbo 支持服务降级吗?
    Pipeline 有什么好处,为什么要用 pipeline?
    为什么redis 需要把所有数据放到内存中?
    你对线程优先级的理解是什么?
    在 java 中 wait 和 sleep 方法的不同?
    一个线程运行时发生异常会怎样?
  • 原文地址:https://www.cnblogs.com/taoxu0903/p/1640479.html
Copyright © 2011-2022 走看看