Sdílet prostřednictvím


TN017: Zničení objektů oken

Tato poznámka popisuje použití CWnd::PostNcDestroy metody. Tuto metodu použijte, pokud chcete provést přizpůsobené přidělení CWnd-odvozených objektů. Tato poznámka také vysvětluje, proč byste místo operátoru měli použít CWnd::DestroyWindow ke zničení objektu delete systému Windows C++.

Pokud budete postupovat podle pokynů v tomto článku, budete mít několik problémů s vyčištěním. Tyto problémy můžou mít za následek problémy, jako je například zapomenutí nebo uvolnění paměti jazyka C++, zapomeňte na volné systémové prostředky, jako jsou HWNDs nebo uvolnění objektů příliš mnohokrát.

Problém

Každý objekt windows (objekt třídy odvozené ) CWndpředstavuje objekt jazyka C++ i objekt HWND. Objekty C++ jsou přiděleny v haldě aplikace a HWNDjsou přiděleny v systémových prostředcích správcem oken. Protože existuje několik způsobů, jak zničit objekt okna, musíme poskytnout sadu pravidel, která brání úniku systémového prostředku nebo paměti. Tato pravidla také musí zabránit zničení objektů a obslužných rutin Systému Windows vícekrát.

Zničení oken

Následující dva povolené způsoby zničení objektu Systému Windows:

  • Volání CWnd::DestroyWindow nebo rozhraní API DestroyWindowsystému Windows .

  • Explicitní odstranění pomocí operátoru delete

První případ je zdaleka nejběžnější. Tento případ platí i v případě, že váš kód nevolá DestroyWindow přímo. Když uživatel přímo zavře okno rámce, tato akce vygeneruje WM_CLOSE zprávu a výchozí odpověď na tuto zprávu je volání DestroyWindow. Když je nadřazené okno zničeno, systém Windows volá DestroyWindow všechny jeho podřízené položky.

Druhý případ, použití operátoru delete na objektech Windows, by mělo být vzácné. Tady jsou některé případy, kdy je použití delete správnou volbou.

Automatické vyčištění pomocí CWnd::PostNcDestroy

Když systém zničí okno systému Windows, poslední zpráva systému Windows poslaná do okna je WM_NCDESTROY. Výchozí CWnd obslužná rutina pro tuto zprávu je CWnd::OnNcDestroy. OnNcDestroy odpoje od HWND objektu C++ a zavolá virtuální funkci PostNcDestroy. Některé třídy tuto funkci přepíší, aby se odstranil objekt C++.

Výchozí implementace CWnd::PostNcDestroy nedělá nic, což je vhodné pro objekty okna, které jsou přiděleny na rámec zásobníku nebo vložené v jiných objektech. Toto chování není vhodné pro objekty oken navržené pro přidělení haldy bez jakýchkoli jiných objektů. Jinými slovy, není vhodné pro objekty okna, které nejsou vloženy do jiných objektů jazyka C++.

Třídy určené pro přidělení samotné haldy přepíší PostNcDestroy metodu delete this;k provedení . Tento příkaz uvolní veškerou paměť přidruženou k objektu C++. I když výchozí CWnd destruktor volá DestroyWindow , pokud m_hWnd není NULL, toto volání nezpůsobí nekonečné rekurze, protože popisovač bude odpojen a NULL během fáze čištění.

Poznámka

Systém obvykle volá poté CWnd::PostNcDestroy , co zpracuje zprávu systému Windows WM_NCDESTROY a HWND objekt okna C++ již nejsou připojeny. Systém bude také volat CWnd::PostNcDestroy při implementaci většiny CWnd::Create volání, pokud dojde k selhání. Pravidla automatického čištění jsou popsána dále v tomto článku.

Třídy automatického čištění

Následující třídy nejsou určené pro automatické vyčištění. Obvykle se vkládají do jiných objektů C++ nebo do zásobníku:

  • Všechny standardní ovládací prvky Systému Windows (CStatic, CEdit, CListBoxatd.)

  • Všechna podřízená okna odvozená přímo z CWnd (například vlastních ovládacích prvků).

  • Rozdělovačová okna (CSplitterWnd).

  • Výchozí řídicí pruhy (třídy odvozené z CControlBar, viz Technická poznámka 31 pro povolení automatického odstranění pro objekty řídicího pruhu).

  • Dialogy (CDialog) navržené pro modální dialogy v rámci zásobníku

  • Všechny standardní dialogy s výjimkou CFindReplaceDialog.

  • Výchozí dialogy vytvořené pomocí TřídyWizard.

Následující třídy jsou navržené pro automatické vyčištění. Obvykle se přidělují sami na haldě:

  • Okna hlavního rámu (odvozená přímo nebo nepřímo z CFrameWnd).

  • Zobrazit okna (odvozená přímo nebo nepřímo z CView).

Pokud chcete tato pravidla přerušit, musíte přepsat metodu PostNcDestroy v odvozené třídě. Pokud chcete do třídy přidat automatické vyčištění, zavolejte základní třídu a pak udělejte .delete this; Pokud chcete z třídy odebrat automatické vyčištění, volejte CWnd::PostNcDestroy přímo místo PostNcDestroy metody přímé základní třídy.

Nejběžnějším použitím změny chování automatického čištění je vytvoření bezmodální dialogové okno, které lze přidělit na haldě.

Kdy zavolat delete

Doporučujeme volat DestroyWindow , abyste zničili objekt Windows, buď metodu C++, nebo globální DestroyWindow rozhraní API.

Nevolejte globální DestroyWindow rozhraní API ke zničení podřízeného okna MDI. Místo toho byste měli použít virtuální metodu CWnd::DestroyWindow .

U objektů okna C++, které neprovádějí automatické vyčištění, může použití operátoru delete způsobit nevracení paměti při pokusu CWnd::~CWnd o volání DestroyWindow v destruktoru, pokud VTBL neodkazuje na správnou odvozenou třídu. K úniku dochází, protože systém nemůže najít odpovídající metodu zničení, která se má volat. Místo DestroyWindow toho, abyste delete se těmto problémům vyhnuli, použijte. Protože tato chyba může být malá, kompilace v režimu ladění vygeneruje následující upozornění, pokud jste ohroženi.

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

U objektů systému Windows C++, které provádějí automatické vyčištění, je nutné volat DestroyWindow. Pokud operátor použijete delete přímo, alokátor diagnostické paměti MFC vás upozorní, že uvolníte paměť dvakrát. Dva výskyty jsou vaše první explicitní volání a nepřímé volání delete this; v implementaci PostNcDestroyautomatického vyčištění .

Po volání DestroyWindow objektu bez automatického vyčištění bude objekt C++ stále kolem, ale m_hWnd bude NULL. Po volání DestroyWindow objektu automatického vyčištění bude objekt C++ pryč, uvolněn operátorem odstranění jazyka C++ v implementaci automatického PostNcDestroyvyčištění .

Viz také

Technické poznámky podle čísla
Technické poznámky podle kategorie