GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax,UINT wRemoveMsg)
参数wRemoveMsg的作用是指定消息获取的方式,如果设为PM_NOREMOVE,那么消息将不会从消息队列中被移出,如果设为PM_REMOVE,那么消息将会从消息队列中被移出;
两个函数主要有以下两个区别:
1.GetMessage将等到有合适的消息时才返回,而PeekMessage只是撇一下消息队列。
2.GetMessage会将消息从队列中删除,而PeekMessage可以设置最后一个参数wRemoveMsg来决定是否将消息保留在队列中。
在Windows的内部,GetMessage和PeekMessage执行着相同的代码。而两者最大的不同之处则体现在没有任何消息返回到应用程序的情况下。在此种情况下,PeekMessage会返回一个空值到应用程序,GetMessage会在此时让应用程序休眠。
HOWTO: How to Use PeekMessage() Correctly in Windows
SUMMARY
In the Windows environment, many applications use a PeekMessage() loop to perform background processing. Such applications must allow the Windows system to enter an idle state when their background processing is complete. Otherwise, system performance, "idle-time" system processes such as paging optimizations, and power management on battery-powered systems will be adversely affected.
While an application is in a PeekMessage() loop, the Windows system cannot go idle. Therefore, an application should not remain in a PeekMessage() loop after its background processing has completed.
NOTE: The PeekMessage method described in this article is only needed if your application is a 32-bit application for Windows and is, for some reason, unable to create threads and perform background processing.
MORE INFORMATION
<script type="text/javascript"></script>An application should not call PeekMessage() unless it has background processing to do between the calls to PeekMessage(). When an application is waiting for an input event, it should call GetMessage() or WaitMessage().
Remaining in a PeekMessage() loop when there is no background work causes system performance problems. A program in a PeekMessage() loop continues to be rescheduled by the Windows scheduler, consuming CPU time and taking time away from other processes.
In enhanced mode, the Virtual Machine (VM) in which Windows is running will not appear to be idle as long as an application is calling the PeekMessage function. Therefore, the Windows VM will continue to receive a considerable fraction of CPU time.
Many power management methods employed on laptop and notebook computers are based on the system going idle when there is no processing to do. An application that remains in a PeekMessage() loop will make the system appear busy to power management software, resulting in excessive power consumption and shortening the time that the user can run the system.
In the future, the Windows system will make more and more use of idle time to do background processing, which is designed to optimize system performance. Applications that do not allow the system to go idle will adversely affect the performance of these techniques.
All these problems can be avoided by calling the PeekMessage() function only when there is background work to do, and calling GetMessage() or WaitMessage() when there is no background work to do.
For example, consider the following PeekMessage() loop. If there is no background processing to do, this loop will continue to run without waiting for messages, preventing the system from going idle and causing the negative effects described above.
{
{
if (msg.message == WM_QUIT)
return TRUE;
DispatchMessage(&msg);
}
}
• | They process all input messages before performing background processing, providing good response to user input. |
• | The application "idles" (waits for an input message) when no background processing needs to be done. |
Improved PeekMessage Loop 1
<script type="text/javascript"></script>
// Improved PeekMessage() loop
for(;;)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (IfBackgroundProcessingRequired())
BackgroundProcessing();
else
WaitMessage(); // Will not return until a message is posted.
}
Improved PeekMessage Loop 2
<script type="text/javascript"></script>
// Another improved PeekMessage() loop
for (;;)
{
for (;;)
{
if (IfBackgroundProcessingRequired())
{
if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
break;
}
else
GetMessage(&msg, NULL, 0, 0, 0);
if (msg.message == WM_QUIT)
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
BackgroundProcessing();
}
BOOL PeekMessage( LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
参数:
lpmsg:接收消息信息的msg结构指针。
hwnd:其消息被检查的窗口的句柄。
wmsgfiltermin:指定被检查的消息范围里的第一个消息。
wmsgfiltermax:指定被检查的消息范围里的最后一个消息。
wremovemsg:确定消息如何被处理。此参数可取下列值之一:
pm_noremove:peekmessage处理后,消息不从队列里除掉。
pm_remove:peekmessage处理后,消息从队列里除掉。
可将pm_noyield随意组合到pm_noremove或pm_remove。此标志使系统不释放等待调用程序空闲的线程。
缺省地,处理所有类型的消息。若只处理某些消息,指定一个或多个下列值:
pm_qs_input:windows nt5.0和windows 98:处理鼠标和键盘消息。
pm_qs_paint:windows nt 5.0和windows 98:处理画图消息。
pm_qs_postmessage:windows nt 5.0和windows 98:处理所有被寄送的消息,包括计时器和热键。
pm_qs_sendmessage:windows nt 5.0和windows 98:处理所有发送消息。
返回值:如果消息可得到,返回非零值;如果没有消息可得到,返回值是零。
备注:和函数getmessage不一样的是,函数peekmesssge在返回前不等待消息被放到队列里。
peekmesssge只得到那些与参数hwnd标识的窗口相联系的消息或被lschild确定为其子窗口相联系的消息,并且该消息要在由参数wmsgfitermin和wmsgfihermax确定的范围内。如果hwnd为null,则peekmessage接收属于当前调用线程的窗口的消息。如果hwnd为c1,peekmessage只返回hwnd值为null的消息,该消息由函数postthreadmessage寄送。如果wmsgfiltermin和wmsgfiltermax都为零,getmessage返回所有可得的消息。
常数wm_keyfirst和wmkeylast可作为过滤值取得所有键盘消息;常数wm_mousefirst和wm_mouselast可用来接收所有的鼠标消息。
peekmessage通常不从队列里清除wm_pant消息。该消息将保留在队列里直到处理完毕。但如果wm_paint消息有一个空更新区,peekmessage将从队列里清除wm_paint消息。
windows ce:有一个null更新区的wm_paint消息不从队列里清除。
速查:windows nt:3.1及以上版本;wihdows:95及以上版本:windows ce:1.0及以上版本;头文件:winuser.h输入库:user32.lib:unicode:在windows nt环境下以unicode和ansi方式实现。
while ( bDoingBackgroundProcessing )
{
MSG msg;
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if ( !PumpMessage( ) )
{
bDoingBackgroundProcessing = FALSE;
::PostQuitMessage( );
break;
}
}
// 使 MFC 进行其空闲处理
LONG lIdle = 0;
while ( AfxGetApp()->OnIdle(lIdle++ ) ) ; // 在此处进行一些后台处理 // 使用另一个对 OnIdle 的调用
}
Note that calls to functions such as IsDialogMessage() and TranslateAccelerator() can be added to these loops as appropriate.
There is one case in which the loops above need additional support: if the application waits for input from a device (for example, a fax board) that does not send standard Windows messages. For the reasons outlined above, a Windows-based application should not use a PeekMessage() loop to continuously poll the device. Rather, implement an Interrupt Service Routine (ISR) in a Dynamic-Link Library (DLL). When the ISR is called, the DLL can use the PostMessage function to inform the application that the device requires service. DLL functions can safely call the PostMessage() function because the PostMessage() function is reentrant.