Udostępnij za pośrednictwem


TN017: likwidowanie obiektów okien

Uwaga ta opisuje korzystanie z CWnd::PostNcDestroy metody.Użyć tej metody, jeśli chcesz zrobić dostosowanych alokacji CWnd-pochodnych obiektów.Uwaga ta także wyjaśnia, dlaczego warto korzystać CWnd::DestroyWindow do niszczenia obiektu C++ Windows, a nie delete operatora.

Jeśli zastosujesz wskazówki zawarte w tym temacie, masz kilka problemów oczyszczania.Te problemy mogą wynikać z takich zagadnień, jak zapominanie delete/zwolnić pamięć C++, zapominając zwolnić zasoby systemowe, takie jak HWNDs lub zwalniania obiektów zbyt wiele razy.

Problem

Każdy obiekt systemu windows (obiekt klasy pochodne CWnd) reprezentuje obiekt C++ i HWND.Z obiektami C++ są przydzielane w stercie aplikacji i HWNDs są przydzielane w zasoby systemowe przez Menedżera okien.Ponieważ istnieje kilka sposobów, aby zniszczyć obiekt window, musimy zapewnić zbiór zasad, które uniemożliwiają system przecieków zasobów lub pamięci.Zasady te muszą również uniemożliwić obiektów i uchwyty Windows niszczone więcej niż jeden raz.

Niszczenie systemu Windows

Oto dwa sposoby dozwolonych zniszczyć obiektu systemu Windows:

  • Wywołanie CWnd::DestroyWindow lub Windows API DestroyWindow.

  • Usuwanie jawnie za pomocą delete operatora.

Pierwszy przypadek jest zdecydowanie najczęściej.Ten przypadek dotyczy, nawet jeśli kod nie wywoływać DestroyWindow bezpośrednio.Gdy użytkownik zamyka bezpośrednio okno ramek, Akcja ta spowoduje wygenerowanie WM_CLOSE wiadomość i domyślną odpowiedź na tę wiadomość jest wywołanie DestroyWindow. , gdy okno nadrzędne ulega zniszczeniu, system Windows wywołuje DestroyWindow dla wszystkich jego obiektów podrzędnych.

Drugi przypadek, korzystanie z delete operatora na obiekty systemu Windows powinien być rzadko.Są następujące niektórych przypadków, w których za pomocą delete z pozoru.

Automatyczne oczyszczanie z CWnd::PostNcDestroy

Gdy system niszczy okna systemu Windows, ostatni komunikat systemu Windows wysyłane do okna jest WM_NCDESTROY.Domyślnie CWnd obsługi dla tej wiadomości jest CWnd::OnNcDestroy.OnNcDestroybędzie odłączyć HWND z C++ object i wywołać funkcję wirtualnych PostNcDestroy.Niektóre klasy zastępują funkcja ta służy do usuwania obiektu języka C++.

Domyślna implementacja z CWnd::PostNcDestroy nic nie robi, który jest odpowiedni do obiektów okna, które są rozdzielone na ramek stosu lub osadzone w innych obiektach.Nie jest to właściwe dla obiektów okna, które są przeznaczone do przydzielenia na stercie bez żadnych innych obiektów.Innymi słowy nie jest właściwe dla obiektów okna, które nie są osadzone w innych obiektów języka C++.

Zastąpienie tych klas, które są przeznaczone do przydzielenia samodzielnie na stercie PostNcDestroy metoda do wykonywania delete this.Ta instrukcja zwolni wszystkie pamięci skojarzone z obiektem C++.Mimo że wartość domyślna CWnd wywołania destruktora DestroyWindow Jeśli m_hWnd jest NIEZEROWE, nie prowadzi do nieskończonej rekursji ponieważ dojście będą odłączane, a wartości NULL podczas fazy oczyszczania.

[!UWAGA]

Zwykle wymaga systemu CWnd::PostNcDestroy po przetwarza on Windows WM_NCDESTROY wiadomości i HWND i obiekt window C++ nie jest już połączony.System będzie również wzywać CWnd::PostNcDestroy w celu wykonania większości CWnd::Create wywołuje, jeśli wystąpi awaria.Reguł automatycznego oczyszczania są opisane w dalszej części tego tematu.

