天天看點

WM_CLOSE、WM_DESTROY、WM_QUIT學習總結(點選關閉按鈕會觸發WM_CLOSE消息,DestroyWindow API會觸發WM_DESTROY和WM_NCDESTROY消息,MSDN上寫的很清楚)

WM_CLOSE:關閉應用程式視窗

WM_DESTROY:關閉應用程式

WM_QUIT:關閉消息循環

隻有關閉了消息循環,應用程式的程序才真正退出(在任務管理器裡消失)。

win32應用程式的完整退出過程:點選視窗右上角的關閉按鈕,發送WM_CLOSE消息。此消息進行中調用DestroyWindow函數,發送WM_DESTROY消息。此消息進行中調用PostQuitMessage(0)函數,發送WM_QUIT消息到消息隊列中。GetMessage捕獲到WM_QUIT,傳回0,退出循環(應用程式真正退出)。

tips:按照上述正常流程,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條件為真,是以進入死循環,程序無法退出。

http://hhfighting.blog.163.com/blog/static/5570032320108215323797/

---------------------------------------------------------------------------------------------------------------

VCL裡相應的代碼:

還有:

DestroyWindow函數來自這裡(TApplication.Destroy裡也調用了這個函數):

那難道每個TButton,每個TPanel,都會收到WM_DESTROY消息嗎?