Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cette note décrit la prise en charge de MFC pour les contrôles personnalisés et autodessinés. Il décrit également les sous-classes dynamiques et décrit la relation entre les objets CWnd et HWND.
L’exemple d’application MFC CTRLTEST illustre l’utilisation de nombreux contrôles personnalisés. Consultez le code source de l’exemple général MFC CtrlTEST et de l’aide en ligne.
Owner-Draw Contrôles/Menus
Windows prend en charge les contrôles et menus dessinés par l’utilisateur à l’aide de messages Windows. La fenêtre parente d’un contrôle ou d’un menu reçoit ces messages et appelle des fonctions en réponse. Vous pouvez remplacer ces fonctions pour personnaliser l’apparence visuelle et le comportement de votre contrôle ou menu de dessin propriétaire.
MFC prend directement en charge le dessin propriétaire avec les fonctions suivantes :
Vous pouvez remplacer ces fonctions dans votre CWnd classe dérivée pour implémenter un comportement de dessin personnalisé.
Cette approche n’entraîne pas de code réutilisable. Si vous avez deux contrôles similaires dans deux classes différentes CWnd , vous devez implémenter le comportement de contrôle personnalisé dans deux emplacements. L’architecture de contrôle de dessin automatique prise en charge par MFC résout ce problème.
Self-Draw Contrôles et menus
MFC fournit une implémentation par défaut pour les messages standard de dessin par le propriétaire dans les classes CWnd et CMenu. Cette implémentation par défaut décode les paramètres de dessin propriétaire et délègue les messages de dessin propriétaire aux contrôles ou au menu. Cela est appelé dessin automatique, car le code de dessin se trouve dans la classe du contrôle ou du menu, et non dans la fenêtre propriétaire.
En utilisant des contrôles auto-dessin, vous pouvez créer des classes de contrôle réutilisables qui utilisent la sémantique de dessin propriétaire pour afficher le contrôle. Le code de dessin du contrôle se trouve dans la classe de contrôle, et non dans son parent. Il s’agit d’une approche orientée objet de la programmation de contrôle personnalisée. Ajoutez la liste suivante de fonctions à vos classes de dessin automatique :
Pour les boutons de dessin automatique :
CButton::DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this buttonPour les menus à dessin automatique :
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 menuPour les zones de liste à dessin automatique :
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 boxPour les boîtes combo personnalisées :
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
Pour plus d’informations sur les structures de dessin propriétaire (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT et DELETEITEMSTRUCT), consultez la documentation MFC pour CWnd::OnDrawItem, CWnd::OnMeasureItemet CWnd::OnCompareItemCWnd::OnDeleteItemrespectivement.
Utilisation de contrôles et de menus auto-dessinés
Pour les menus à dessin automatique, vous devez remplacer les méthodes OnMeasureItem et OnDrawItem.
Pour les boîtes de liste autonome et les boîtes combinées, vous devez remplacer OnMeasureItem et OnDrawItem. Vous devez spécifier le style LBS_OWNERDRAWVARIABLE pour les zones de liste ou le style CBS_OWNERDRAWVARIABLE pour les zones de liste déroulante dans le modèle de boîte de dialogue. Le style OWNERDRAWFIXED ne fonctionne pas avec les éléments autodessinés, car la hauteur de l’élément fixe est déterminée avant que les contrôles autodessinés soient attachés à la boîte de liste. (Vous pouvez utiliser les méthodes CListBox ::SetItemHeight et CComboBox ::SetItemHeight pour surmonter cette limitation.)
Le passage à un style OWNERDRAWVARIABLE force le système à appliquer le style NOINTEGRALHEIGHT au contrôle. Étant donné que le contrôle ne peut pas calculer une hauteur intégrale avec des éléments de taille variable, le style par défaut de INTEGRALHEIGHT est ignoré et le contrôle est toujours NOINTEGRALHEIGHT. Si vos éléments sont à hauteur fixe, vous pouvez empêcher les éléments partiels d’être dessinés en spécifiant la taille du contrôle comme multiplicateur entier de la taille de l’élément.
Pour les zones de liste à auto-dessin et les zones de liste déroulante avec le style LBS_SORT ou CBS_SORT, vous devez redéfinir la méthode OnCompareItem.
Pour les zones de liste déroulantes auto-dessinées et les zones de liste combo, OnDeleteItem n'est généralement pas redéfini. Vous pouvez remplacer OnDeleteItem si vous souhaitez effectuer un traitement spécial. L’un des cas où cela s’applique est lorsque de la mémoire supplémentaire ou d’autres ressources sont stockées avec chaque élément de liste ou de liste déroulante.
Exemples de contrôles et de menus Self-Drawing
L'exemple général MFC CTRLTEST fournit des exemples de menu à dessin automatique et d'une zone de liste à dessin automatique.
L’exemple le plus classique d’un bouton auto-dessin est un bouton bitmap. Un bouton bitmap est un bouton qui affiche une, deux ou trois images bitmap pour les différents états. Un exemple de ceci est fourni dans la classe MFC CBitmapButton.
Sous-classification dynamique
Parfois, vous souhaiterez modifier les fonctionnalités d’un objet qui existe déjà. Les exemples précédents vous ont demandé de personnaliser les contrôles avant leur création. La sous-classe dynamique vous permet de personnaliser un contrôle qui a déjà été créé.
La sous-classe est le terme Windows permettant de remplacer la WndProc fenêtre par une fonctionnalité personnalisée WndProc et d’appeler l’ancienne WndProc pour les fonctionnalités par défaut.
Cela ne doit pas être confondu avec la dérivation de classe C++. Pour plus d’informations, la classe de base de termes C++ et la classe dérivée sont analogues à la superclasse et à la sous-classe dans le modèle objet Windows. La dérivation C++ avec les sous-classes MFC et Windows est fonctionnellement similaire, sauf que C++ ne prend pas en charge la sous-classe dynamique.
La CWnd classe fournit la connexion entre un objet C++ (dérivé de CWnd) et un objet fenêtre Windows (appelé « an HWND»).
Il existe trois façons courantes dont ces éléments sont liés :
CWndcrée leHWND. Vous pouvez modifier le comportement dans une classe dérivée en créant une classe dérivée deCWnd. LaHWNDvaleur est créée lorsque votre application appelle CWnd ::Create.L’application attache un
CWndà un objet existantHWND. Le comportement de la fenêtre existante n’est pas modifié. Il s’agit d’un cas de délégation et cela est rendu possible en appelant CWnd::Attach pour associer unHWNDà un objetCWndexistant.CWndest attaché à un existantHWNDet vous pouvez modifier le comportement dans une classe dérivée. Cela est appelé sous-classe dynamique, car nous modifions le comportement, et par conséquent la classe, d’un objet Windows au moment de l’exécution.
Vous pouvez obtenir une sous-classe dynamique à l’aide des méthodes CWnd ::SubclassWindow et CWnd ::SubclassDlgItem.
Les deux routines attachent un CWnd objet à un objet existant HWND.
SubclassWindow prend le HWND directement.
SubclassDlgItem est une fonction d’assistance qui prend l'ID de contrôle et la fenêtre parente.
SubclassDlgItem est conçu pour attacher des objets C++ aux contrôles de boîte de dialogue créés à partir d’un modèle de dialogue.
Consultez l’exemple CTRLTEST pour obtenir plusieurs exemples de cas d’utilisation SubclassWindow et SubclassDlgItem.