TN017: Likvidace objektů oken
Tato poznámka popisuje použití CWnd::PostNcDestroy metody.Tuto metodu použijte, pokud chcete provést vlastní rozdělení CWnd-odvozené objekty.Tato poznámka také vysvětluje, proč byste měli používat CWnd::DestroyWindow ke zničení objektu C++ Windows namísto delete operátor.
Pokud budete postupovat podle pokynů v tomto tématu, budete mít několik problémů vyčištění.Tyto problémy mohou být výsledkem problémy zapomenutí delete/uvolnit paměť C++, že zapomenete uvolněte systémové prostředky jako HWNDs nebo uvolnění objektů mnohokrát.
Problém
Každý objekt systému windows (objekt třídy odvozené z CWnd) představuje objekt jazyka C++ a HWND.Objektů jazyka C++ jsou přidělené haldy aplikace a HWNDs přiděluje prostředky systému správce oken.Existuje několik způsobů, jak zničit objektu okna, musí nabízíme sadu pravidel, která brání systému netěsnosti prostředků nebo paměti.Tato pravidla musí rovněž zabránit objektů a systému Windows zpracovává zničen více než jednou.
Zničení systému Windows
Následují dva povolené způsoby zničení objektu systému Windows:
Volání CWnd::DestroyWindow rozhraní API systému Windows nebo DestroyWindow.
Odstranění explicitně pomocí delete operátor.
Prvním případě je zdaleka nejčastější.Tento případ se týká i v případě, že váš kód nevolá DestroyWindow přímo.Když uživatel zavře přímo okno rámce, tato akce vytvoří WM_CLOSE zpráv a výchozí odpověď na tuto zprávu je volat DestroyWindow. když nadřazené okno je zničen, volání Windows DestroyWindow pro všechny jeho podřízené položky.
Druhém případě, použití delete operátor u objektů systému Windows by měla být vzácné.V následujícím textu jsou některé případy, kde pomocí delete je správná volba.
Automatické čištění s CWnd::PostNcDestroy
Systém ničí okna systému Windows, je poslední zprávy systému Windows odesílány do okna WM_NCDESTROY.Ve výchozím nastavení CWnd obslužné rutiny pro tuto zprávu je CWnd::OnNcDestroy.OnNcDestroybude odpojit HWND ze C++ objektu a volání virtuální funkce PostNcDestroy.Některé třídy přepsat tuto funkci Odstranit objekt jazyka C++.
Výchozí implementace CWnd::PostNcDestroy neprovede nic, což je vhodné pro okna jsou přiděleny v zásobníku nebo objekty vložené do jiných objektů.To není vhodné pro okno objekty, které mají být přiděleny na haldě bez dalších objektů.Jinými slovy není vhodné pro okno objekty, které nejsou vloženy do jiných objektů jazyka C++.
Přepsat tyto třídy, které mají být samostatně přiděleny na haldě modulu PostNcDestroy metoda provádět delete this.Tento příkaz bude bez jakékoliv paměti, přidružený objekt jazyka C++.Přestože výchozí CWnd volání destruktoru DestroyWindow -li m_hWnd je NENULOVÝ, to nevede k nekonečnému opakování protože popisovač bude odpojena a NULL během fáze čištění.
[!POZNÁMKA]
Systém obvykle volá CWnd::PostNcDestroy po zpracování systému Windows WM_NCDESTROY zpráva a HWND a okno objekt jazyka C++ jsou již připojeny.Systém bude také volat CWnd::PostNcDestroy při provádění většiny CWnd::Create zavolá, pokud dojde k selhání.Pravidla automatického čištění jsou popsány dále v tomto tématu.
Automatické vyčištění třídy
Následující třídy není určen pro automatické vyčištění.Obvykle jsou vloženy v jiné objekty v C++ nebo v zásobníku:
Všechny standardní ovládací prvky systému Windows (CStatic, CEdit, CListBoxa tak dále).
Všech podřízených oken odvozena přímo z CWnd (například vlastní ovládací prvky).
Rozdělovač windows (CSplitterWnd).
Výchozí ovládací panely (třídy odvozené z CControlBar, viz Technická poznámka: 31 umožňující automatické odstranění objekty ovládacích panelů).
Dialogy (CDialog) určen pro modální dialogová okna v zásobníku.
Všechny standardní dialogová okna s výjimkou CFindReplaceDialog.
Výchozí dialogy vytvořené ClassWizard.
Tyto třídy jsou určeny pro automatické vyčištění.Obvykle samy o sobě jsou přidělovány na haldě:
Hlavní rámec windows (odvozeny přímo nebo nepřímo z CFrameWnd).
Zobrazení systému windows (odvozeny přímo nebo nepřímo z CView).
Pokud chcete zrušit tato pravidla, je nutné přepsat PostNcDestroy metoda v odvozené třídě.Automatické vyčištění přidat do vaší třídy, volat základní třídy a potom proveďte delete this.Automatické vyčištění odebrat z vaší třídy, volat CWnd::PostNcDestroy přímo místo nebo PostNcDestroy metody základní třídy přímé.
Nejčastěji změny chování automatického vyčištění je vytváření nemodální dialogové okno, které mohou být přiděleny na haldě.
Když na volání delete
Doporučujeme volat DestroyWindow zničit Windows objekt, metoda C++ nebo globální DestroyWindow rozhraní API.
Nevolejte globální DestroyWindow rozhraní API ke zničení MDI podřízené okno.Byste měli použít virtuální metody CWnd::DestroyWindow místo.
Pro okno C++ objekty Neprovádět automatické čištění, použití delete operátor může způsobit nevracení paměti při pokusu o volání DestroyWindow v CWnd::~CWnd destruktor Pokud VTBL neukazuje správně odvozené třídy.K tomu dochází, protože systém nemůže nalézt že odpovídající metodu volat zničit.Pomocí DestroyWindow místo delete se vyhnete těmto problémům.Vzhledem k tomu, může to být drobný chyby kompilace v režimu ladění vygeneruje následující upozornění Pokud jste v nebezpečí.
Warning: calling DestroyWindow in CWnd::~CWnd
OnDestroy or PostNcDestroy in derived class will not be called
V případě C++ Windows objekty, které provádějí automatické vyčištění, musíte zavolat DestroyWindow.Použijete-li delete operátor přímo, přidělování diagnostiku paměti MFC vás upozorní, že jste se uvolňování paměti dvakrát.Dva výskyty jsou první explicitní volání a nepřímé volání delete this při provádění automatického čištění PostNcDestroy.
Po volání DestroyWindow u objektu automatického vyčištění objekt jazyka C++ bude kolem, ale m_hWnd bude mít hodnotu NULL.Po volání DestroyWindow automatické vyčištění objektu, objekt jazyka C++ bude pryč, uvolněných operátor delete jazyka C++ v provedení automatické vyčištění PostNcDestroy.