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发送一个非队列消息。这种情况下两个线程都得不到执行,将永远挂起。