Freigeben über


Info zu Window-Prozeduren

Jedes Fenster ist ein Element einer bestimmten Fensterklasse. Die Fensterklasse bestimmt die Standardfensterprozedur, die ein einzelnes Fenster zum Verarbeiten seiner Nachrichten verwendet. Alle Fenster, die derselben Klasse angehören, verwenden dieselbe Standardfensterprozedur. Beispielsweise definiert das System eine Fensterprozedur für die Kombinationsfeldklasse (COMBOBOX); Alle Kombinationsfelder verwenden dann diese Fensterprozedur.

Eine Anwendung registriert in der Regel mindestens eine neue Fensterklasse und die zugehörige Fensterprozedur. Nach dem Registrieren einer Klasse kann die Anwendung viele Fenster dieser Klasse erstellen, von denen alle die gleiche Fensterprozedur verwenden. Da dies bedeutet, dass mehrere Quellen gleichzeitig den gleichen Codeabschnitt aufrufen können, müssen Sie beim Ändern freigegebener Ressourcen aus einer Fensterprozedur vorsichtig sein. Weitere Informationen finden Sie unter Fensterklassen.

Fensterprozeduren für Dialogfelder (als Dialogfeldprozeduren bezeichnet) weisen eine ähnliche Struktur und Funktion als normale Fensterprozeduren auf. Alle Punkte, die auf Fensterprozeduren in diesem Abschnitt verweisen, gelten auch für Dialogfeldprozeduren. Weitere Informationen finden Sie unter Dialogfelder.

In diesem Abschnitt werden die folgenden Themen erläutert.

Struktur einer Window-Prozedur

Eine Fensterprozedur ist eine Funktion mit vier Parametern und gibt einen signierten Wert zurück. Die Parameter bestehen aus einem Fensterhandle, einem UINT-Nachrichtenbezeichner und zwei Nachrichtenparametern, die mit den Datentypen WPARAM und LPARAM deklariert wurden. Weitere Informationen finden Sie unter WindowProc.

Nachrichtenparameter enthalten häufig Informationen sowohl in ihren Wörtern mit niedriger Reihenfolge als auch in hoher Reihenfolge. Es gibt mehrere Makros, mit denen eine Anwendung Informationen aus den Nachrichtenparametern extrahieren kann. Das LOWORD-Makro extrahiert z. B. das Wort mit niedriger Reihenfolge (Bits 0 bis 15) aus einem Nachrichtenparameter. Weitere Makros sind HIWORD, LOBYTE und HIBYTE-Makro.

Die Interpretation des Rückgabewerts hängt von der jeweiligen Nachricht ab. Lesen Sie die Beschreibung jeder Nachricht, um den entsprechenden Rückgabewert zu ermitteln.

Da es möglich ist, eine Fensterprozedur rekursiv aufzurufen, ist es wichtig, die Anzahl der von ihr verwendeten lokalen Variablen zu minimieren. Bei der Verarbeitung einzelner Nachrichten sollte eine Anwendung Funktionen außerhalb der Fensterprozedur aufrufen, um übermäßige Verwendung lokaler Variablen zu vermeiden, was dazu führen kann, dass der Stapel während der tiefen Rekursion überläuft.

Standardmäßige Window-Prozedur

Die Standardmäßige Fensterprozedurfunktion DefWindowProc definiert bestimmte grundlegende Verhaltensweisen, die von allen Fenstern gemeinsam verwendet werden. Die Standardfensterprozedur stellt die minimale Funktionalität für ein Fenster bereit. Eine anwendungsdefinierte Fensterprozedur sollte alle Meldungen übergeben, die sie nicht für die Standardverarbeitung an die DefWindowProc-Funktion verarbeitet.

Erstellen von Unterklassen für Window-Prozeduren

Wenn eine Anwendung ein Fenster erstellt, weist das System einen Speicherblock zum Speichern spezifischer Informationen für das Fenster zu, einschließlich der Adresse der Fensterprozedur, die Nachrichten für das Fenster verarbeitet. Wenn das System eine Nachricht an das Fenster übergeben muss, durchsucht es die fensterspezifischen Informationen nach der Adresse der Fensterprozedur und übergibt die Nachricht an diese Prozedur.

