Windows訊息響應機制之四:PostQuitMessage和GetMessage函式
今天在練習Win32程式設計時碰到一個關於GetMessage函式的問題。這個問題之前一直沒有引起過我的注意,但是今天
在網上搜索發現這個問題很多程式設計師都跟我一樣處於一知半解的狀態。
在Win32應用程式的主函式中有一段訊息迴圈收發的程式碼:
while (GetMessage(&Msg, hWnd, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
在Debug環境下啟動程式後點擊關閉按鈕可以正常關閉掉視窗,但是VS2008卻無法正常退出執行狀態(即應用程式沒有正常返回)。於是我按如下步驟進行了Debug:
(1).在訊息處理函式中WM_DESTORY的處理中設定斷點,點選關閉按鈕case WM_DESROTY程式碼段可以執行;
(2).當程式執行到case WM_DESROTY程式碼段之後再在主函式的TranslateMessage(&Msg)處設定斷點
(3).按下F5發現程式可以執行到TranslateMessage(&Msg)處。
經過上述步驟Debug後發現當在WM_DESTORY訊息處理過程中呼叫PostQuitMessage(0)函式後程序的訊息迴圈程式碼段可以繼續執行,但是按MSDN的描述PostQuitMessage函式會往執行緒的訊息佇列中插入一個WM_QUIT訊息,而GetMessage函式在收到WM_QUIT訊息後會返回一個非正數。
後來在網上搜索網友克塞前來拜訪的一段解釋:
對PostQuitMessage而言,它實際上並不傳送WM_QUIT訊息,他所做的實際是設定一些特殊的系統標誌,而佇列存取體系根據這個標誌並結合一些比較複雜的演算法來決定在某時某處引發實際的WM_QUIT。當演算法臨界時,GetMessage(hwnd)照樣能獲取WM_QUIT。而如果你PostThreadMessage(WM_QUIT),那麼一個實際的WM_QUIT訊息會被佇列,GetMessage(hwnd)永遠不會獲得這個退出訊息。一個最簡單的滿足演算法要求的實驗可以是這樣:你在WM_CLOSE訊息裡PostQuitMessage,然後在啟動程式後,首先移動視窗,然後關閉視窗,則程式能夠正常退出,設定斷點除錯可以發現,GetMessage(hwnd)確實捕獲了這個理論上發給執行緒佇列的退出訊息,並且列印記憶體棧可以發現,訊息本身確實是發給執行緒佇列而非視窗佇列的。反之,如果你先使hwnd失效,則無論你如何操作,GetMessage(hwnd)永遠不會收到退出訊息。所以總結起來說,最終能否退出首先取決於hwnd是否失效,雖然這並不是能解釋這個問題的根本原因,但至少是一個正確的部分表象原因。
現階段由於我個人的水平還無法鑑別其真偽,所以這段解釋暫且先記錄下來作為日後的學習參考。