Unterklassensteuerelemente

Wenn ein Steuerelement fast alles tut, was Sie möchten, Aber Sie noch einige weitere Features benötigen, können Sie Features ändern oder dem ursprünglichen Steuerelement hinzufügen, indem Sie es in Unterklassen unterteilen. Eine Unterklasse kann alle Features einer vorhandenen Klasse sowie alle zusätzlichen Features aufweisen, die Sie ihr geben 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

Sie können ein Steuerelement in einer Unterklasse ablegen und Benutzerdaten in einem -Steuerelement speichern. Dies geschieht, wenn Sie Versionen von ComCtl32.dll vor Version 6 verwenden. Das Erstellen von Unterklassen mit früheren Versionen von ComCtl32.dll hat einige Nachteile.

Um ein neues Steuerelement zu erstellen, ist es am besten, mit einem der Windows allgemeinen Steuerelemente zu beginnen und es entsprechend einer bestimmten Notwendigkeit zu erweitern. Um ein Steuerelement zu erweitern, erstellen Sie ein Steuerelement, und ersetzen Sie seine vorhandene Fensterprozedur durch ein neues. Die neue Prozedur fängt die Meldungen des Steuerelements ab und verarbeitet sie entweder 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 Sie einen WNDPROC ersetzen.

OldWndProc = (WNDPROC)SetWindowLongPtr (hButton,
GWLP_WNDPROC, (LONG_PTR)NewWndProc);

Speichern von Benutzerdaten

Möglicherweise möchten Sie Benutzerdaten in einem einzelnen Fenster speichern. Diese Daten können von der neuen Fensterprozedur verwendet werden, um zu bestimmen, wie das Steuerelement gezeichnet wird oder wohin bestimmte Nachrichten gesendet werden sollen. Beispielsweise können Sie Daten verwenden, um einen C++-Klassenzeiger auf die Klasse zu speichern, die das Steuerelement darstellt. Das folgende Codebeispiel zeigt, wie Sie SetProp verwenden, um Daten mit einem Fenster zu speichern.

SetProp (hwnd, TEXT("MyData"), (HANDLE)pMyData);

Nachteile des alten Unterklassenansatzes

In der folgenden Liste sind einige Nachteile der Verwendung des zuvor beschriebenen Ansatzes zum Unterklassen eines Steuerelements aufgeführt.

  • 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 umwandlungen und aufrufen. Sie müssen sie mithilfe 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 unter- oder überklassigt werden.

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 und nicht auf die Verwaltung von Unterklassen konzentrieren. Die Unterklassenfunktionen sind:

SetWindowSubclass

Diese Funktion wird verwendet, um zunächst eine Unterklasse für ein Fenster zu erstellen. Jede Unterklasse wird durch die Adresse der pfnSubclass und ihrer uIdSubclass eindeutig identifiziert. Beides sind Parameter der SetWindowSubclass-Funktion. Mehrere Unterklassen können dieselbe Unterklassenprozedur verwenden, und die ID kann jeden Aufruf identifizieren. Um Verweisdaten zu ändern, können Sie nachfolgende Aufrufe an SetWindowSubclass vornehmen. Der wichtige Vorteil besteht darin, dass jede Unterklasseninstanz über eigene Verweisdaten verfügt.

Die Deklaration einer Unterklassenprozedur unterscheidet sich geringfügig von einer regulären Fensterprozedur, da sie zwei zusätzliche Daten 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 Skelettimplementierungen einer Fensterprozedur für ein Unterklassensteuerelement.

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 nächste Fensterprozedur.