共用方式為


TN017: 終結視窗物件

這個註解,說明如何使用CWnd::PostNcDestroy方法。 如果您想要做的自訂的配置,請使用這個方法CWnd-衍生物件。 這張便箋也說明了為什麼您應該使用CWnd::DestroyWindow要終結 C++ 視窗物件,而不是delete運算子。

如果您遵循本主題中的指導方針,您必須清理的幾個問題。 這些問題可能會導致問題,例如忘記刪除/釋放的記憶體 C++,忘記釋放系統資源,如HWNDs,或釋放物件的次數過多。

問題

每個 windows 物件 (物件類別的衍生自CWnd) 表示 C++ 物件和HWND。 C + + 物件會在應用程式的堆集配置和HWNDs 由 「 視窗管理員 」 中的系統資源配置。 由於有幾種方式可以終結視窗物件,因此我們必須先提供一組規則,以避免系統資源或記憶體流失。 這些規則也必須防止物件和視窗控制代碼被摧毀一次以上。

終結視窗

以下是兩種方法允許的可以終結視窗物件:

  • 呼叫CWnd::DestroyWindow或 Windows API DestroyWindow

  • 明確地刪除與delete運算子。

如為前者是到目前為止最常見的。 這種情況下會套用,即使您的程式碼不會呼叫DestroyWindow直接。 當使用者直接關閉框架視窗時,這個動作會產生WM_CLOSE訊息,以及回應這封郵件的預設值就是呼叫DestroyWindow. 當父視窗被損毀時,Windows 就會呼叫DestroyWindow的所有子系。

第二個情況、 所用的delete運算子,在視窗物件,應該相當罕見。 下列為一些狀況下,使用delete是正確的選擇。

使用 CWnd::PostNcDestroy 的自動清除

系統會終結視窗,傳送至視窗的最後一個 Windows 訊息時, WM_NCDESTROY。 預設值CWnd該訊息的處理常式是CWnd::OnNcDestroyOnNcDestroy將卸離HWND C++ 物件,並呼叫虛擬函式PostNcDestroy。 某些類別覆寫此函式來刪除 C++ 物件。

預設實作的CWnd::PostNcDestroy不會執行任何動作,也就是適合視窗物件的堆疊框架上配置或內嵌於其他物件。 不,這也適用於視窗物件,使其可用來在不需要任何其他物件堆積上配置。 也就是說,不適合視窗不會內嵌在其他的 C++ 物件的物件。

這些設計來單獨配置在堆積上的類別會覆寫PostNcDestroy方法,以執行delete this。 此陳述式會釋放任何與 C++ 物件相關聯的記憶體。 即使預設值CWnd解構函式呼叫DestroyWindow如果m_hWnd為非 NULL,這不會導致無限遞迴因為控點時,將會中斷連結] 和 [空值清除階段。

注意事項注意事項

系統通常會呼叫CWnd::PostNcDestroy它處理 Windows 後WM_NCDESTROY訊息和HWND而不會再連線至 C++ 視窗物件。系統也會呼叫CWnd::PostNcDestroy中的大部分實作CWnd::Create發生失敗時呼叫。本主題中稍後說明的自動清除規則。

自動清除類別

下列類別並未設計為自動清除。 它們通常被內嵌在其他的 C++ 物件,或在堆疊上:

  • 所有的標準 Windows 控制項 (CStaticCEditCListBox,依此類推)。

  • 任何子視窗直接衍生自CWnd (例如,自訂控制項)。

  • 分隔視窗 (CSplitterWnd)。

  • 預設控制列 (類別衍生自CControlBar,請參閱技術提示 31 啟用自動刪除的控制項列物件)。

  • 對話方塊 (CDialog) 為強制回應對話方塊的堆疊框架上所設計。

  • 對話方塊以外的所有標準CFindReplaceDialog

  • 類別精靈所建立的預設對話方塊。

下列類別是設計用的自動清除。 它們通常是由本身配置,在堆積上:

  • 主框架視窗 (直接或間接衍生自CFrameWnd)。

  • 檢視視窗 (直接或間接衍生自CView)。

如果您想要違反這些規則,您必須覆寫PostNcDestroy您的衍生類別中的方法。 若要加入至類別的自動清理,呼叫您的基底類別,然後執行delete this。 若要移除自動清理,從您的類別,呼叫CWnd::PostNcDestroy直接代替PostNcDestroy您的直接基底類別的方法。

若要建立非強制回應對話方塊,可以配置在堆積上是最常見的用法,變更自動清除行為。

至 [刪除的呼叫

我們建議您呼叫DestroyWindow終結視窗物件,是 C++ 方法或全域DestroyWindow API。

請不要呼叫全域DestroyWindow API 來摧毀的 MDI 子視窗。 您應該使用的虛擬方法CWnd::DestroyWindow相反的。

對於 C++ 視窗物件,並不會執行自動清理,使用delete運算子會造成記憶體遺漏,當您嘗試呼叫DestroyWindowCWnd::~CWnd如果 VTBL 並未指向正確的衍生類別的解構函式。 這是因為系統找不到適當的損毀時要呼叫方法。 使用DestroyWindow而不是delete可以避免這些問題。 因為這可能非常難以捉摸的錯誤,在偵錯模式下編譯會產生下列警告如果您處於危險。

Warning: calling DestroyWindow in CWnd::~CWnd
   OnDestroy or PostNcDestroy in derived class will not be called

如果是執行自動清理的 C++ 視窗物件,您必須呼叫DestroyWindow。 如果您使用delete運算子直接,MFC 診斷記憶體配置器會通知您您會釋放記憶體兩次。 兩個是您第一次的明確呼叫和間接呼叫delete this的自動清除實作PostNcDestroy

在撥號後DestroyWindow非自動清除,在物件上的 C++ 物件仍然會,但是m_hWnd會是 NULL。 在撥號後DestroyWindow自動清理物件,C++ 物件就會消失不見,釋放 C++ delete 運算子,自動清理實作PostNcDestroy

請參閱

其他資源

技術的備忘稿編號

依類別的技術注意事項