Steuerelemente für Unterklassen
Wenn ein Steuerelement fast alles tut, was Sie möchten, sie aber einige weitere Features benötigen, können Sie das ursprüngliche Steuerelement ändern oder Features hinzufügen, indem Sie es unterklassieren. Eine Unterklasse kann über alle Features einer vorhandenen Klasse sowie über alle zusätzlichen Features verfügen, die Sie bereitstellen möchten.
In diesem Dokument wird erläutert, wie Unterklassen erstellt werden, und es werden die folgenden Themen behandelt.
- Unterklassensteuerelemente vor ComCtl32.dll Version 6
- Unterklassensteuerelemente mit ComCtl32.dll Version 6
Unterklassensteuerelemente vor ComCtl32.dll Version 6
Sie können ein Steuerelement in einer Unterklasse platzieren und Benutzerdaten in einem Steuerelement speichern. Dies geschieht, wenn Sie Versionen von ComCtl32.dll vor Version 6 verwenden. Es gibt einige Nachteile beim Erstellen von Unterklassen mit früheren Versionen von ComCtl32.dll.
Um ein neues Steuerelement zu erstellen, empfiehlt es sich, mit einem der allgemeinen Windows-Steuerelemente zu beginnen und es entsprechend einer bestimmten Anforderung zu erweitern. Um ein Steuerelement zu erweitern, erstellen Sie ein Steuerelement, und ersetzen Sie dessen vorhandene Fensterprozedur durch ein neues. Die neue Prozedur fängt die Nachrichten des Steuerelements ab und handelt entweder auf sie ein oder übergibt sie zur Standardverarbeitung an die ursprüngliche Prozedur. Verwenden Sie die Funktion SetWindowLong oder SetWindowLongPtr , um den WNDPROC des Steuerelements zu ersetzen. Im folgenden Codebeispiel wird gezeigt, wie Ein WNDPROC ersetzt wird.
OldWndProc = (WNDPROC)SetWindowLongPtr (hButton,
GWLP_WNDPROC, (LONG_PTR)NewWndProc);
Speichern von Benutzerdaten
Möglicherweise möchten Sie Benutzerdaten mit einem einzelnen Fenster speichern. Diese Daten können von der neuen Fensterprozedur verwendet werden, um zu bestimmen, wie das Steuerelement gezeichnet oder wohin bestimmte Nachrichten gesendet werden sollen. Sie können beispielsweise Daten verwenden, um einen C++-Klassenzeiger auf die Klasse zu speichern, die das Steuerelement darstellt. Im folgenden Codebeispiel wird gezeigt, wie Sie SetProp verwenden, um Daten in einem Fenster zu speichern.
SetProp (hwnd, TEXT("MyData"), (HANDLE)pMyData);
Nachteile des alten Unterklassenansatzes
Die folgende Liste zeigt einige der Nachteile der Verwendung des zuvor beschriebenen Ansatzes für die Unterklassifizierung eines Steuerelements.
- Die Fensterprozedur kann nur einmal ersetzt werden.
- Es ist schwierig, eine Unterklasse zu entfernen, nachdem sie erstellt wurde.
- Das Zuordnen privater Daten zu einem Fenster ist ineffizient.
- Um die nächste Prozedur in einer Unterklassenkette aufzurufen, können Sie die alte Fensterprozedur nicht umwandeln und aufrufen. Sie müssen sie mit der CallWindowProc-Funktion aufrufen.
Unterklassensteuerelemente mit ComCtl32.dll Version 6
Hinweis
ComCtl32.dll Version 6 ist nur Unicode. Die allgemeinen Steuerelemente, die von ComCtl32.dll Version 6 unterstützt werden, sollten nicht mit ANSI-Fensterprozeduren Unterklassen (oder superklassig) sein.
ComCtl32.dll Version 6 enthält vier Funktionen, die das Erstellen von Unterklassen vereinfachen und die zuvor beschriebenen Nachteile beseitigen. Die neuen Funktionen kapseln die Verwaltung, die mit mehreren Verweisdatensätzen verbunden ist, daher kann sich der Entwickler auf programmierfeatures konzentrieren und nicht auf die Verwaltung von Unterklassen. Die Unterklassenfunktionen sind:
SetWindowSubclass
Diese Funktion wird verwendet, um ein Fenster zunächst unterzuklassieren. Jede Unterklasse wird durch die Adresse der pfnSub-Klasse und ihrer uIdSub-Klasse eindeutig identifiziert. Beides sind Parameter der SetWindowSubclass-Funktion . Mehrere Unterklassen können dieselbe Unterklassenprozedur gemeinsam nutzen, und die ID kann jeden Aufruf identifizieren. Um Verweisdaten zu ändern, können Sie nachfolgende Aufrufe von SetWindowSubclass ausführen. Der wichtige Vorteil besteht darin, dass jede Unterklasse instance über eigene Verweisdaten verfügt.
Die Deklaration einer Unterklassenprozedur unterscheidet sich geringfügig von einer regulären Fensterprozedur, da sie zwei zusätzliche Datenelemente enthält: die Unterklassen-ID und die Verweisdaten. Die letzten beiden Parameter der folgenden Funktionsdeklaration zeigen dies.
LRESULT CALLBACK MyWndProc (HWND hWnd, UINT msg,
WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass,
DWORD_PTR dwRefData);
Jedes Mal, wenn eine Nachricht von der neuen Fensterprozedur empfangen wird, werden eine Unterklassen-ID und Verweisdaten eingeschlossen.
Hinweis
Alle an die Prozedur übergebenen Zeichenfolgen sind Unicode-Zeichenfolgen, auch wenn Unicode nicht als Präprozessordefinition angegeben ist.
Das folgende Beispiel zeigt eine Skelettimplementierung einer Fensterprozedur für ein unterklassiges Steuerelement.
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_PAINT:
.
.
.
return TRUE;
// Other cases...
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Die Fensterprozedur kann an das Steuerelement im WM_INITDIALOG-Handler der Dialogprozedur angefügt werden, wie im folgenden Beispiel gezeigt.
case WM_INITDIALOG:
{
HWND button = GetDlgItem(hDlg, IDC_OWNERDRAWBUTTON);
SetWindowSubclass(button, OwnerDrawButtonProc, 0, 0);
return TRUE;
}
GetWindowSubclass
Diese Funktion ruft Informationen zu einer Unterklasse ab. Beispielsweise können Sie getWindowSubclass verwenden, um auf die Verweisdaten zuzugreifen.
RemoveWindowSubclass
Diese Funktion entfernt Unterklassen. RemoveWindowSubclass in Kombination mit SetWindowSubclass ermöglicht Ihnen das dynamische Hinzufügen und Entfernen von Unterklassen.
DefSubclassProc
Die DefSubclassProc-Funktion ruft den nächsten Handler in der Unterklassenkette auf. Die Funktion ruft auch die richtigen ID- und Verweisdaten ab und übergibt die Informationen an die Prozedur des nächsten Fensters.