PreTranslateMessage

来源:互联网 发布:mac ppt导出图片 编辑:程序博客网 时间:2024/05/17 08:49

 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继承过来。其简化后的代码大概如下:

Title  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(虽然也会调用其他函数,但是这个最为关键),其代码如下:

Title  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 。同时这里满足了虚函数层层条用的条件(1 自类窗口对象附值给父类指针,2 PreTranslateMessage为虚函数),所以这个循环是:从 "子类" --> "父类" 方向层层运行 PreTranslateMessage函数,再由 "子窗口" --> "父窗口" 层层运行,直到发现该消息在某个类中被 "return True" 才停止。

MFC中PreTranslateMessage是GetMessage(...)函数的下一级操作,即GetMessage(...)从消息队列中获取消息后,交由PreTranslateMessage()处理,若其返回FALSE则再交给TranslateMessage和DispatchMessage处理(进入WindowProc);  
如果用SendMessage,   则消息直接交到WindowProc处理,所以GetMessage不会取得SendMessage的消息,当然PreTranslateMessage也就不会被调用。 
如果用PostMessage,则消息进入消息队列,由GetMessage取得,PreTranslateMessage就有机会进行处理。
源码:

Title

BOOL CWinThread::PumpMessage()
{
  return AfxInternalPumpMessage();
}

BOOL AFXAPI AfxInternalPumpMessage()
{

 _AFX_THREAD_STATE *pState = AfxGetThreadState();

 if (!::GetMessage(&(pState->m_msgCur), NULL, NULL, NULL))
 {
#ifdef _DEBUG
  TRACE(traceAppMsg, 1, _T("CWinThread::PumpMessage - Received WM_QUIT./n"));
   pState->m_nDisablePumpCount++; // application must die
#endif
  // Note: prevents calling message loop things in 'ExitInstance'
  // will never be decremented
  return FALSE;
 }

#ifdef _DEBUG
  if (pState->m_nDisablePumpCount != 0)
 {
   TRACE(traceAppMsg, 0, _T("Error: CWinThread::PumpMessage called when not permitted./n"));
   ASSERT(FALSE);
 }
#endif

#ifdef _DEBUG
 _AfxTraceMsg(_T("PumpMessage"), &(pState->m_msgCur));
#endif

  // process this message

 if (pState->m_msgCur.message != WM_KICKIDLE && !AfxPreTranslateMessage(&(pState->m_msgCur)))
 {
  ::TranslateMessage(&(pState->m_msgCur));
  ::DispatchMessage(&(pState->m_msgCur));
 }
  return TRUE;
}
BOOL __cdecl AfxPreTranslateMessage(MSG* pMsg)
{

  CWinThread *pThread = AfxGetThread();
  if( pThread )
 return pThread->PreTranslateMessage( pMsg );
  else
 return AfxInternalPreTranslateMessage( pMsg );
}
BOOL CWinThread::PreTranslateMessage(MSG* pMsg)
{
 ASSERT_VALID(this);
 return AfxInternalPreTranslateMessage( pMsg );
}
BOOL AfxInternalPreTranslateMessage(MSG* pMsg)
{

// ASSERT_VALID(this);

 CWinThread *pThread = AfxGetThread();
 if( pThread )
 {
  // if this is a thread-message, short-circuit this function
  if (pMsg->hwnd == NULL && pThread->DispatchThreadMessageEx(pMsg))
   return TRUE;
 }

 // walk from target to main window
 CWnd* pMainWnd = AfxGetMainWnd();
 if (CWnd::WalkPreTranslateTree(pMainWnd->GetSafeHwnd(), pMsg))
  return TRUE;

 // in case of modeless dialogs, last chance route through main
 //   window's accelerator table
 if (pMainWnd != NULL)
 {
   CWnd* pWnd = CWnd::FromHandle(pMsg->hwnd);
   if (pWnd->GetTopLevelParent() != pMainWnd)
   return pMainWnd->PreTranslateMessage(pMsg);
 }

 return FALSE;   // no special processing
}

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: accelerato

rs)
  }

  // got to hWndStop window without interest
  if (hWnd == hWndStop)
   break;
 }
 return FALSE;       // no special processing
}

 

 

http://www.cnblogs.com/kingln/archive/2009/08/21/1551491.html

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 12306手机丢了密码忘了怎么办 教师考试注册时邮箱填写错误怎么办 计算机二级注册时邮箱填错了怎么办 注册时执业范围填错了怎么办 百度号被盗了申诉不回来怎么办 斗鱼直播伴侣显示分类不可用怎么办 斗鱼黑名单显示网络加载失败怎么办 平台登录验证码只能显示一半怎么办 想改微博密码但是忘了原密码怎么办 微博账号密码都忘了怎么办 新浪博客忘记邮箱和密码忘了怎么办 新浪助学贷款邮箱密码忘了怎么办 客厅的父母乐忘记密码了怎么办 微博密码忘记了手机号也换了怎么办 想改密码旧密码忘了怎么办 商标转让转让方不配合做补证怎么办 肇事后责任方拒赔怎么办久草www 我出车祸了对方逃逸找不到人怎么办 肇事车辆怀疑是故意伤人怎么办啊 法院判的交通事故罚金没钱交怎么办 公安抓人应该行政拘留却放了怎么办 停车场把人家车刮了跑了后怕怎么办 膝盖半月板损伤可走路不疼怎么办 面试过程中遇到写的笔没水怎么办 当学生会主席底下的人不服怎么办 中班学生放学总是不写作业怎么办 妻子不想离婚主动同认婚外情怎么办 淘宝自动退款超时了卖家怎么办 征途盟战刺探自己盟的没做怎么办 被蜜蜂蛰了但一周后奇痒怎么办 热带鱼小鱼抢食大鱼吃不到怎么办 家里养的植物土壤里有虫子怎么办 哺乳期乳房有硬块乳头有白点怎么办 税务查税拿到不开票销售合同怎么办 买地皮是集体证已交钱了怎么办 word里的字体都是英文版怎么办 华为手机开机卡在菊花那里怎么办 车辆挂牌时公司名称打错了怎么办 经营异常名录查不到怎么办移除 企业被列入经营税务异常名录怎么办 手机号被别人绑定了企业微信怎么办