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 STRGTEST veranschaulicht die Verwendung vieler benutzerdefinierter Steuerelemente. Sehen Sie sich den Quellcode für das allgemeine MFC-Beispiel STRGTEST und die Onlinehilfe an.

Steuerelemente/Menüs für Besitzer zeichnen

Windows bietet Unterstützung für Steuerelemente und Menüs zum Zeichnen von Besitzern mithilfe 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 Besitzer-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 Klassen und CMenu ) für die standardmäßigen Besitzer-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 im übergeordneten Element. 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 Self-Draw-Schaltflächen:

    CButton:DrawItem(LPDRAWITEMSTRUCT);
    // insert code to draw this button
    
  • Für Selbst zeichnende Menü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 Selbst zeichnende 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::OnCompareItembzwCWnd::OnDeleteItem.

Verwenden von Self-Draw-Steuerelementen und Menüs

Für Selbst zeichnende Menüs müssen Sie sowohl die Methoden OnDrawItem als auch die OnMeasureItem 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 die LBS_OWNERDRAWVARIABLE Formatvorlage für Listenfelder oder CBS_OWNERDRAWVARIABLE Formatvorlage für Kombinationsfelder in der Dialogfeldvorlage angeben. Die OWNERDRAWFIXED-Formatvorlage funktioniert nicht mit Selbstzeichnungselementen, da die Höhe eines festen Elements bestimmt wird, bevor steuerelemente für die Selbstzeichnung an das Listenfeld angefügt werden. (Sie können die Methoden verwendenCListBox::SetItemHeight und CComboBox::SetItemHeight , um diese Einschränkung zu überwinden.)

Wenn Sie zu einer OWNERDRAWVARIABLE-Formatvorlage wechseln, wird das System zwingen, die NOINTEGRALHEIGHT-Formatvorlage 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 Selbstzeichnungslistenfelder und Kombinationsfelder mit dem LBS_SORT oder CBS_SORT Format müssen Sie die OnCompareItem Methode überschreiben.

Bei Selbstzeichnungslistenfeldern und Kombinationsfeldern OnDeleteItem wird 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 Selbstzeichnungssteuerelemente und Menüs

Das MFC General-Beispiel STRGTEST enthält Beispiele für ein Selbstzeichnen-Menü und ein Selbstzeichnen-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.

Unterklassen ist der Windows-Begriff zum Ersetzen WndProc des Fensters durch ein angepasstes WndProc und Aufrufen der 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. Die HWND Wird erstellt, wenn Ihre Anwendung CWnd::Create aufruft.

  • Die Anwendung fügt eine CWnd an eine vorhandene HWNDAnwendung an. Das Verhalten des vorhandenen Fensters wird nicht geändert. Dies ist ein Fall von Delegierung und wird durch Aufrufen von CWnd::Attach to alias an ein vorhandenes HWND CWnd Objekt ermöglicht.

  • 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 undCWnd::SubclassDlgItem können Sie dynamische Unterklassen erreichen.

Beide Routinen fügen ein CWnd Objekt an ein vorhandenes HWNDAnfügen an. SubclassWindow nimmt die HWND direkt. SubclassDlgItem ist eine Hilfsfunktion, die eine Steuerelement-ID und das übergeordnete Fenster verwendet. 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 für mehrere Beispiele für die Verwendung SubclassWindow und die SubclassDlgItemVerwendung an.

Siehe auch

Technische Hinweise – nach Nummern geordnet
Technische Hinweise – nach Kategorien geordnet