Alternatives à l’annotation dynamique
Il existe d’autres façons de fournir une prise en charge IAccessible personnalisée pour les éléments d’interface utilisateur et, dans certains cas, ils constituent la solution appropriée. Avant l’annotation dynamique, ces techniques alternatives étaient les seules options disponibles pour les développeurs. Ils incluent l’implémentation de toutes les techniques d’interface et de programmation IAccessible .
Implémentation de l’ensemble de l’interface IAccessible
Une autre technique consiste à implémenter l’ensemble de l’interface IAccessible . Cette approche est souvent nécessaire pour les contrôles personnalisés ou les éléments d’interface utilisateur radicalement différents ; toutefois, les coûts de développement et de test sont suffisamment importants pour être évités, sauf si cela est vraiment nécessaire. Si l’objectif est de modifier une propriété unique, le coût est difficile à justifier.
Techniques programmatiques
Une autre option consiste à utiliser des techniques de sous-classification et d’habillage pour modifier les informations exposées pour une propriété spécifique. Il s’agit de la technique que l’annotation dynamique est destinée à remplacer. Pour remplacer une propriété unique à l’aide de la sous-classe et de l’encapsulage, le développeur doit effectuer les étapes suivantes :
- Sous-classez le HWND de l’objet IAccessible .
- Interceptez le message WM_GETOBJECT pour la valeur IParam/OBJID correcte.
- Transférez le message WM_GETOBJECT à la classe de base à l’aide de la fonction de rappel CallWndProc . Si zéro est retourné, appelez CreateStdAccessibleObject ; sinon, appelez LresultFromObject sur la valeur retournée pour obtenir le pointeur d’interface IAccessible natif du contrôle.
- Créez une classe wrapper, qui implémente IAccessible et encapsule le pointeur d’interface IAccessible retourné à l’étape précédente. Cette classe wrapper envoie toutes les méthodes et propriétés au pointeur d’interface IAccessible d’origine, à l’exception de celles qui doivent être remplacées. Cela implique l’écriture de code de transfert pour toutes les 21 propriétés et méthodes de l’interface IAccessible , quel que soit le nombre réellement substitué.
En outre, les développeurs doivent vérifier les conditions suivantes :
- La méthode ou la propriété remplacée doit uniquement gérer les ID enfants requis et transférer tous les autres vers le pointeur d’interface IAccessible d’origine.
- Le wrapping doit également transférer les interfaces IEnumVARIANT et IOleWindow uniquement si l’objet d’origine les prend en charge.
- Le comptage des références doit être géré correctement, en particulier si d’autres interfaces sont prises en charge.
- Les valeurs de retour IDispatch doivent être gérées correctement, en particulier avec la méthode ITypeInfo::Invoke, qui doit être appelée avec un pointeur d’interface vers l’interface wrapper, et non un pointeur vers l’interface IAccessible d’origine.
Ces techniques nécessitent un travail considérable, même si une ou deux propriétés seulement doivent être remplacées. La majorité du code résultant concerne la sous-classification et l’encapsulage, et seule une petite fraction fournit en fait les informations remplacées.
Toutefois, il existe des scénarios dans lesquels ces techniques sont nécessaires. Par exemple, si vous apportez des modifications structurelles pour créer un élément d’interface utilisateur d’espace réservé, vous devez utiliser ces techniques plutôt que l’annotation dynamique.
Correction des noms dérivés des étiquettes
Certains contrôles microsoft Win32 courants, tels que le contrôle de zone d’édition, sont presque toujours utilisés avec une étiquette (une entrée LTEXT dans le fichier de ressources) ou une zone de groupe (GROUPBOX dans le fichier de ressources). Microsoft Active Accessibility dérive automatiquement la propriété name du contrôle de son étiquette. Pour ces contrôles, le texte de la fenêtre (affiché dans Microsoft Visual Studio en tant que propriété Name ou ID) est ignoré, car il est généralement généré automatiquement et rarement très descriptif ; par exemple, « IDC_EDIT1 ».
Si l’interface utilisateur de l’application n’est pas conçue correctement, Microsoft Active Accessibility risque de ne pas pouvoir définir le nom correctement. Pour être associé à un contrôle, l’étiquette ou la zone de groupe doivent être placées immédiatement avant le contrôle dynamique dans l’ordre de tabulation.
Vous pouvez modifier l’ordre de tabulation à l’aide de l’outil dans Visual Studio (dans le menu Format lorsque l’éditeur de ressources est ouvert) ou en modifiant directement le fichier de ressources.
L’exemple suivant montre la description d’un fichier de ressources d’une boîte de dialogue qui contient deux zones d’édition étiquetées.
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
LTEXT "First Name:",IDC_STATIC,8,16,43,8
LTEXT "Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
END
Dans cet exemple, les étiquettes et les contrôles ne sont pas répertoriés dans l’ordre de tabulation correct. Par conséquent, Microsoft Active Accessibility attribue le nom « Nom » à la zone d’édition du prénom et aucun nom du tout à la zone d’édition de nom.
L’exemple suivant montre la liste des ressources correcte. Notez également que les touches de raccourci ont été désignées dans les étiquettes.
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
LTEXT "&First Name:",IDC_STATIC,8,16,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
LTEXT "&Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
END
Lorsque les contrôles ont des étiquettes supplémentaires, telles que pour les valeurs minimales et maximales sur une barre de suivi, ces étiquettes doivent être placées après le contrôle dans l’ordre de tabulation. L’étiquette main du contrôle doit apparaître immédiatement avant le contrôle lui-même.
Nommer des contrôles sans étiquettes
Il n’est pas toujours possible ou souhaitable d’avoir une étiquette visible pour chaque contrôle. Toutefois, vous pouvez toujours fournir un nom pour le contrôle en ajoutant une étiquette invisible. Comme toujours, l’étiquette invisible doit immédiatement précéder le contrôle dans l’ordre de tabulation.
Si vous utilisez l’Éditeur de ressources dans Microsoft Visual Studio .NET, vous pouvez définir la propriété Visible sur False. Pour rendre l’étiquette invisible lors de la modification du fichier de ressources (.rc), ajoutez NOT WS_VISIBLE ou à la partie style du contrôle d’étiquette, comme illustré dans l’exemple suivant.
LTEXT "&FullName:",IDC_STATIC,111,23,44,8,NOT WS_VISIBLE
Notez que toute touche de raccourci désignée fonctionne même si l’étiquette est invisible.