本文對WM_CLOSE、WM_DESTROY、WM_QUIT及各種消息投遞函數的功能及區別做出了分析比對,有助于讀者更好的對消息投遞函數加以理解。詳情如下:
一、WM_CLOSE、WM_DESTROY、WM_QUIT區別
WM_CLOSE:關閉應用程序窗口
WM_DESTROY:關閉應用程序
WM_QUIT:關閉消息循環
只有關閉了消息循環,應用程序的進程才真正退出(在任務管理器里消失)。
win32應用程序的完整退出過程:點擊窗口右上角的關閉按鈕,發送WM_CLOSE消息。此消息處理中調用DestroyWindow函數,發送WM_DESTROY消息。此消息處理中調用PostQuitMessage(0)函數,發送WM_QUIT消息到消息隊列中。GetMessage捕獲到WM_QUIT,返回0,退出循環(應用程序真正退出)。
注意:按照上述正常流程,WM_QUIT是不會到達窗口過程的。(因為在GetMessage截獲了WM_QUIT消息之后,程序已經徹底退出了!)
MFC應用程序的完整退出過程:點擊窗口右上角的關閉按鈕,或選擇【File/Close】,發出 WM_CLOSE消息。CMyFrameWnd 并沒有設置WM_CLOSE 處理常式,于是交給預設之處理常式。預設函數對于WM_CLOSE 的處理方式是呼叫 ::DestroyWindow, 并因而發出WM_DESTROY。預設之WM_DESTROY 處理方式是呼叫::PostQuitMessage,因此發出WM_QUIT。CWinApp::Run 收到WM_QUIT 后會結束其內部之訊息回路, 然后呼叫ExitInstance,這是CWinApp 的一個虛擬函數。如果自己應用程序類CMyWinApp 改寫了ExitInstance , 那么CWinApp::Run 所呼叫的就是CMyWinApp::ExitInstance,否則就是 CWinApp::ExitInstance。最后回到 AfxWinMain,執行 AfxWinTerm,結束程序。
附加:當調用DestroyWindow函數后,操作系統就會進行一系列的刪除動作,先發送WM_DESTROY消息,接著發送WM_NCDESTROY消息。如果這個窗口還有子窗口或者是其它窗口的所有者,就需要給所有子窗口發送刪除消息。
WM_QUIT是唯一可以使GetMessage(&msg,NULL,0,0)返回假值的消息.
相關代碼分析:
//主函數中進入消息循環的代碼片斷while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg); //將消息進行處理一下DispatchMessage(&msg); //再將消息變量msg傳給windows,讓windows來調用消息處理函數}
如果把GetMessage(&msg,NULL,0,0)改為GetMessage(&msg,hWnd,0,0),則發現關閉應用程序后,任務管理器中仍有該程序的進程,且占用大量的內存,why?
msdn中的原因解釋是:對于GetMessage(&msg,hWnd,0,0),當第二個參數無效時,此函數返回值為-1。對于上述循環來說,此while條件為真,因此進入死循環,進程無法退出。
二、各種消息投遞函數
1、SendMessage:發送消息給指定的窗口過程;直到窗口過程處理了消息才返回。
2、PostMessage:將消息放入消息隊列(與指定窗口創建的線程相關)中;無需等待消息處理,立即返回。
不能發送WM_QUIT消息,此消息只能由PostQuitMessage函數發送。
3、PostThreadMessage:發送消息給指定線程的消息隊列;無需等待線程處理消息,立即返回。
此函數發送的消息和窗口是無關的。我們只需指定線程ID就OK了,但要保證線程已創建,否則會失敗。
4、GetMessage:從調用線程的消息隊列中取消息。
當第二個參數為NULL時,它檢索以下兩種消息:
a、屬于調用線程的任何窗口的消息;
b、由PostThreadMessag投遞給該調用線程的消息。
5、PeekMessage:功能同GetMessage。區別是:
GetMessage:直到一個匹配了過濾條件的消息,被放到消息隊列中才返回。
PeekMessage:不管消息是否放入隊列,立即返回。
6、DispatchMessage:派遣消息給相應的窗口過程。
7、TranslateMessage:轉換虛擬鍵信息到字符消息。
新聞熱點
疑難解答
圖片精選