Das Erstellen von Unterklassen ist eine Technik, mit der eine Anwendung Nachrichten abfangen und verarbeiten kann, die an ein bestimmtes Fenster gesendet oder gepostet wurden, bevor das Fenster die Möglichkeit hat, sie zu verarbeiten. Durch die Unterklassen eines Fensters kann eine Anwendung das Verhalten des Fensters erweitern, ändern oder überwachen. Eine Anwendung kann ein Fenster unterklassen, das zu einer globalen Systemklasse gehört, z. B. ein Bearbeitungssteuerelement oder ein Listenfeld. Beispielsweise könnte eine Anwendung eine Unterklasse eines Editier-Steuerelements erstellen, um zu verhindern, dass das Steuerelement bestimmte Zeichen akzeptiert. Sie können jedoch keine Unterklassen für ein Fenster oder eine Klasse unterstellen, die zu einer anderen Anwendung gehört. Alle Subklassifizierungen müssen innerhalb desselben Prozesses durchgeführt werden.

Eine Anwendung unterklassiert ein Fenster, indem die Adresse der ursprünglichen Fensterprozedur des Fensters durch die Adresse einer neuen Fensterprozedur ersetzt wird, die als Unterklassenprozedur bezeichnet wird. Danach empfängt die Unterklassenprozedur alle Nachrichten, die an das Fenster gesendet oder gepostet werden.

Die Unterklassenprozedur kann beim Empfangen einer Nachricht drei Aktionen ausführen: Sie kann die Nachricht an die ursprüngliche Fensterprozedur übergeben, die Nachricht ändern und an die ursprüngliche Fensterprozedur übergeben oder die Nachricht verarbeiten und nicht an die ursprüngliche Fensterprozedur übergeben. Wenn die Unterklassenprozedur eine Nachricht verarbeitet, kann dies vor, nach oder sowohl vor als auch nach dem Übergeben der Nachricht an die ursprüngliche Fensterprozedur erfolgen.

Das System bietet zwei Arten von Unterklassen: Instanz und global. In Instanzunterklassen ersetzt eine Anwendung die Fensterprozeduradresse einer einzelnen Instanz eines Fensters. Eine Anwendung muss Instanzunterklassen verwenden, um ein vorhandenes Fenster zu unterklassen. In globalen Unterklassen ersetzt eine Anwendung die Adresse der Fensterprozedur in der WNDCLASSEX-Struktur einer Fensterklasse. Alle nachfolgenden Fenster, die mit der Klasse erstellt wurden, weisen die Adresse der Unterklassenprozedur auf, vorhandene Fenster der Klasse sind jedoch nicht betroffen.

Erstellen von Unterklassen für Instanzen

Eine Anwendung unterklassiert eine Instanz eines Fensters mithilfe der SetWindowLongPtr-Funktion . Die Anwendung übergibt das GWL_WNDPROC-Flag, das Handle an das Fenster, für das eine Unterklasse erstellt werden woll, und die Adresse der Unterklassenprozedur an SetWindowLongPtr. Die Unterklassenprozedur kann sich entweder in der ausführbaren Datei der Anwendung oder in einer DLL befinden.

Wenn das GWL_WNDPROC-Flag übergeben wird, gibt SetWindowLongPtr die Adresse der ursprünglichen Fensterprozedur des Fensters zurück. Die Anwendung muss diese Adresse speichern, indem sie in nachfolgenden Aufrufen der CallWindowProc-Funktion verwendet wird, um abgefangene Nachrichten an die ursprüngliche Fensterprozedur zu übergeben. Die Anwendung muss auch über die ursprüngliche Fensterprozeduradresse verfügen, um die Unterklasse aus dem Fenster zu entfernen. Um die Unterklasse zu entfernen, ruft die Anwendung SetWindowLongPtr erneut auf, und übergibt die Adresse der ursprünglichen Fensterprozedur mit dem GWL_WNDPROC Flag und dem Handle an das Fenster.

