一、PeekMessage與GetMessage的對比
GetMessage的主要功能是從消息隊列中“取出”消息,消息被取出以後,就從消息隊列中將其刪除;而PeekMessage的主要功能是“窺視”消息,如果有消息,就返回true,否則返回false。
也可以使用PeekMessage從消息隊列中取出消息,這要用到它的一個參數(UINT wRemoveMsg),如果設置爲PM_REMOVE,消息則被取出並從消息隊列中刪除;如果設置爲PM_NOREMOVE,消息就不會從消息隊列中取出。
相同點:
PeekMessage函數與GetMessage函數都用於查看應用程序消息隊列,有消息時將隊列中的消息派發出去。
不同點:
無論應用程序消息隊列是否有消息,PeekMessage函數都立即返回,程序得以繼續執行後面的語句(無消息則執行其它指令,有消息時一般要將消息派發出去,再執行其它指令)。
GetMessage函數只有在消息隊列中有消息時返回,如果隊列中無消息就會一直等,直至下一個消息出現時才返回。在等的這段時間,應用程序不能執行任何指令。
二、實例
PeekMessage
//PeekMessage查看消息隊列中是否有消息,如果沒有則執行畫矩形DrawRectangle,有消息則先把消息發配出去,
PeekMessage函數獲取並派發消息出去,然後繼續畫矩形DrawRectangle。
nt WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("RandRect") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Random Rectangles"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
//用於替換的部分
while (TRUE)
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
else
DrawRectangle (hwnd) ;
}
//用於替換的部分
return msg.wParam ;
}
如果換成
GetMessage
while (TRUE)
{
if (GetMessage (&msg, NULL, 0, 0))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
DrawRectangle (hwnd) ;
}
else
break;
}
則應用程序產生一個消息(鼠標移動、改變窗體大小等),在窗體內畫一個隨機生成的矩形,無消息產生時,窗體無變化。
三、總結
如果GetMessage從消息隊列中取不到消息,則線程就會被操作系統掛起,等到OS重新調度該線程時,兩者的性質不同:使用GetMessage線程仍會被掛起,使用PeekMessage線程會得到CPU的控制權,運行一段時間。
GetMessage每次都會等待消息,直到取到消息才返回;而PeekMessage只是查詢消息隊列,沒有消息就立即返回,從返回值判斷是否取到了消息。
我們也可以說,PeekMessage是一個具有線程異步行爲的函數,不管消息隊列中是否有消息,函數都會立即返回。而GetMessage則是一個具有線程同步行爲的函數,如果消息隊列中沒有消息的話,函數就會一直等待,直到消息隊列中至少有一條消息時才返回。
所以,從它們的不同點上來看,PeekMessage函數有點像“乞丐行乞”,有你就施捨點,沒有也不強求。GetMessage函數有點像“強盜打劫”,有你得給,沒有我就等你什麼時候有了再給,這段時間我什麼都不幹,我就等你。
參考: