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::OnCompareItem
bzwCWnd::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 dasHWND
. Sie können das Verhalten in einer abgeleiteten Klasse ändern, indem Sie eine vonCWnd
. DieHWND
Wird erstellt, wenn Ihre Anwendung CWnd::Create aufruft.Die Anwendung fügt eine
CWnd
an eine vorhandeneHWND
Anwendung 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 vorhandenesHWND
CWnd
Objekt ermöglicht.CWnd
ist an eine vorhandeneHWND
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 HWND
Anfü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 SubclassDlgItem
Verwendung an.
Siehe auch
Technische Hinweise – nach Nummern geordnet
Technische Hinweise – nach Kategorien geordnet