Das System besitzt die globalen Systemklassen, und Aspekte der Steuerelemente können sich von einer Version des Systems zum nächsten ändern. Wenn die Anwendung ein Fenster unterklassen muss, das zu einer globalen Systemklasse gehört, muss der Entwickler die Anwendung möglicherweise aktualisieren, wenn eine neue Version des Systems veröffentlicht wird.

Da die Instanzunterklassen nach dem Erstellen eines Fensters auftreten, können Sie dem Fenster keine zusätzlichen Bytes hinzufügen. Anwendungen, die ein Fenster unterklassen, sollten die Eigenschaftenliste des Fensters verwenden, um alle Daten zu speichern, die für eine Instanz des Unterklassenfensters erforderlich sind. Weitere Informationen finden Sie unter "Window Properties".

Wenn eine Anwendung ein Unterklassenfenster unterordnet, muss sie die Unterklassen in der umgekehrten Reihenfolge entfernen, in der sie ausgeführt wurden. Wenn die Entfernungsreihenfolge nicht rückgängig gemacht wird, kann ein nicht behebbarer Systemfehler auftreten.

Globale Unterklassen

Um eine Fensterklasse global zu unterklassen, muss die Anwendung über ein Handle für ein Fenster der Klasse verfügen. Die Anwendung benötigt außerdem das Handle, um die Unterklasse zu entfernen. Zum Abrufen des Handles erstellt eine Anwendung in der Regel ein ausgeblendetes Fenster der Klasse, für das eine Unterklasse erstellt werden soll. Nach dem Abrufen des Handles ruft die Anwendung die SetClassLongPtr-Funktion auf, wobei das Handle, das GCL_WNDPROC Flag und die Adresse der Unterklassenprozedur angegeben werden. SetClassLongPtr gibt die Adresse der ursprünglichen Fensterprozedur für die Klasse zurück.

Die ursprüngliche Fensterprozeduradresse wird in der globalen Unterklassenbildung auf die gleiche Weise verwendet wie in der Instanz-Unterklassenbildung. Die Unterklassenprozedur übergibt Nachrichten an die ursprüngliche Fensterprozedur, indem CallWindowProc aufgerufen wird. Die Anwendung entfernt die Unterklasse aus der Fensterklasse, indem SetClassLongPtr erneut aufgerufen wird, wobei die Adresse der ursprünglichen Fensterprozedur, das GCL_WNDPROC-Flag und das Handle für ein Fenster der Klasse angegeben wird, die unterklassigt wird. Eine Anwendung, die global eine Steuerelementklasse unterordnet, muss die Unterklasse entfernen, wenn die Anwendung beendet wird. andernfalls kann ein nicht behebbarer Systemfehler auftreten.

Globale Unterklassen weisen die gleichen Einschränkungen wie Instanzenunterklassen sowie einige zusätzliche Einschränkungen auf. Eine Anwendung sollte nicht die zusätzlichen Bytes für die Klasse oder die Fensterinstanz verwenden, ohne genau zu wissen, wie die ursprüngliche Fensterprozedur sie verwendet. Wenn die Anwendung Daten einem Fenster zuordnen muss, sollte sie Fenstereigenschaften verwenden.

Erstellen von Unterklassen für Window-Prozeduren

Superclassing ist eine Technik, die es einer Anwendung ermöglicht, eine neue Fensterklasse mit der grundlegenden Funktionalität der vorhandenen Klasse zu erstellen, sowie Verbesserungen, die von der Anwendung bereitgestellt werden. Eine Superklasse basiert auf einer vorhandenen Fensterklasse, die als Basisklasse bezeichnet wird. Häufig ist die Basisklasse eine globale Systemfensterklasse, z. B. ein Bearbeitungssteuerelement, kann jedoch eine beliebige Fensterklasse sein.