Automatyczne oczyszczanie klas

Poniższe klasy nie są przeznaczone do automatycznego oczyszczania.Są one zazwyczaj osadzone w innych obiektów języka C++ lub na stosie:

  • Wszystkich standardowych formantów systemu Windows (CStatic, CEdit, CListBox, i tak dalej).

  • Wszelkie okien podrzędnych pochodzi bezpośrednio z CWnd (na przykład formantów niestandardowych).

  • Windows rozdzielacza (CSplitterWnd).

  • Domyślnie paski sterowania (pochodną klasy CControlBar, zobacz technicznej 31 Uwaga umożliwiających automatyczne usuwanie obiektów pasek sterowania).

  • Okna dialogowe (CDialog) przeznaczony dla modalnych okien dialogowych w klatce stosu.

  • Wszystkie standardowe okna dialogowe z wyjątkiem CFindReplaceDialog.

  • Domyślne okien dialogowych utworzonych przez ClassWizard.

Poniższe klasy przeznaczone są do automatycznego oczyszczania.Zazwyczaj są im przydzielane przez siebie na stercie:

  • Ramka głównej systemu windows (pochodzące bezpośrednio lub pośrednio z CFrameWnd).

  • Wyświetlanie okien (pochodzące bezpośrednio lub pośrednio z CView).

Jeśli chcesz przerwać te reguły, należy zastąpić PostNcDestroy metoda w klasie pochodnej.Aby dodać automatycznego oczyszczania do swojej klasy, wywołanie klasy podstawowej, a następnie wykonaj delete this.Aby usunąć automatyczne oczyszczanie z klasy, wywołaj CWnd::PostNcDestroy bezpośrednio zamiast z PostNcDestroy metoda bezpośrednia klasa podstawowa.

Najczęstszym zastosowaniem Zmiana zachowania Oczyszczanie automatyczne jest utworzenie niemodalne okno dialogowe, która może być alokowana na stercie.

Kiedy należy usunąć wywołanie

Firma Microsoft zaleca, aby wywołać DestroyWindow do niszczenia obiektu Windows, Metoda C++ lub globalnym DestroyWindow interfejsu API.

Nie wywołuj globalnym DestroyWindow interfejsu API w celu zniszczenia okno potomne MDI.Należy użyć metody virtual CWnd::DestroyWindow w zamian.

Dla okna C++ obiektów, które nie wykonują automatyczne oczyszczanie, za pomocą delete operator może spowodować przeciek pamięci podczas próby wywołania DestroyWindow w CWnd::~CWnd destruktor, jeśli VTBL nie wskazuje klasy pochodnej poprawnie.Dzieje się tak, ponieważ system nie może znaleźć odpowiedniego zniszczyć metodę do wywołania.Za pomocą DestroyWindow zamiast delete pozwala uniknąć tych problemów.Ponieważ może to być błąd delikatny, kompilacji w trybie debugowania będzie generować następujące ostrzeżenie Jeśli jesteś w niebezpieczeństwie.

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

W przypadku obiektów systemu Windows w języku C++, które należy wykonywać automatyczne oczyszczanie, musisz wywołać DestroyWindow.Jeśli używasz delete operatora bezpośrednio, program przydzielania pamięci diagnostycznych MFC wyświetli powiadomienie, że można są zwalnianiu pamięci dwa razy.Dwa wystąpienia są Twoje pierwsze wywołanie jawne i pośrednich wywołania delete this w wykonaniu automatycznego oczyszczania PostNcDestroy.

Po wywołaniu DestroyWindow w obiekcie oczyszczania non auto, obiekt C++ nadal będzie się wokół, ale m_hWnd będzie mieć wartość NULL.Po wywołaniu DestroyWindow do obiektu automatycznego oczyszczania, obiekt C++ zniknie, zwolniona przez operatora delete C++ w realizacji automatycznego oczyszczania PostNcDestroy.

Zobacz też

Inne zasoby

Uwagi techniczne według numerów

Uwagi techniczne według kategorii