Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Hinweis wird die Verwendung der CWnd::PostNcDestroy Methode beschrieben. Verwenden Sie diese Methode, wenn Sie eine angepasste Zuordnung von CWndabgeleiteten Objekten ausführen möchten. In diesem Hinweis wird auch erläutert, warum Sie anstelle des delete Operators ein C++-Windows-Objekt zerstören solltenCWnd::DestroyWindow.
Wenn Sie die Richtlinien in diesem Artikel befolgen, gibt es nur wenige Bereinigungsprobleme. Diese Probleme können zu Problemen führen, z. B. das Löschen/Freigeben des C++-Speichers, das Vergessen, Systemressourcen wie HWNDs freizugeben oder Objekte zu oft freizugeben.
Das Problem
Jedes Fensterobjekt (Objekt einer von ) abgeleiteten CWndKlasse stellt sowohl ein C++-Objekt als auch ein HWND. C++-Objekte werden im Heap der Anwendung zugeordnet und HWNDwerden vom Fenster-Manager in Systemressourcen zugewiesen. Da es mehrere Möglichkeiten gibt, ein Fensterobjekt zu zerstören, müssen wir eine Reihe von Regeln bereitstellen, die Systemressourcen oder Speicherverluste verhindern. Diese Regeln müssen auch verhindern, dass Objekte und Windows-Handles mehr als einmal zerstört werden.
Zerstörte Fenster
Im Folgenden sind die beiden zulässigen Methoden zum Zerstören eines Windows-Objekts aufgeführt:
Aufrufen
CWnd::DestroyWindowoder die Windows-APIDestroyWindow.Explizites Löschen mit dem
deleteOperator.
Der erste Fall ist bei weitem am häufigsten. Dieser Fall gilt auch dann, wenn Ihr Code nicht direkt aufruft DestroyWindow . Wenn der Benutzer ein Framefenster direkt schließt, generiert diese Aktion die WM_CLOSE Nachricht, und die Standardantwort auf diese Nachricht besteht darin, aufzurufen DestroyWindow. Wenn ein übergeordnetes Fenster zerstört wird, ruft Windows alle untergeordneten Elemente auf DestroyWindow .
Der zweite Fall, die Verwendung des delete Operators für Windows-Objekte, sollte selten sein. Im Folgenden sind einige Fälle aufgeführt, in denen die Verwendung delete die richtige Wahl ist.
Automatische Bereinigung mit CWnd::PostNcDestroy
Wenn das System ein Windows-Fenster zerstört, wird WM_NCDESTROYdie letzte windows-Nachricht, die an das Fenster gesendet wurde, angezeigt. Der Standardhandler CWnd für diese Nachricht lautet CWnd::OnNcDestroy.
OnNcDestroy wird das HWND vom C++-Objekt getrennt und die virtuelle Funktion PostNcDestroyaufgerufen. Einige Klassen überschreiben diese Funktion, um das C++-Objekt zu löschen.
Die Standardimplementierung von CWnd::PostNcDestroy "does nothing", die für Fensterobjekte geeignet ist, die im Stapelframe zugeordnet sind oder in andere Objekte eingebettet sind. Dieses Verhalten eignet sich nicht für Fensterobjekte, die für die Zuordnung auf dem Heap ohne andere Objekte vorgesehen sind. Das heißt, es ist nicht für Fensterobjekte geeignet, die nicht in andere C++-Objekte eingebettet sind.
Klassen, die für die Zuordnung allein für den Heap vorgesehen sind, setzen die PostNcDestroy Methode außer Kraft, um eine delete this;. Diese Anweisung gibt alle Arbeitsspeicher frei, die dem C++-Objekt zugeordnet sind. Obwohl die Standarddestruktoraufrufe DestroyWindowCWnd andernfalls m_hWnd nicht NULLerfolgen, führt dieser Aufruf nicht zu unendlicher Rekursion, da der Handle getrennt und NULL während der Bereinigungsphase getrennt wird.
Hinweis
Das System wird in der Regel aufgerufen CWnd::PostNcDestroy , nachdem die Windows-Nachricht WM_NCDESTROY verarbeitet wurde, und das HWND C++-Fensterobjekt ist nicht mehr verbunden. Das System ruft CWnd::PostNcDestroy auch die Implementierung der meisten CWnd::Create Aufrufe auf, wenn ein Fehler auftritt. Die Regeln für die automatische Bereinigung werden weiter unten in diesem Artikel beschrieben.
Automatische Bereinigungsklassen
Die folgenden Klassen sind nicht für die automatische Bereinigung konzipiert. Sie sind in der Regel in andere C++-Objekte oder auf dem Stapel eingebettet:
Alle standardmäßigen Windows-Steuerelemente (
CStatic,CEdit,CListBoxusw.).Alle untergeordneten Fenster, die direkt von
CWnd(z. B. benutzerdefinierten Steuerelementen) abgeleitet werden.Splitterfenster (
CSplitterWnd).Standardsteuerungsleisten (klassen abgeleitet,
CControlBarsiehe Technisches Hinweis 31 zum Aktivieren der automatischen Löschung für Steuerelementleistenobjekte).Dialoge (
CDialog) entwickelt für modale Dialogfelder im Stapelframe.Alle Standarddialogfeld mit Ausnahme
CFindReplaceDialogvon .Die standarddialogischen Dialogfelder, die von ClassWizard erstellt wurden.
Die folgenden Klassen sind für die automatische Bereinigung konzipiert. Sie werden in der Regel selbst auf dem Heap zugeordnet:
Hauptrahmenfenster (direkt oder indirekt von
CFrameWnd).Ansichtsfenster (direkt oder indirekt von
CView).
Wenn Sie diese Regeln unterbrechen möchten, müssen Sie die PostNcDestroy Methode in der abgeleiteten Klasse überschreiben. Rufen Sie die Basisklasse auf, um Ihrem Kurs die automatische Bereinigung hinzuzufügen, und führen Sie dann eine delete this;. Um die automatische Bereinigung aus Ihrer Klasse zu entfernen, rufen Sie direkt anstelle der PostNcDestroy Methode Der direkten Basisklasse aufCWnd::PostNcDestroy.
Die am häufigsten verwendete Verwendung des Verhaltens der automatischen Bereinigung besteht darin, ein modusloses Dialogfeld zu erstellen, das für den Heap zugewiesen werden kann.
Wann wird angerufen? delete
Es wird empfohlen, ein DestroyWindow Windows-Objekt zu zerstören, entweder die C++-Methode oder die globale DestroyWindow API.
Rufen Sie die globale DestroyWindow API nicht auf, um ein untergeordnetes MDI-Fenster zu zerstören. Stattdessen sollten Sie die virtuelle Methode CWnd::DestroyWindow verwenden.
Bei C++-Fensterobjekten, die keine automatische Bereinigung durchführen, kann die Verwendung des delete Operators einen Speicherverlust verursachen, wenn Sie versuchen, den CWnd::~CWnd Destruktor aufzurufenDestroyWindow, wenn dies VTBL nicht auf die ordnungsgemäß abgeleitete Klasse verweist. Das Leck tritt auf, da das System die entsprechende Zerstörungsmethode nicht finden kann, die aufgerufen werden soll. Die Verwendung DestroyWindow anstelle dieser delete Probleme wird vermieden. Da dieser Fehler subtil sein kann, generiert das Kompilieren im Debugmodus die folgende Warnung, wenn Sie gefährdet sind.
Warning: calling DestroyWindow in CWnd::~CWnd
OnDestroy or PostNcDestroy in derived class will not be called
Für C++-Windows-Objekte, die die automatische Bereinigung ausführen, müssen Sie aufrufen DestroyWindow. Wenn Sie den Operator direkt verwenden, benachrichtigt Sie der MFC-Diagnosespeicher-Allocator, dass Sie Arbeitsspeicher zweimal freigeben.If you use the delete operator directly, the MFC diagnostic memory allocator will notify you're two times. Die beiden Vorkommen sind Ihr erster expliziter Aufruf und der indirekte Aufruf delete this; in der Automatischen Bereinigungsimplementierung von PostNcDestroy.
Nachdem Sie ein Nicht-Auto-Bereinigungsobjekt aufgerufen DestroyWindow haben, befindet sich das C++-Objekt weiterhin, ist aber m_hWnd vorhanden NULL. Nachdem Sie ein AutoBereinigungsobjekt aufgerufen DestroyWindow haben, ist das C++-Objekt nicht mehr vorhanden, das vom C++-Löschoperator in der Automatischen Bereinigungsimplementierung freigegeben PostNcDestroywird.
Siehe auch
Technische Hinweise nach Nummer
Technische Hinweise nach Kategorie