Contrôles personnalisés
Cette section contient des informations sur les contrôles personnalisés ou définis par l’application.
Les sujets suivants sont abordés.
- Création de contrôles Owner-Drawn
- Sous-classification de la classe Window d’un contrôle existant
- Implémentation d’une classe window Application-Defined
- Envoi de notifications à partir d’un contrôle
- Accessibilité
- Rubriques connexes
Création de contrôles Owner-Drawn
Les boutons, les menus, les contrôles de texte statique, les zones de liste et les zones de liste déroulante peuvent être créés avec un indicateur de style dessiné par le propriétaire. Lorsqu’un contrôle a le style dessiné par le propriétaire, le système gère l’interaction de l’utilisateur avec le contrôle comme d’habitude, en effectuant des tâches telles que la détection du moment où un utilisateur a choisi un bouton et la notification du propriétaire du bouton de l’événement. Toutefois, étant donné que le contrôle est dessiné par le propriétaire, la fenêtre parente du contrôle est responsable de l’apparence visuelle du contrôle. La fenêtre parente reçoit un message chaque fois que le contrôle doit être dessiné.
Pour les boutons et les contrôles de texte statiques, le style dessiné par le propriétaire affecte la façon dont le système dessine l’ensemble du contrôle. Pour les zones de liste et les zones de liste déroulante, la fenêtre parente dessine les éléments du contrôle et le contrôle dessine son propre contour. Par exemple, une application peut personnaliser une zone de liste afin qu’elle affiche une petite bitmap en regard de chaque élément de la liste.
L’exemple de code suivant montre comment créer un contrôle de texte statique dessiné par le propriétaire. Supposons qu’Unicode soit défini.
// g_myStatic is a global HWND variable.
g_myStatic = CreateWindowEx(0, L"STATIC", L"Some static text",
WS_CHILD | WS_VISIBLE | SS_OWNERDRAW,
25, 125, 150, 20, hDlg, 0, 0, 0);
Dans l’exemple suivant, à partir de la procédure de fenêtre de la boîte de dialogue qui contient le contrôle créé dans l’exemple précédent, le message WM_DRAWITEM est géré en affichant le texte dans une couleur personnalisée, à l’aide de la police par défaut. Notez que vous n’avez pas besoin d’appeler BeginPaint et EndPaint lors de la gestion des WM_DRAWITEM.
case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT pDIS = (LPDRAWITEMSTRUCT)lParam;
if (pDIS->hwndItem == g_myStatic)
{
SetTextColor(pDIS->hDC, RGB(100, 0, 100));
WCHAR staticText[99];
int len = SendMessage(myStatic, WM_GETTEXT,
ARRAYSIZE(staticText), (LPARAM)staticText);
TextOut(pDIS->hDC, pDIS->rcItem.left, pDIS->rcItem.top, staticText, len);
}
return TRUE;
}
Pour plus d’informations sur les contrôles dessinés par le propriétaire, consultez Création d’une zone de liste dessinée par le propriétaire et de zones de liste déroulante dessinées par le propriétaire.
Sous-classification de la classe Window d’un contrôle existant
La sous-classification d’un contrôle existant est une autre façon de créer un contrôle personnalisé. La procédure de sous-classe peut modifier les comportements sélectionnés du contrôle en traitant les messages qui affectent les comportements sélectionnés. Tous les autres messages passent à la procédure de fenêtre d’origine pour le contrôle. Par exemple, une application peut afficher une petite bitmap en regard du texte dans un contrôle d’édition en lecture seule à une seule ligne en sous-classant le contrôle et en traitant le message WM_PAINT . Pour plus d’informations, consultez À propos des procédures de fenêtre et des contrôles de sous-classification.
Implémentation d’une classe window Application-Defined
Pour créer un contrôle qui n’est pas explicitement basé sur un contrôle existant, l’application doit créer et inscrire une classe de fenêtre. Le processus d’inscription d’une classe de fenêtre définie par l’application pour un contrôle personnalisé est identique à l’inscription d’une classe pour une fenêtre ordinaire. Pour créer un contrôle personnalisé, spécifiez le nom de la classe window dans la fonction CreateWindowEx ou dans un modèle de boîte de dialogue. Chaque classe doit avoir un nom unique, une procédure de fenêtre correspondante et d’autres informations.
Au minimum, la procédure de fenêtre dessine le contrôle. Si une application utilise le contrôle pour permettre à l’utilisateur de taper des informations, la procédure de fenêtre traite également les messages d’entrée à partir du clavier et de la souris et envoie des messages de notification à la fenêtre parente. En outre, si le contrôle prend en charge les messages de contrôle, la procédure de fenêtre traite les messages qui lui sont envoyés par la fenêtre parente ou d’autres fenêtres. Par exemple, les contrôles traitent souvent le message WM_GETDLGCODE envoyé par les boîtes de dialogue pour diriger une boîte de dialogue pour traiter l’entrée au clavier d’une manière donnée.
La procédure de fenêtre pour un contrôle défini par l’application doit traiter tout message de contrôle prédéfini dans le tableau suivant si le message affecte le fonctionnement du contrôle.
Message | Recommandation |
---|---|
WM_GETDLGCODE | Procédez si le contrôle utilise les touches ENTRÉE, ÉCHAP, TABulation ou flèche. La fonction IsDialogMessage envoie ce message aux contrôles d’une boîte de dialogue pour déterminer s’il faut traiter les clés ou les transmettre au contrôle. |
WM_GETFONT | Traitez si le message WM_SETFONT est également traité. |
WM_GETTEXT | Procédez si le texte du contrôle n’est pas le même que le titre spécifié par la fonction CreateWindowEx . |
WM_GETTEXTLENGTH | Procédez si le texte du contrôle n’est pas le même que le titre spécifié par la fonction CreateWindowEx . |
WM_KILLFOCUS | Procédez si le contrôle affiche un signe d’insertion, un rectangle de focus ou un autre élément pour indiquer qu’il a le focus d’entrée. |
WM_SETFOCUS | Procédez si le contrôle affiche un signe d’insertion, un rectangle de focus ou un autre élément pour indiquer qu’il a le focus d’entrée. |
WM_SETTEXT | Procédez si le texte du contrôle n’est pas le même que le titre spécifié par la fonction CreateWindowEx . |
WM_SETFONT | Traiter si le contrôle affiche du texte. Le système envoie ce message lors de la création d’une boîte de dialogue qui a le style DS_SETFONT. |
Les messages de contrôle définis par l’application sont spécifiques au contrôle donné et doivent être explicitement envoyés au contrôle à l’aide d’une fonction SendMessage ou SendDlgItemMessage . La valeur numérique de chaque message doit être unique et ne doit pas entrer en conflit avec les valeurs des autres messages de fenêtre. Pour s’assurer que les valeurs de message définies par l’application ne sont pas en conflit, une application doit créer chaque valeur en ajoutant un nombre unique à la valeur WM_USER .
Envoi de notifications à partir d’un contrôle
Des contrôles personnalisés peuvent être nécessaires pour envoyer des notifications d’événements à la fenêtre parente afin que l’application hôte puisse répondre à ces événements. Par exemple, un affichage de liste personnalisé peut envoyer une notification lorsque l’utilisateur sélectionne un élément, et une autre notification lorsqu’un élément est double-cliqué.
Les notifications sont envoyées sous forme de messages WM_COMMAND ou WM_NOTIFY . WM_NOTIFY messages contiennent plus d’informations que WM_COMMAND messages.
L’identificateur de contrôle est un numéro unique que l’application utilise pour identifier le contrôle qui envoie le message. L’application définit l’identificateur d’un contrôle lorsqu’elle crée le contrôle. L’application spécifie l’identificateur dans le paramètre hMenu de la fonction CreateWindowEx ou dans le membre id de la structure DLGITEMTEMPLATEEX .
Étant donné que le contrôle lui-même ne définit pas l’identificateur du contrôle, il doit récupérer l’identificateur avant de pouvoir envoyer des messages de notification. Un contrôle doit utiliser la fonction GetDlgCtrlID pour récupérer son propre identificateur de contrôle. Bien que l’identificateur de contrôle soit spécifié comme handle de menu lors de la création du contrôle, la fonction GetMenu ne peut pas être utilisée pour récupérer l’identificateur. Un contrôle peut également récupérer l’identificateur du membre hMenu dans la structure CREATESTRUCT lors du traitement du message WM_CREATE .
Les exemples suivants, où hwndControl est le handle de la fenêtre de contrôle et CN_VALUECHANGED est une définition de notification personnalisée, montrent les deux façons d’envoyer une notification spécifique au contrôle.
// Send as WM_COMMAND.
SendMessage(GetParent(hwndControl),
WM_COMMAND,
MAKEWPARAM(GetDlgCtrlID(hwndControl), CN_VALUECHANGED),
(LPARAM)hwndControl);
// Send as WM_NOTIFY.
NMHDR nmh;
nmh.code = CN_VALUECHANGED;
nmh.idFrom = GetDlgCtrlID(hwndControl);
nmh.hwndFrom = hwndControl;
SendMessage(GetParent(hwndControl),
WM_NOTIFY,
(WPARAM)hwndControl,
(LPARAM)&nmh);
Notez que la structure NMHDR peut faire partie d’une structure définie par un contrôle plus large qui contient des informations supplémentaires. Dans l’exemple, les anciennes et nouvelles valeurs du contrôle peuvent être contenues dans cette structure. (Ces structures étendues sont utilisées avec de nombreuses notifications standard ; par exemple, consultez LVN_INSERTITEM, qui utilise la structure NMLISTVIEW .)
Accessibilité
Tous les contrôles courants prennent en charge Microsoft Active Accessibility (MSAA), qui permet l’accès par programmation par des applications technologiques accessibles telles que les lecteurs d’écran. MSAA permet également UI Automation, une technologie plus récente, d’interagir avec les contrôles.
Les contrôles personnalisés doivent implémenter l’interface IAccessible (pour prendre en charge MSAA) ou les interfaces UI Automation, ou les deux. Sinon, les produits de technologie accessible ne pourront obtenir que des informations très limitées sur la fenêtre de contrôle, n’auront pas accès aux propriétés du contrôle et ne pourront pas déclencher des événements dans le contrôle.
Pour plus d’informations sur la mise à disposition de votre contrôle, consultez API Windows Automation.
Rubriques connexes
-
Conceptuel
-
Personnalisation de l’apparence d’un contrôle à l’aide d’un dessin personnalisé
-
Utilisation de styles visuels avec des contrôles Owner-Drawn