Freigeben über


TN014: Benutzerdefinierte Steuerelemente

In diesem Hinweis wird die MFC-Unterstützung für benutzerdefinierte und Selbstzeichnungssteuerelemente beschrieben. Außerdem wird die dynamische Unterklasse beschrieben und die Beziehung zwischen CWnd-Objekten und HWND-Objekten beschrieben.

Die MFC-Beispielanwendung CTRLTEST veranschaulicht, wie viele benutzerdefinierte Steuerelemente verwendet werden können. Sehen Sie sich den Quellcode für das allgemeine MFC-Beispiel STRGTEST und die Onlinehilfe an.

Owner-Draw Steuerelemente/Menüs

Windows bietet Unterstützung für Owner-Draw-Steuerelemente und -Menüs durch die Verwendung von Windows-Nachrichten. Das übergeordnete Fenster eines Steuerelements oder Menüs empfängt diese Nachrichten und ruft als Reaktion Funktionen auf. Sie können diese Funktionen außer Kraft setzen, um die visuelle Darstellung und das Verhalten Ihres Steuerelements oder Menüs für das Zeichnen des Besitzers anzupassen.

MFC unterstützt direkt Owner-Draw mit den folgenden Funktionen:

Sie können diese Funktionen in Ihrer CWnd abgeleiteten Klasse überschreiben, um benutzerdefiniertes Draw-Verhalten zu implementieren.

Dieser Ansatz führt nicht zu wiederverwendbarem Code. Wenn Sie zwei ähnliche Steuerelemente in zwei verschiedenen CWnd Klassen haben, müssen Sie das verhalten des benutzerdefinierten Steuerelements an zwei Stellen implementieren. Die von MFC unterstützte Selbstzeichnungssteuerungsarchitektur löst dieses Problem.

Self-Draw Steuerelemente und Menüs

MFC stellt eine Standardimplementierung (in den CWnd und CMenu Klassen) für die standardmäßigen Owner-Draw Nachrichten bereit. Diese Standardimplementierung decodiert die Parameter "owner-draw", und delegiert die Besitzer-Draw-Nachrichten an die Steuerelemente oder das Menü. Dies wird als Self-Draw bezeichnet, da sich der Zeichencode in der Klasse des Steuerelements oder Menüs befindet, nicht im Besitzerfenster.

Mithilfe von Self-Draw-Steuerelementen können Sie wiederverwendbare Steuerelementklassen erstellen, die die Besitzer-Draw-Semantik verwenden, um das Steuerelement anzuzeigen. Der Code zum Zeichnen des Steuerelements befindet sich in der Steuerelementklasse und nicht in der Elternklasse. Dies ist ein objektorientierter Ansatz für die benutzerdefinierte Steuerelementprogrammierung. Fügen Sie die folgende Liste der Funktionen zu Ihren selbst zeichnenden Klassen hinzu:

  • Für selbstgezeichnete Schaltflächen:

    CButton::DrawItem(LPDRAWITEMSTRUCT);
    // insert code to draw this button
    
  • Für benutzerdefinierte Zeichenmenüs:

    CMenu::MeasureItem(LPMEASUREITEMSTRUCT);
    // insert code to measure the size of an item in this menu
    CMenu::DrawItem(LPDRAWITEMSTRUCT);
    // insert code to draw an item in this menu
    
  • Für selbstzeichnende Listenfelder:

    CListBox::MeasureItem(LPMEASUREITEMSTRUCT);
    // insert code to measure the size of an item in this list box
    CListBox::DrawItem(LPDRAWITEMSTRUCT);
    // insert code to draw an item in this list box
    
    CListBox::CompareItem(LPCOMPAREITEMSTRUCT);
    // insert code to compare two items in this list box if LBS_SORT
    CListBox::DeleteItem(LPDELETEITEMSTRUCT);
    // insert code to delete an item from this list box
    
  • Für selbst zeichnende Kombinationsfelder:

    CComboBox::MeasureItem(LPMEASUREITEMSTRUCT);
    // insert code to measure the size of an item in this combo box
    CComboBox::DrawItem(LPDRAWITEMSTRUCT);
    // insert code to draw an item in this combo box
    
    CComboBox::CompareItem(LPCOMPAREITEMSTRUCT);
    // insert code to compare two items in this combo box if CBS_SORT
    CComboBox::DeleteItem(LPDELETEITEMSTRUCT);
    // insert code to delete an item from this combo box
    

Ausführliche Informationen zu den Besitzer-Draw-Strukturen (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT und DELETEITEMSTRUCT) finden Sie in der MFC-Dokumentation für CWnd::OnDrawItem, CWnd::OnMeasureItem, CWnd::OnCompareItem und CWnd::OnDeleteItem.

Verwenden von selbst gezeichneten Steuerelementen und Menüs

Für Menüs zur Selbstgestaltung müssen Sie sowohl die OnMeasureItem als auch die OnDrawItem Methoden außer Kraft setzen.

