MFC視窗的清除過程[轉]
對於vc++初學者來說,總覺得視窗物件的清除過程有些莫名其妙.在程式中看不到對delete的顯式呼叫,這似乎違反了c++中有關初始化和清除的規則.那麼,程式是怎樣取消一個視窗物件?
要消除視窗物件,必須清楚視窗物件的構成.在一個通常的程式中,先建立c++視窗物件,然後由Windows建立實際的視窗結構,並返回控制代碼與c++物件連線.也就是說,視窗物件包含c++視窗物件和Windows視窗物件,兩者通過控制代碼HWND聯絡.
現在,讓我們看看"正規"的視窗物件清除流程.所謂物件的清除是指釋放物件所佔的資源,視窗物件中Windows視窗物件佔有的是系統資源,c++物件佔有的是記憶體資源.釋放系統資源相對要簡單一些:呼叫虛擬函式DestroyWindow刪除Windows視窗物件.如果DestroyWindow刪除的是父視窗,Windows會自動為子視窗呼叫DestroyWindow.一般來說,程式不必呼叫DestroyWindow.因為當用戶關閉視窗時,Windows便傳送WM_CLOSE訊息,WM_CLOSE的預設訊息處理函式CWnd::OnClose呼叫DestroyWindow.
到這時,清除工作已經完成了一半,螢幕上的視窗已經不見了!但是別忘了,在記憶體中還有一個c++視窗物件.讓我們再看看c++物件清除的過程:當視窗被取消時,視窗最後傳送的一個訊息是WM_NCDESTROY.它預設的訊息處理函式CWnd::OnNcDestroy把c++視窗物件與控制代碼HWND分離,並呼叫一個很重要的虛擬函式PostNcDestroy.這個函式是搞清視窗物件清除的關鍵.Cwnd中的PostNcDestroy什麼都不做.有些MFC視窗類會過載它,並加入delete this程式碼刪除c++物件.這些視窗類常常是以new操作符建立在堆中的.由於過載了PostNcDestroy,使視窗有自動清除功能.因此,我們不用關心清除問題了.另外的一些MFC視窗類一般是以變數形式建立的,MFC沒有為也沒必要為它們過載PostNcDestroy函式.
不具備自動清除功能的視窗類,一般在堆疊中建立或嵌入於其它c++物件中:
所有標準的Windows控制元件類(如CStatic, CEdit, CListBox等等)
由CWnd類直接派生出來的子視窗物件(如使用者定製的控制元件)
拆分視窗類(CSplitterWnd)
預設的控制條類(CControlBar的派生類)
對話方塊類(CDialog)在堆疊上建立的模態對話方塊類
所有的Windows通用對話方塊(除CFindReplaceDialog)
由ClassWizard建立的對話方塊
具有自動清除功能的視窗類,一般在堆中建立:
主框架視窗類(直接或間接從CFrameWnd類派生)
檢視類(直接或間接從CView類派生)
從某種程度上來說,MFC的"服務到家"使初學者有些找不著北.不過,不得不承認:MFC乾的很漂亮!
談到這裡,我們應該明白c++裡一條重要的準則:用DestroyWindow清除視窗物件,不要用"delete".
對於不具備自動清除功能的視窗類使用"delete"時,"delete"先呼叫解構函式裡的DestroyWindow,由於在解構函式中,虛機制不起作用,這裡只能呼叫本地版本(Cwnd類)DestroyWindow函式,顯然這不是我們想要的.對於有自動清除功能的視窗類,好象問題更嚴重一點,前面提到了過載的PostNcDestroy已經含有了"delete this",這樣c++物件就被釋放了兩次.
很多人認為,vc++同vb一樣,是一個完全視覺化的產品,不用在看c++的書了.通過上面對視窗物件的清除的介紹,可以發現,Windows程式是與Windows緊密結合的,而且牽涉到很多c++的知識(如虛擬函式、解構函式、new操作符等).要對vc++有進一步理解,必須理解Windows機制,深入學習c++.
posted on 2009-02-11 10:50 大海 閱讀(660) 評論(0) 編輯 收藏 引用 所屬分類: VC++