PeekMessage/GetMessage SendMessage和PostMessage SendMessageTimeOut

1.PeekMessage/GetMessage

  两个函数主要有以下两个区别:
    1.GetMessage只有在等到消息时才返回,没有消息时就会阻塞线程,这时线程的时间片将会被出让给别的线程。而且当GetMessage遇到WM_QUIT时,将会返回0.
      而PeekMessage只是检查一下消息队列,有没有消息都会立即返回,只是在没有消息的时候返回值为0. 所以PeekMessage无论有无消息都不会出让线程的时间片。
    2.GetMessage会将消息从队列中删除,而PeekMessage可以设置最后一个参数wRemoveMsg来决定是否将消息保留在队列中。
   
    BOOL GetMessage(
      LPMSG lpMsg,              // 一个MSG的指针
      HWND hWnd,               // 一般为当前窗口的句柄
      UINT wMsgFilterMin,   // 指定被检索的最小消息值的整数
      UINT wMsgFilterMax   // 指定被检索的最大消息值的整数
    );
    如果第三,四个参数都为零,则取所有的消息。
    如果出现错误,比如参数一或参数而指向的指针或句柄无效,则会返回-1.
   
    BOOL PeekMessage(
      LPMSG lpMsg,                 // 一个MSG的指针
      HWND hWnd,                  //
      UINT wMsgFilterMin,      //
      UINT wMsgFilterMax,     // 前四个参数和GetMessage的一样
      UINT wRemoveMsg       // 取完消息要做的操作
    );
    wRemoveMsg:确定消息如何被处理。此参数可取下列值之一:
    PM_NOREMOVE:PeekMessage处理后,消息不从队列里除掉。
    PM_REMOVE:PeekMessage处理后,消息从队列里除掉,一般都是采用这种删除的方法。

    GetMessage举例
    // 主消息循环:
     while (GetMessage(&msg, NULL, 0, 0))
     {
      if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
      {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
      }
     }
     
    PeekMessage举例:
    while(1)
    {
        if(PeekMessage(&msg, NULL, 0, 0))
        {
          TranslateMessage(&msg);
       DispatchMessage(&msg);
        }
        else
        {
            //do other things
        }
   
    }
   
   
2.SendMessage和PostMessage

    下面以线程A向线程B发送消息为例来说明:

    (1).如果线程A和线程B是同一线程:
    PostMessage会将消息压入窗口所在线程的消息队列,然后立即返回,返回值标志消息放到线程队列是否成功;然后这个消息会通过消息循环Dispatch到目标窗口。
    而SendMessage则不经过消息队列,SendMessage可认为是直接调用了该窗口的窗口过程,在窗口过程执行完毕之后SendMessage才会返回。SendMessage的返回值就是窗口过程的返回值。

    (2).如果线程A和线程B是不同的线程:
    在多线程应用中,PostMessage的用法还是一样,但是最好用PostThreadMessage代替PostMessage,他工作的很好。
    然而SendMessage则不同了。如果在线程A中向线程B所创建的一个窗口hWndB发送消息SendMessage(hWndB,WM_MSG,0,0),那么系统将会立即将执行权从线程A切换到线程B,然后在线程B中调用hWndB的窗口过程来处理消息,并且在处理完该消息后,执行权仍然在B手中!这个时候,线程A则暂停在SendMessage处,等待下次线程A获得执行权后才继续执行,并且仍然可以获得消息处理的结果(返回值)。一般,为了避免死锁,在B中对WM_MSG做出处理之前,要加上:
   
      if(InSendMessage())
        RelpyMessage(lResult);
    即判断:如果该消息是发自另外一个线程,则立即 RelpyMessage,回复消息,参数lResult即是返回值。而如果是在同一个线程内,则InSendMessage()将会返回FALSE。
   
3.SendMessageTimeOut
作用是:设定等待消息返回的最大时间。

当线程A通过SendMessage向线程B发送消息,但是在SendMessage没有返回的时候,线程A可能会收到非队列消息(nonqueued messages,比如其他线程用SendMessage向线程A发送消息)。
由于一个线程在等待发送的消息返回时允许被中断,以便处理另一个发送来的消息。也就是说这时调用线程A对应的窗口过程是允许的。我们可以使用SendMessageTimeOut函数的SMTO_BLOCK阻止这样的中断。
但是这样可能引起死锁,比如这时线程B又向线程A发送一个非队列消息。这种情况下两个线程都得不到执行,将永远挂起。

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值