Eine Superklasse hat eine eigene Fensterprozedur, die als Superklassenprozedur bezeichnet wird. Die Superklassenprozedur kann drei Aktionen ausführen, wenn eine Nachricht empfangen wird: Sie kann die Nachricht an die ursprüngliche Fensterprozedur übergeben, die Nachricht ändern und an die ursprüngliche Fensterprozedur übergeben oder die Nachricht verarbeiten und nicht an die ursprüngliche Fensterprozedur übergeben. Wenn die Superklassenprozedur eine Nachricht verarbeitet, kann dies vor, nach oder sowohl vor als auch nach dem Übergeben der Nachricht an die ursprüngliche Fensterprozedur erfolgen.

Im Gegensatz zu einer Unterklassenprozedur kann eine Superklassenprozedur Fenstererstellungsmeldungen verarbeiten (WM_NCCREATE, WM_CREATE usw.), aber sie müssen sie auch an die ursprüngliche Basisklassenfensterprozedur übergeben, damit die Prozedur für die Basisklassenfenster ihre Initialisierungsprozedur ausführen kann.

Zum Überklassen einer Fensterklasse ruft eine Anwendung zuerst die GetClassInfoEx-Funktion auf, um Informationen über die Basisklasse abzurufen. GetClassInfoEx füllt eine WNDCLASSEX-Struktur mit den Werten aus der WNDCLASSEX-Struktur der Basisklasse aus. Als Nächstes kopiert die Anwendung ein eigenes Instanzhandle in das hInstance-Element der WNDCLASSEX-Struktur und kopiert den Namen der Superklasse in das lpszClassName-Element . Wenn die Basisklasse über ein Menü verfügt, muss die Anwendung ein neues Menü mit denselben Menübezeichnern bereitstellen und den Menünamen in das lpszMenuName-Element kopieren. Wenn die Superklassenprozedur die WM_COMMAND Nachricht verarbeitet und nicht an die Fensterprozedur der Basisklasse übergeben wird, benötigt das Menü keine entsprechenden Bezeichner. GetClassInfoEx gibt nicht das lpszMenuName-, lpszClassName- oder hInstance-Element der WNDCLASSEX-Struktur zurück.

Eine Anwendung muss auch das lpfnWndProc-Element der WNDCLASSEX-Struktur festlegen. Die GetClassInfoEx-Funktion füllt dieses Element mit der Adresse der ursprünglichen Fensterprozedur für die Klasse aus. Die Anwendung muss diese Adresse speichern, um Nachrichten an die ursprüngliche Window-Prozedur zu übergeben, und dann die Adresse der Superklassenprozedur in das lpfnWndProc-Element kopieren. Die Anwendung kann ggf. andere Elemente der WNDCLASSEX-Struktur ändern. Nachdem sie die WNDCLASSEX-Struktur ausgefüllt hat, registriert die Anwendung die Superklasse, indem die Adresse der Struktur an die RegisterClassEx-Funktion übergeben wird. Die Superklasse kann dann zum Erstellen von Fenstern verwendet werden.

Da das Superclassing eine neue Fensterklasse registriert, kann eine Anwendung sowohl zu den zusätzlichen Klassen-Bytes als auch zu den zusätzlichen Fenster-Bytes beitragen. Die Superklasse darf nicht die ursprünglichen zusätzlichen Bytes für die Basisklasse oder das Fenster aus denselben Gründen verwenden, die eine Instanzunterklasse oder eine globale Unterklasse nicht verwenden sollte. Wenn die Anwendung zusätzliche Bytes für die Verwendung der Klasse oder der Fensterinstanz hinzufügt, muss sie auch auf die zusätzlichen Bytes relativ zur Anzahl zusätzlicher Bytes verweisen, die von der ursprünglichen Basisklasse verwendet werden. Da die Anzahl der von der Basisklasse verwendeten Bytes von einer Version der Basisklasse zum nächsten variieren kann, kann der Anfangsoffset für die zusätzlichen Bytes der Superklasse auch von einer Version der Basisklasse zum nächsten variieren.