Für selbst zeichnende Listenfelder und Kombinationsfelder müssen Sie außer Kraft setzen OnMeasureItem und OnDrawItem. Sie müssen den Stil LBS_OWNERDRAWVARIABLE für Listenfelder oder CBS_OWNERDRAWVARIABLE für Kombinationsfelder in der Dialogfeldvorlage angeben. Der OWNERDRAWFIXED-Style funktioniert nicht mit selbst gezeichneten Elementen, da die feste Höhe eines Elements bestimmt wird, bevor Steuerelemente zum Selbstzeichnen in das Listenfeld eingebunden werden. (Sie können die Methoden CListBox::SetItemHeight und CComboBox::SetItemHeight verwenden, um diese Einschränkung zu überwinden.)

Wenn Sie zu einem OWNERDRAWVARIABLE-Stil wechseln, wird das System dazu gezwungen, den NOINTEGRALHEIGHT-Stil auf das Steuerelement anzuwenden. Da das Steuerelement keine integrale Höhe mit Elementen mit variabler Größe berechnen kann, wird der Standardstil von INTEGRALHEIGHT ignoriert, und das Steuerelement ist immer NOINTEGRALHEIGHT. Wenn ihre Elemente eine feste Höhe aufweisen, können Sie verhindern, dass Teilelemente gezeichnet werden, indem Sie die Steuerelementgröße als ganzzahliger Multiplizierer der Elementgröße angeben.

Für selbstzeichnende Listenfelder und Kombinationsfelder mit dem LBS_SORT- oder CBS_SORT-Stil sollten Sie die OnCompareItem-Methode überschreiben.

Bei Selbstzeichnungslistenfeldern und Kombinationsfeldern wird OnDeleteItem normalerweise nicht überschrieben. Sie können außer Kraft setzen OnDeleteItem , wenn Sie eine spezielle Verarbeitung durchführen möchten. Ein Fall, in dem dies anwendbar wäre, ist, wenn zusätzlichen Arbeitsspeicher oder andere Ressourcen mit jedem Listenfeld- oder Kombinationsfeldelement gespeichert werden.

Beispiele für Self-Drawing Steuerelemente und Menüs

Das allgemeine MFC-Beispiel CTRLTEST enthält Beispiele für ein selbstgezeichnetes Menü und ein selbstgezeichnetes Listenfeld.

Das typischste Beispiel für eine Selbstzeichnungsschaltfläche ist eine Bitmapschaltfläche. Eine Bitmapschaltfläche ist eine Schaltfläche, die ein, zwei oder drei Bitmapbilder für die verschiedenen Zustände anzeigt. Ein Beispiel hierfür wird in der MFC-Klasse CBitmapButton bereitgestellt.

Dynamische Unterklassen

Gelegentlich möchten Sie die Funktionalität eines bereits vorhandenen Objekts ändern. In den vorherigen Beispielen mussten Sie die Steuerelemente anpassen, bevor sie erstellt wurden. Mithilfe der dynamischen Unterklassen können Sie ein bereits erstelltes Steuerelement anpassen.

Unterklassenbildung ist der Windows-Begriff für das Ersetzen des WndProc eines Fensters durch ein angepasstes WndProc und das Aufrufen des alten WndProc für Standardfunktionen.

Dies sollte nicht mit der C++-Klassenableitung verwechselt werden. Zur Klärung sind die C++-Begriffe Basisklasse und abgeleitete Klasse analog zu Superklassen und Unterklassen im Windows-Objektmodell. Die C++-Ableitung mit MFC- und Windows-Unterklassen ist funktional ähnlich, außer C++ unterstützt keine dynamische Unterklassen.

Die CWnd Klasse stellt die Verbindung zwischen einem C++-Objekt (abgeleitet von CWnd) und einem Windows-Fensterobjekt (bekannt als ein HWND).

Es gibt drei häufige Möglichkeiten, die im Zusammenhang stehen:

  • CWnd erstellt das HWND. Sie können das Verhalten in einer abgeleiteten Klasse ändern, indem Sie eine von CWnd abgeleitete Klasse erstellen. Die HWND wird erzeugt, wenn Ihre Anwendung CWnd::Create aufruft.

  • Die Anwendung fügt ein CWnd zu einem vorhandenen HWND hinzu. Das Verhalten des vorhandenen Fensters wird nicht geändert. Dies ist ein Fall von Delegierung und wird durch das Aufrufen von CWnd::Attach ermöglicht, um ein vorhandenes HWND-Objekt einem CWnd-Objekt zuzuordnen.

  • CWnd ist an eine vorhandene HWND angefügt, und Sie können das Verhalten in einer abgeleiteten Klasse ändern. Dies wird als dynamische Unterklassen bezeichnet, da wir das Verhalten und daher die Klasse eines Windows-Objekts zur Laufzeit ändern.

Mithilfe der Methoden CWnd::SubclassWindow und CWnd::SubclassDlgItem können Sie dynamische Unterklassen erreichen.

Beide Routinen hängen ein CWnd-Objekt an ein bestehendes HWND an. SubclassWindow nimmt die HWND direkt. SubclassDlgItem ist eine Hilfsfunktion, die eine Steuerelement-ID und das Elternfenster entgegennimmt. SubclassDlgItem ist für das Anfügen von C++-Objekten an Dialogfeldsteuerelemente konzipiert, die aus einer Dialogfeldvorlage erstellt wurden.

Sehen Sie sich das STRGTEST-Beispiel an, um mehrere Beispiele für die Verwendung von SubclassWindow und SubclassDlgItem zu sehen.

Siehe auch

Technische Hinweise nach Nummer
Technische Hinweise nach Kategorie