SendMessage和PostMessage 的区别 PreTranslateMessage

来源:互联网 发布:php header setcookie 编辑:程序博客网 时间:2024/06/12 19:16
SendMessage和PostMessage 的区别,以及消息循环路由
一、下面示例函数func()中有PostMessage和SendMessage
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 int MainWnd(...)
 {
  MSG msg;
  while(1)
  {
   //当没有消息时,GetMessage不返回,程序就停在这里
   GetMessage(&msg,NULL,0,0)
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }  
  ........
 }


 LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
 {
  switch(message)
  {
  case WM_CLOSE:
   {
   }
   break;
  case WM_PASTE:
   {
   }
  default:
   return DefWindowProc(hWnd,message,wParam,lParam);
  }
  return 0;
 }


 void func()
 {
  ........
  ........
  PostMessage(hWnd,WM_CLOSE,NULL,NULL)
  //PostMessage,只是简单的把WM_CLOSE放在消息队列里,然后函数立刻返回,
  //继续执行下面的代码,那我们要执行的WM_CLOSE什么时候执行呢?这个系统说了算
  //系统会在合适的时候从消息队列里取出WM_CLOSE,在代码里体现为
  //GetMessage返回,参数msg.message设为WM_CLOSE,之后如代码所示,会执行到
  //DispatchMessage,DispatchMessage内部调用SendMessage,SendMessage内部调用
  //窗口函数WndProc,最后才会跳到 “case WM_CLOSE”

  ........
  ........
  SendMessage(hWnd,WM_PASTE,NULL,NULL)
  //SendMessage内部调用了WndProc,之后就会跳转到"case WM_PASTE" ,再之后WndProc返回,
  //SendMessage返回。程序才会继续往下执行。从理解的角度来看,你完全可以把
  //SendMessage(hWnd,WM_PASTE,NULL,NULL) 等同于调用函数
  //WndProc(hWnd,WM_PASTE,NULL,NULL) ,这样就很好理解了。
 }


二、总结来说:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 1.
 PostMessage(WM_CLOSE)简单把消息放入队列并返回->
 GetMessage->DispatchMessage->SendMessage->WndProc->处理消息WM_CLOSE

 2.
 SendMessage(WM_CLOSE) 就相当于调用WndProc(WM_CLOSE)

 

三、PostMessage、SendMessage和 GetMessage 内部结构简化:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 PostMessage内部结构简化:
 BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
 {
  ....................
  把消息放到窗口消息队列中
  ....................
  return TRUE;
 }

 SendMessage内部结构简化:
 LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
 {
  ....................
  ....................
  LRESULT ret=WndProc(hWnd,Msg,wParam,lParam);
  ....................
  ....................
  return ret;
 }


 GetMessage内部结构简化:
 BOOL GetMessage(LPMSG lpMsg,HWND hWnd,wMsgFilterMin,wMsgFilterMax)
 {
  ....................

  GetMessage是一个很神奇的函数,它不是按我们常规那样理解的。
  常规函数里的代码是一行一行往下执行并最后返回,但GetMessage里有堵塞结构
  系统如果发现消息队列里没有消息,就让代码停下来,整个程序也就没有“运动了”
  (后台程序往往处于这种情况)
  不停地查看消息队列里是否有消息,如果没有就停在这里,不往下执行。
  如果发现有消息了,比如系统发现鼠标点击了窗口,会把WM_LBUTTONDOWN
  放到消息队列里,这时就可以从队列中取出WM_LBUTTONDOWN消息,继续往下执行

  ....................

  lpMsg->message=WM_LBUTTONDOWN;

  ....................

  return TRUE; //GetMessage基本都是返回TRUE,否则while循环就推出,程序也就结束了
 }

http://hi.baidu.com/qiujiejia/item/7475b442558925e51381dae4

PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当你需要在MFC之前处理某些消息时,常常要在这里添加代码.  MFC消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage(),通过重载这个函数,我们可以改变MFC的消息控制流程,甚至可以作一个全新的控制流出来。只有穿过消息队列的消息才受PreTranslateMessage()影响,采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息根本不会理睬PreTranslateMessage()的存在。
一、是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。
二、传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。可以在该函数中使用(pMsg->wParam==VK_RETURN)来拦截回车键。
三、在WindowProc里不能处理WM_Char消息。
四、SetWindowText会发送WM_Char给窗口。
五、PeekMessage和GetMessage的区别:
GetMessage在没有消息的时候等待消息,cpu占用率当然低。
PeekMessage没有消息的时候立刻返回,可以在没有消息的时候可以做其他处理,但cpu占用率一般较高。
大多游戏都用PeekMessage();
1111


0 0