?? 01.6 消息循環的錯誤分析.txt
字號:
1.6 消息循環的錯誤分析
有不少初學者學完第1章后,編寫了下面的代碼:
…
HWND hwnd;
hwnd=CreateWindow(…);
…
MSG msg;
while(GetMessage(&msg,hwnd,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
…
注意代碼中以粗體顯示的部分。這段代碼基于這樣一個想法:第1章的程序只有一個窗口,而我們前面說了GetMessage函數的hWnd參數是用于指定接收屬于哪一個窗口的消息,于是不少人就在消息循環中為GetMessage函數的hWnd參數指定了CreateWindow函數返回的窗口句柄。
讀者可以用上述代碼中的消息循環部分替換1.5節代碼中的消息循環部分,然后運行程序,關閉程序。你會發現你的機器變慢了,同時按下鍵盤上的Ctrl + Alt + Delete鍵,啟動Windows的任務管理器,切換到“進程”選項卡,單擊“CPU”項進行排序,你會發現如圖1.7所示的情況。
從圖1.7中可以看到,WinMain.exe的CPU占用率接近100,難怪機器“變慢了”。那么這是什么原因呢?實際上這個問題的答案在MSDN中就可以找到,并且就在GetMessage函數的說明文檔中。不少初學者在遇到問題時,首先是頭腦一片空白,接著就去找人求助,這種思想用在程序開發的學習中,沒有什么好處。筆者經常遇到學員問問題,結果有不少問題的答案在MSDN關于某個函數的解釋中就可看到(由于顯示器的限制,有的答案需要滾動窗口才能看到 J)。所以在這里,筆者也建議讀者遇到問題一定要記得查看MSDN,學會使用MSDN并從中汲取知識,將使你受用無窮。
圖1.7 WinMain.exe的CPU占用率接近100
回到正題,在1.4.3節介紹GetMessage函數時,曾說過如果hWnd參數是無效的窗口句柄或lpMsg參數是無效的指針時,GetMessage函數將返回-1。當我們關閉窗口時,調用了DestroyWindow來銷毀窗口,由于窗口被銷毀了,窗口的句柄當然也就是無效的句柄了,那么GetMessage將返回-1。在C/C++語言中,非0即為真,由于窗口被銷毀,句柄變為無效,GetMessage總是返回-1,循環條件總是為真,于是形成了一個死循環,機器當然就“變慢了”。J
在MSDN關于GetMessage函數的說明文檔中給出了下面的代碼:
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
針對我們這個問題,可以修改上述代碼如下:
…
HWND hwnd;
hwnd=CreateWindow(…);
…
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, hwnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
return -1;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
…
讀者可以再次運行修改后的程序,看看運行的結果。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -