I. Introduction▲
Les fonctions d'accessibilité sont une interface de programmation développée par Microsoft.
En anglais : MSAA pour MicroSoft Active Accessibility.
L'interface est livrée sous forme d'API dans une librairie dll (oleacc.dll).
- La version 2.0 est livrée à partir de Windows XP.
- La version 3.0 est livrée à partir de Windows 7.
La version redistribuable 2.0 peut être téléchargée si nécessaire ici ou ici pour les versions de Window antérieures (Windows 98, Windows ME, Windows NT…).
(Une version antérieure est peut-être déjà installée par défaut et peut s'avérer suffisante).
Le tableau récapitulatif des versions est disponible ici : Supported Platforms
L'évolution des fonctions d'accessibilité dans Windows Vista s'appelle Microsoft UI Automation.
Ces fonctions sont utilisables dans toute application qui a implémenté cette interface :
- Office (Access, Excel, ...)
- Internet Explorer
- Le bureau de Windows
- L'explorateur de fichier Windows
- ....
Même si l'application n'est pas spécifiquement programmée pour, on pourra utiliser les fonctions d'accessibilité sur ses contrôles standards.
Chaque fenêtre ou contrôle est potentiellement un objet d'accessibilité.
On peut alors lui appliquer des fonctions d'accessibilité pour connaître :
- sa position (en pixel sur l'écran)
- son nom
- sa valeur
- son rôle (élément de liste, onglet, fenêtre, ...)
- son état (coché, sélectionné, ...)
- son parent
- ses enfants (les contrôles qu'il contient)
Et on peut également exécuter son action par défaut.
Si on peut lire beaucoup d'informations, il n'est pas possible d'agir sur ces objets avec les fonctions d'accessibilité (mise à part l'action par défaut).
Par contre on peut récupérer l'identifiant (handle) de la fenêtre à laquelle correspond un objet pour lui envoyer des messages.
II. Premières découvertes▲
La page d'accueil de la librairie MSDN est ici : Microsoft Active Accessibility
Pour bien débuter et comprendre ce que sont ces fameux objets d'accessibilité, le plus simple est d'utiliser les outils du SDK.
Ces outils sont disponibles dans le SDK Windows.
Ce SDK étant très volumineux, si vous ne l'avez pas déjà il peut être préférable de télécharger ces outils ici : gui-inspect-tool
Dans ce SDK vous avez 3 programmes intéressants :
- Accessible Explorer (AccExplorer32.exe)
- Inspect Objects (Inspect32.exe)
- Accessible Event Watcher (AccEvent32.exe)
Accessible Explorer permet de visualiser l'arborescence des objets d'une fenêtre.
Lancez le programme, cliquez sur la cible dans le menu :
Tirez la cible vers un formulaire Access et relâcher.
On visualise tous les objets d'accessibilité de ce formulaire.
(Cliquez sur Object => Highlight dans le menu pour visualiser l'objet sélectionné dans la liste)
Inspect Objects affiche les informations de l'objet qui se trouve sous le curseur de la souris.
Lancez le programme et essayez de déplacer la souris sur diverses applications.
Accessible Event Watcher est un programme qui permet de visualiser les événements qui ont lieu.
Ces trois programmes sont très utiles lors du développement pour nous aider à repérer les différents objets et leur comportement.
Vous trouverez également en téléchargement un fichier de documentation MSAAv2.doc (en anglais) qui recense les fonctions et constantes utilisées.
III. Comment utiliser ces fonctions d'accessibilité dans Office?▲
L'ensemble des fonctions d'accessibilité est regroupé dans la librairie oleacc.dll.
Il est nécessaire de déclarer les fonctions et variables pour y avoir accès.
Nous utiliserons dans la suite de l'article un module de classe qui encapsule ces fonctions pour plus de facilité.
Cependant, certains objets présentent une interface IAccessible qui permet de directement faire appel à certaines de ces fonctions.
Attention : ces fonctions ne sont pas documentées et doivent donc être utilisées avec prudence.
Voici une liste de ces objets (correspond à Access 2003) :
Librairie | Objet | Remarques |
---|---|---|
Office | CommandBar | Barre de menu |
Office | CommandBarButton | Bouton dans un menu |
Office | CommandBarComboBox | Liste déroulante dans un menu |
Office | CommandBarControl | Contrôle dans un menu |
Office | CommandBarPopup | Barre de menu contextuel |
Access | BoundObjectFrame | Cadre d'objet dépendant |
Access | CheckBox | Case à cocher |
Access | ComboBox | Zone de liste déroulante |
Access | CommandButton | Bouton de commande |
Access | CustomControl | Contrôle personnalisé |
Access | Form | Formulaire |
Access | Label | Etiquette |
Access | ListBox | Zone de liste |
Access | OptionButton | Bouton d'option |
Access | Page | Page d'onglet |
Access | OptionGroup | Groupe d'options |
Access | SubForm | Sous-formulaire |
Access | TabControl | Contrôle à onglets |
Access | TextBox | Zone de texte |
Access | ToggleButton | Bouton bascule |
Pour voir les fonctions non documentées :
- affichez l'explorateur d'objets dans l'éditeur VBA.
- click droit dans l'explorateur d'objets puis sélectionnez Afficher les membres masqués.
Pour les objets possédant une interface IAccessible, on note alors une série de fonctions commençant par acc.
IV. Les propriétés et méthodes de l'objet IAccessible▲
Téléchargez la documentation des fonctions et des propriétés (anglais)
Consultez la librairie MSDN (anglais)
Méthode ou propriété | Fonction | Remarques |
---|---|---|
accName | Nom de l'objet | - Le nom d'un contrôle est le texte de l'étiquette qui lui est attachée ou le nom du contrôle s'il n'a pas d'étiquette - Le nom d'une fenêtre est son titre |
accDefaultAction | Action par défaut | C'est un texte : Press, Ouvrir |
accDoDefaultAction | Déclenche l'action par défaut | |
accRole | Rôle de l'objet | Utiliser l'API GetRoleText pour récupérer le texte correspondant |
accState | Etat de l'objet | Utiliser l'API GetStateText pour récupérer le texte correspondant |
accParent | Objet parent | L'objet parent d'un contrôle par exemple est le client du formulaire |
accDescription | Description de l'objet | |
accKeyboardShortcut | Raccourci clavier de l'objet (pour les entrées de menu par exemple) | |
accChildCount | Nombre de sous-objets de l'objet | |
accFocus | Sous-objet qui a le focus | |
accLocation | Position de l'objet sur l'écran | Cette position est donnée en pixel. |
accHitTest | Sous-objet sous le curseur de la souris | |
accSelection | Liste des objets sélectionnés | |
accSelect | Modifie la sélection | |
accHelp | Texte d'aide | |
accHelpTopic | Fichier d'aide correspondant |
V. Utilisation directe des fonctions masquées dans Access▲
V-A. Première approche▲
Créez sur un nouveau formulaire une zone de texte txtTexte et un bouton btnBouton.
Sur click sur le bouton, ajouter ce code :
Private
Sub
btnBouton_Click
(
)
MsgBox
Me.txtTexte.accName
(
ByVal
0
&
)
End
Sub
Le paramètre ByVal 0& est important : il précise que la fonction s'applique sur l'objet et non pas un de ses sous-objet.
Pour information : ce paramètre correspond à la constante CHILDID_SELF.
Ouvrez le formulaire et cliquez sur le bouton.
Le message qui s'affiche contient le texte de l'étiquette rattachée à la zone de texte.
S'il n'y a pas d'étiquette, le message affiche le nom du contrôle.
Ajoutons l'affichage de la valeur de la zone de texte :
Private
Sub
btnBouton_Click
(
)
MsgBox
Me.txtTexte.accName
(
ByVal
0
&
) &
" :"
&
Me.txtTexte.accValue
(
ByVal
0
&
)
End
Sub
Si la zone de texte est vide, une erreur est levée (sur certaines versions), sinon son contenu s'affiche.
V-B. Elément survolé dans une liste▲
Nous allons aller un peu loin (et plus utile) en recherchant l'élément survolé par la souris sur une zone de liste.
Créez sur un nouveau formulaire une zone de liste lstListe contenant quelques éléments.
Ajoutez une zone de texte txtTexte.
Pour connaître la position de la souris, ajoutez ces déclarations en en-tête de module du formulaire.
Private
Declare
Function
GetCursorPos Lib
"user32.dll"
(
lpPoint As
PointAPI) As
Long
Private
Type
PointAPI
X As
Long
Y As
Long
End
Type
Sur souris déplacée sur la liste, ajouter ce code :
Private
Sub
lstListe_MouseMove
(
Button As
Integer
, Shift As
Integer
, X As
Single
, Y As
Single
)
Dim
lPt As
PointAPI
Dim
lElement As
Variant
' Position de la souris
GetCursorPos lPt
' Elément survolé
lElement =
Me.lstListe.accHitTest
(
lPt.X
, lPt.Y
)
' Inscrit le numéro de l'élément survolé dans la zone de texte
Me.txtTexte.Value
=
lElement
End
Sub
Ouvrez le formulaire et déplacer la souris sur la liste.
Le numéro de l'élément survolé s'affiche dans la zone de texte.
Notez que ce numéro débute à 1, contrairement à la propriété ListIndex de la zone de liste qui débute à 0.
On note également que lorsqu'on déplace la souris sur la liste en dessous du dernier élément, la fonction accHitTest renvoit 1 alors qu'on ne survole aucun élément.
Pour corriger ce problème, on va déterminer la position de l'élément avec la fonction accLocation pour la comparer à la position de la souris.
Private
Sub
lstListe_MouseMove
(
Button As
Integer
, Shift As
Integer
, X As
Single
, Y As
Single
)
Dim
lPt As
PointAPI
Dim
lElement As
Variant
Dim
lLeft As
Long
, lTop As
Long
, lWidth As
Long
, lHeight As
Long
' Position de la souris
GetCursorPos lPt
' Element survolé
lElement =
Me.lstListe.accHitTest
(
lPt.X
, lPt.Y
)
' Position de l'élément
Me.lstListe.accLocation
lLeft, lTop, lWidth, lHeight, lElement
' Vérifie qu'on survole effectivement l'élement
If
lPt.X
<
lLeft Or
lPt.X
>
lLeft +
lWidth Or
lPt.Y
<
lTop Or
lPt.Y
>
lTop +
lWidth Then
lElement =
0
End
If
' Inscris le numéro de l'élément survolé dans la zone de texte
Me.txtTexte.Value
=
lElement
End
Sub
On passe l'élément en paramètre de la fonction accLocation pour connaître sa position à l'écran.
Si on voulait lire la position de la liste, on utiliserait le paramètre Byval 0&
V-C. Conclusion▲
Nous n'avons pas développé ici toutes les possibilités de ces fonctions masquées.
Même si elles peuvent s'avérer utiles, elles sont toutefois limitées.
L'utilisation des API offre beaucoup plus de possibilités.
VI. Utilisation de l'API : librairie oleacc.dll▲
VI-A. Le module de classe clAccessibility▲
Pour faciliter l'utilisation des fonctions et constantes d'accessibilité, nous allons utiliser un module de classe spécifique.
Ce module se nomme clAccessibility.
Télécharger le module de classe au format texte
Une fois téléchargé et décompressé, importez le fichier clAccessibility.cls dans votre projet.
Dans le menu : Fichier => Importer un fichier ... (ou glisser-déposer le fichier dans le projet).
Le module de classe est nommé clAccessibility.
Ce module utilise un objet IAccessible que l'on peut trouver dans la librairie Microsoft Office XX Object Library.
Le XX correspond à la version d'Office installée.
Ajoutez donc une référence à cette librairie : Outils => Références ....
VI-B. Fonctionnement du module clAccessibility▲
Consultez la documentation des fonctions et des propriétés de ce module.
Pour utiliser ce module, il faut d'abord créer un objet de type clAccessibility.
Dim
oAcc As
ClAccessibility
Set
oAcc =
New
ClAccessibility
Ensuite, définissez l'objet avec une des fonctions SetAccObjFrom*.
Par exemple, pour un formulaire Access :
oAcc.SetAccObjFromObject
Me
Les fonctions et propriétés sont alors accessibles.
Par exemple, pour parcourir les éléments du formulaire et afficher leur nom et rôle :
Private
Sub
Commande0_Click
(
)
Dim
oAcc As
ClAccessibility
Dim
lCpt As
Long
Dim
ltexte As
String
' Nouvel objet
Set
oAcc =
New
ClAccessibility
' Définit le formulaire en objet
oAcc.SetAccObjFromObject
Me
' Boucle sur les sous-éléments
For
lCpt =
1
To
oAcc.Childcount
' Ajoute au texte le nom et le rôle du sous-élément
ltexte =
ltexte &
vbCrLf
&
oAcc.GetChild
(
lCpt).Name
&
" : "
&
oAcc.GetChild
(
lCpt).RoleText
Next
' Affiche le texte dans une boîte de message
MsgBox
ltexte
End
Sub
VI-C. Exemple 1 : afficher l'élément situé sous le curseur de la souris▲
Cet exemple est réalisé avec Excel.
Dans un nouveau module VBA, ajoutez une fonction qui va lire les informations de l'objet sous le curseur de la souris :
Function
DisplayElementUnderMouse
(
)
Dim
oAcc As
ClAccessibility
' Nouvel objet
Set
oAcc =
New
ClAccessibility
' Récupère l'objet sous le curseur de la souris
' Inscrit le nom et le rôle de l'objet sur la première cellule de la première feuille
If
oAcc.SetAccObjFromPosition
Then
Sheets
(
1
).Range
(
"A1"
).Value
=
oAcc.Name
&
" : "
&
oAcc.RoleText
Else
Sheets
(
1
).Range
(
"A1"
).Value
=
""
End
If
End
Function
Cette fonction récupère l'objet sous le curseur de la souris à l'aide de la fonction SetAccObjFromPosition.
Ensuite elle met à jour la première cellule de la première feuille avec les informations de l'objet récupéré.
Pour que cette fonction s'exécute en boucle on va utiliser la procédure OnTime.
Afin de pouvoir arrêter cette boucle, on utilise une variable gStop.
Option
Explicit
' Variable pour stopper le traitement
Private
gStop As
Boolean
' Fonction de lecture de l'objet sous la souris
Function
DisplayElementUnderMouse
(
)
Dim
oAcc As
ClAccessibility
' Nouvel objet
Set
oAcc =
New
ClAccessibility
' Récupère l'objet sous le curseur de la souris
' Inscrit le nom et le rôle de l'objet sur la première cellule de la première feuille
If
oAcc.SetAccObjFromPosition
Then
Sheets
(
1
).Range
(
"A1"
).Value
=
oAcc.Name
&
" : "
&
oAcc.RoleText
Else
Sheets
(
1
).Range
(
"A1"
).Value
=
""
End
If
' Relance la fonction dans une seconde sauf si stop demandé
If
Not
gStop Then
Application.OnTime
DateAdd
(
"s"
, 1
, Now
), "DisplayElementUnderMouse"
End
Function
' Lance l'affichage
Sub
StartDisplay
(
)
gStop =
False
DisplayElementUnderMouse
End
Sub
' Arrête l'affichage
Sub
StopDisplay
(
)
gStop =
True
End
Sub
Pour faciliter l'exécution des fonctions, créer sur la première feuille du classeur deux formes rectangulaires auxquelles vous affectez les procédures StartDisplay et StopDisplay.
Cliquez sur le premier bouton pour démarrer l'exécution.
La cellule en haut à gauche est actualisée toute les secondes avec les informations de l'élément situé sous le curseur de la souris.
Cliquez sur le deuxième bouton pour arrêter l'exécution.
Sur l'image, le curseur est positionné sur le menu Insertion d'Excel.
Il est cependant possible d'accéder à des objets n'appartenant pas à l'application Excel.
Nous allons le voir dans l'exemple suivant.
VI-D. Exemple 2 : Le bouton Démarrer de Windows.▲
VI-D-1. Exemple 2-a : Cliquer sur le bouton lorsqu'on le survole.▲
Cet exemple est réalisé avec Excel, à la suite du code précédent.
Si vous déplacez le curseur de la souris sur le menu démarrer, le code précédent nous indique : Démarrer : bouton poussoir.
Note : cela est identique avec les versions de Windows plus récentes (Windows 10 par exemple ).
On peut voir ces mêmes informations également à l'aide du programme inspect32.exe (voir le lien de téléchargement en introduction).
Pour cliquer sur le menu Démarrer de Windows lorsqu'on le survol, ajoutez ce code avant la relance de la fonction avec onTime.
' Si le curseur est sur un bouton poussoir de nom "Démarrer"
If
oAcc.Role
=
ROLE_SYSTEM_PUSHBUTTON And
oAcc.Name
=
"Démarrer"
Then
' Cliquer sur ce bouton
oAcc.DoDefaultAction
End
If
Lorsqu'on survole le bouton Démarrer, le programme clique dessus automatiquement.
VI-D-2. Exemple 2-b : Cliquer sur le bouton à la demande.▲
Cet exemple est réalisé avec Excel.
On a vu précédemment comment cliquer sur un bouton à l'aide de la fonction DoDefaultAction.
L'objet bouton était détecté lors du survol de la souris.
Comment faire pour retrouver ce bouton si on ne le survole pas ?
L'objet de plus haut niveau est le bureau Windows : à partir de lui on peut retrouver n'importe quel objet.
On peut donc écrire une petite fonction qui définit le bureau comme premier objet, et qui cherche ensuite le bouton Démarrer de manière récursive à l'aide de la fonction FindChild.
Function
ClickStartupMenu
(
)
Dim
oAcc As
ClAccessibility
' Nouvel objet
Set
oAcc =
New
ClAccessibility
oAcc.SetAccObjFromDesktop
OBJID_WINDOW
Set
oAcc =
oAcc.FindChild
(
"Démarrer"
, ROLE_SYSTEM_PUSHBUTTON, , , , True
)
If
Not
oAcc Is
Nothing
Then
oAcc.DoDefaultAction
End
If
End
Function
Si vous exécutez la fonction, le programme clique sur le bouton Démarrer.
C'est la méthode la plus simple mais certainement pas la plus efficace.
Première remarque : Est-on certain qu'il n'existe qu'un seul bouton nommé "Démarrer"?
Deuxième remarque : Il existe énormément d'objet d'accessibilité sur le bureau; la recherche peut prendre un certain temps s'il n'est pas situé vers le haut de l'arborescence.
Nous allons donc modifier la fonction pour ne plus utiliser l'option de récursivité de la recherche.
Il faut alors connaître exactement les parents de l'objet recherché.
Pour nous aider, on peut utiliser les programmes inspect32.exe ou AccExplorer32.exe.
On note les parents du bouton Démarrer et leurs informations utiles :
Nom | Rôle | Classe de fenêtre |
---|---|---|
Démarrer | Bouton poussoir | Button |
Démarrer | Fenêtre | Button |
Client | Shell_TrayWnd | |
Fenêtre | Shell_TrayWnd | |
Bureau | Client | #32769 |
Bureau | Fenêtre | #32769 |
Il est possible que certains objets n'aient pas de nom.
On peut alors également rechercher les objets à l'aide de la classe de fenêtre, ce que nous allons faire pour la barre des tâches (Shell_TrayWnd).
Le premier élément est l'élément recherché : un bouton poussoir de nom "Démarrer".
Le dernier élément est le bureau que l'on peut récupérer à l'aide de la fonction SetAccObjFromDesktop.
On démarre en fait de l'avant-dernier élément car la fonction nous permet de préciser qu'on veut récupérer l'objet client.
Function
ClickStartupMenu
(
)
Dim
oAcc As
ClAccessibility
' Nouvel objet
Set
oAcc =
New
ClAccessibility
' Objet Bureau : client
oAcc.SetAccObjFromDesktop
OBJID_CLIENT
' Barre des tâches : fenêtre
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_WINDOW, , "Shell_TrayWnd"
)
' Barre des tâches : client
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT, , "Shell_TrayWnd"
)
' Menu démarrer : fenêtre
Set
oAcc =
oAcc.FindChild
(
"Démarrer"
, ROLE_SYSTEM_WINDOW)
' Menu démarrer : bouton poussoir
Set
oAcc =
oAcc.FindChild
(
"Démarrer"
, ROLE_SYSTEM_PUSHBUTTON)
' Si on a trouver le bouton
If
Not
oAcc Is
Nothing
Then
' On clique dessus
oAcc.DoDefaultAction
End
If
End
Function
Exécutez la fonction pour ouvrir le menu démarrer.
Les fonctions FindChild ne sont pas récursives dans cet exemple.
On maîtrise la descente niveau par niveau jusqu'à l'objet recherché.
On a vu dans cet exemple un principe récurrent qui veut qu'il y a presque toujours une fenêtre contenant un client.
La fenêtre contient également la barre de titre, le menu système, les barres de défilements, ...
Le client contient notamment les contrôles (listes, boutons, ...).
VI-D-3. Exemple 2-c : Changer le texte du bouton Démarrer.▲
Cet exemple est réalisé avec Excel, à la suite du code précédent.
Cet exemple ne fonctionne qu'avec les anciennes versions de Windows où un texte était affiché sur le menu démarrer.
Nous allons modifier la fonction précédente ClickStartupMenu pour changer le texte du bouton Démarrer.
Le texte "Démarrer" est contenu dans la propriété name de l'objet.
Cette propriété est en écriture mais n'a aucun effet si on cherche à la modifier.
Même si cette propriété est bien définie en écriture pour l'objet IAccessible, elle n'est pas gérée en écriture par la plupart des objets. (C'est également le cas de la propriété value)
Par contre on peut modifier le texte de la fenêtre grâce à la fonction WindowSetText.
C'est fonction appelle l'API SetWindowText qui modifie le texte d'une fenêtre.
"Fenêtre" est à prendre au sens large : un bouton peut également être une fenêtre.
Function
ChangeStartupMenu
(
pText As
String
)
Dim
oAcc As
ClAccessibility
' Nouvel objet
Set
oAcc =
New
ClAccessibility
' Objet Bureau : client
oAcc.SetAccObjFromDesktop
OBJID_CLIENT
' Barre des tâches : fenêtre
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_WINDOW, , "Shell_TrayWnd"
)
' Barre des tâches : client
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT, , "Shell_TrayWnd"
)
' Menu démarrer : fenêtre
Set
oAcc =
oAcc.FindChild
(
"Démarrer"
, ROLE_SYSTEM_WINDOW)
' Menu démarrer : bouton poussoir
Set
oAcc =
oAcc.FindChild
(
"Démarrer"
, ROLE_SYSTEM_PUSHBUTTON)
' Si on a trouver le bouton
If
Not
oAcc Is
Nothing
Then
' On change le texte
oAcc.WindowSetText
, pText
End
If
End
Function
Dans la fenêtre d'exécution :
ChangeStartupMenu "Coucou"
Le texte du bouton est modifié :
VI-E. Exemple 3 : Lister le contenu de la zone de notification.▲
On va dans cet exemple lister le contenu de la zone de notification (les icônes à droite de la barre des tâches).
Pour changer, cet exemple est réalisé avec Word et Windows 7.
On note (à l'aide des programmes inspect32.exe ou AccExplorer32.exe) les parents d'une des icônes et leurs informations utiles :
Nom | Rôle | Classe de fenêtre |
---|---|---|
Volume | Bouton poussoir | ToolbarWindow32 |
Zone de notification | Barre d'outils | ToolbarWindow32 |
Zone de notification | Fenêtre | ToolbarWindow32 |
Client | SysPager | |
Fenêtre | SysPager | |
Client | TrayNotifyWnd | |
Fenêtre | TrayNotifyWnd | |
Client | Shell_TrayWnd | |
Fenêtre | Shell_TrayWnd | |
Bureau | Client | #32769 |
Bureau | Fenêtre | #32769 |
On navigue alors d'objet en objet jusqu'à trouver la barre d'outils contenant les icônes.
Puis on parcourt les sous-éléments et, si l'objet est visible, on ajoute au texte le nom et le rôle du sous-élément.
Function
ListSystray
(
)
Dim
oAcc As
ClAccessibility
Dim
lcpt As
Long
Dim
ltexte As
String
' Nouvel objet
Set
oAcc =
New
ClAccessibility
' Nouvel objet
Set
oAcc =
New
ClAccessibility
' Objet Bureau : client
oAcc.SetAccObjFromDesktop
OBJID_CLIENT
' Barre des tâches : fenêtre
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_WINDOW, , "Shell_TrayWnd"
)
' Barre des tâches : client
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT, , "Shell_TrayWnd"
)
' Zone de notification : fenêtre
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_WINDOW, , "TrayNotifyWnd"
)
' Zone de notification : client
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT, , "TrayNotifyWnd"
)
' SysPager : fenêtre
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_WINDOW, , "SysPager"
)
' SysPager : client
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT, , "SysPager"
)
' Barre d'outils : fenêtre
Set
oAcc =
oAcc.FindChild
(
"Zone de notification"
, ROLE_SYSTEM_WINDOW, , "ToolbarWindow32"
)
' Barre d'outils : client
Set
oAcc =
oAcc.FindChild
(
"Zone de notification"
, ROLE_SYSTEM_TOOLBAR, , "ToolbarWindow32"
)
' Boucle sur les sous-éléments
For
lcpt =
1
To
oAcc.Childcount
' Seulement si l'objet est visible
If
(
oAcc.GetChild
(
lcpt).State
And
STATE_SYSTEM_INVISIBLE) <>
STATE_SYSTEM_INVISIBLE Then
' Ajoute au texte le nom et le rôle du sous-élément
ltexte =
ltexte &
vbCrLf
&
oAcc.GetChild
(
lcpt).Name
&
" : "
&
oAcc.GetChild
(
lcpt).RoleText
End
If
Next
' Affiche le texte sur le document
ThisDocument.Content.Font.Size
=
6
ThisDocument.Content.Text
=
ltexte
End
Function
Exécutez la fonction pour lister les icônes visibles :
Connexion réseau sans fil PCMCIA (Fast3302_5fc4) Vitesse : 54,0 Mbits/s Force du signal : Excellent État : Connecté : bouton poussoir Retirer le périphérique en toute sécurité : bouton poussoir Windows Live Messenger (Hors ligne) : bouton poussoir Volume : bouton poussoir Source d'alimentation actuelle : Alimentation secteur Autonomie batterie : 100% Profil : Pleine puissance : bouton Connexion réseau sans fil Connexion sans fil non disponible Son virtuel TOSHIBA : Activé : bouton poussoir Intel(R) Graphics Media Accelerator Driver for Mobile : bouton poussoir Application Modem On Hold V.92 : bouton poussoir |
VI-F. Exemple 4 : Le ruban Office 2007.▲
Ces exemples sont réalisés avec Access, mais le code est similaire pour toute application ayant un ruban.
Les objets d'accessibilité du ruban sont décrits dans ce document (en anglais) :
Working with Active Accessibility in the 2007 Office Fluent User Interface
Pensez également à utiliser le programme AccExplorer32.exe pour voir l'arborescence des éléments du ruban.
Voici l'arborescence du ruban vu par le programme AccExplorer32.exe :
Ruban 2007 | Ruban 2010 |
Pour atteindre le ruban, on utilisera l'objet CommandBars. Ensuite on recherche l'objet de valeur Ribbon et de rôle ROLE_SYSTEM_PROPERTYPAGE.
Dim
oAcc As
ClAccessibility
Set
oAcc =
New
ClAccessibility
' Objet ruban
oAcc.SetAccObjFromObject
CommandBars
(
"ribbon"
)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE, "Ribbon"
, , , True
)
On obtient alors l'objet racine qui nous permettra d'accéder aux divers éléments du ruban.
VI-F-1. Exemple 4-a : Ouvrir le menu Office.▲
En version Office 2007, le menu Office a un rôle égal à ROLE_SYSTEM_BUTTONDROPDOWNGRID.
A partir de la version 2010, le menu Office est remplacé par un bouton poussoir simple « FICHIER » ; ce chapitre ne fonctionne donc que sur Office 2007.
Pour appuyer sur ce bouton, il suffit d'exécuter son action par défaut (DoDefaultAction).
Function
OpenOfficeMenu
(
)
Dim
oAcc As
ClAccessibility
Set
oAcc =
New
ClAccessibility
' Objet ruban
oAcc.SetAccObjFromObject
CommandBars
(
"ribbon"
)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE, "Ribbon"
, , , True
)
' Menu Office
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_BUTTONDROPDOWNGRID)
' Appuie sur le bouton du menu Office
oAcc.DoDefaultAction
End
Function
Si on exécute la fonction, le menu s'ouvre ou se ferme.
Si on souhaite ne pas fermer le menu, il faut vérifier s'il est déjà ouvert en testant la propriété state.
Function
OpenOfficeMenu
(
)
Dim
oAcc As
ClAccessibility
Set
oAcc =
New
ClAccessibility
' Objet ruban
oAcc.SetAccObjFromObject
CommandBars
(
"ribbon"
)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE, "Ribbon"
, , , True
)
' Menu Office
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_BUTTONDROPDOWNGRID)
' Si le bouton n'est pas déjà pressé
If
(
oAcc.State
And
STATE_SYSTEM_PRESSED) <>
STATE_SYSTEM_PRESSED Then
' Ouvre le menu Office
oAcc.DoDefaultAction
End
If
End
Function
VI-F-2. Exemple 4-b : Lister les onglets du ruban.▲
Les onglets sont listés dans l'objet de rôle ROLE_SYSTEM_PAGETABLIST (en fait dans son client).
Remarque : les onglets contextuels sont des objets de rôle ROLE_SYSTEM_PAGETAB inclus dans un objet de rôle ROLE_SYSTEM_GROUPING.
Dans l'exemple ci-dessous, on ne les gère pas.
Function
ListRibbonTabs
(
)
Dim
oAcc As
ClAccessibility
Dim
oTab As
ClAccessibility
Dim
lCpt As
Long
Dim
lText As
String
Set
oAcc =
New
ClAccessibility
' Objet ruban
oAcc.SetAccObjFromObject
CommandBars
(
"ribbon"
)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE, "Ribbon"
, , , True
)
' Liste des onglets
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PAGETABLIST)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT)
' Parcourt les sous-éléments
For
lCpt =
1
To
oAcc.Childcount
' Sous-élement
Set
oTab =
oAcc.GetChild
(
lCpt)
' Si le sous-élément est un onglet
If
oTab.Role
=
ROLE_SYSTEM_PAGETAB Then
' Ajoute son nom et s'il est visible ou non
lText =
lText &
vbCrLf
&
oTab.Name
&
" :"
&
IIf
((
oTab.State
And
STATE_SYSTEM_FOCUSABLE) =
STATE_SYSTEM_FOCUSABLE, "visible"
, "invisible"
)
End
If
Next
' Affiche le texte
MsgBox
lText
End
Function
Ce code affiche la liste des onglets dans une boîte de message.
VI-F-3. Exemple 4-c : Connaître l'onglet actif.▲
L'objet représentant l'onglet actif est situé dans le ruban inférieur (valeur Lower Ribbon de rôle ROLE_SYSTEM_PANE).
Ce ruban inférieur contient d'abord un client (ROLE_SYSTEM_CLIENT) puis l'onglet actif de rôle ROLE_SYSTEM_PROPERTYPAGE.
Créez un nouveau formulaire contenant une zone de texte nommé txtTexte.
Cette zone de texte affichera le nom de l'onglet courant.
Dans l'événement Sur minuterie du formulaire, on récupère l'objet représentant l'onglet courant et on inscrit le nom de cet onglet dans la zone de texte.
Private
Sub
Form_Timer
(
)
Dim
oAcc As
ClAccessibility
Set
oAcc =
New
ClAccessibility
' Objet ruban
oAcc.SetAccObjFromObject
CommandBars
(
"ribbon"
)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE, "Ribbon"
, , , True
)
' Ruban inférieur
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PANE, "Lower Ribbon"
)
' Client sans nom
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT)
' Onglet actif
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE)
' Inscrit le nom de l'onglet actif dans la zone de texte
If
Not
oAcc Is
Nothing
Then
Me.txtTexte.Value
=
oAcc.Name
End
Sub
N'oublions pas de préciser un intervalle de minuterie dans les propriétés du formulaire.
Afficher le formulaire et naviguer dans les onglets pour tester le code.
VI-F-4. Exemple 4-d : Activer un onglet.▲
Dans cet exemple nous souhaitons activer un onglet.
Cela peut être utile pour afficher un onglet spécifique en fonction du contrôle actif.
Activer un onglet est simple : il suffit d'exécuter son action par défaut (DoDefaultAction).
Créez un nouveau formulaire dans lequel vous placez une zone de liste nommée lstOnglets.
La propriété Origine source de cette liste doit être égale à Liste valeurs.
On remplit la liste des onglets au démarrage du formulaire.
Le code est similaire à celui vu dans l'exemple 4-b : Lister les onglets du ruban.
Private
Sub
Form_Load
(
)
Dim
oAcc As
ClAccessibility
Dim
oTab As
ClAccessibility
Dim
lCpt As
Long
Set
oAcc =
New
ClAccessibility
' Objet ruban
oAcc.SetAccObjFromObject
CommandBars
(
"ribbon"
)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE, "Ribbon"
, , , True
)
' Liste des onglets
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PAGETABLIST)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT)
' Initialise la liste
Me.lstOnglets.RowSource
=
""
' Parcourt les sous-éléments
For
lCpt =
1
To
oAcc.Childcount
' Sous-élement
Set
oTab =
oAcc.GetChild
(
lCpt)
' Si le sous-élément est un onglet
If
oTab.Role
=
ROLE_SYSTEM_PAGETAB Then
' Ajoute son nom à la liste
If
Not
Me.lstOnglets.RowSource
=
""
Then
Me.lstOnglets.RowSource
=
Me.lstOnglets.RowSource
&
";"
Me.lstOnglets.RowSource
=
Me.lstOnglets.RowSource
&
oTab.Name
End
If
Next
End
Sub
Ensuite lorsqu'on choisit un onglet dans la liste, on active l'onglet correspondant dans le ruban.
Private
Sub
lstOnglets_AfterUpdate
(
)
Dim
oAcc As
ClAccessibility
Dim
oTab As
ClAccessibility
Dim
lCpt As
Long
Set
oAcc =
New
ClAccessibility
' Objet ruban
oAcc.SetAccObjFromObject
CommandBars
(
"ribbon"
)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PROPERTYPAGE, "Ribbon"
, , , True
)
' Liste des onglets
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_PAGETABLIST)
Set
oAcc =
oAcc.FindChild
(
, ROLE_SYSTEM_CLIENT)
' Parcourt les sous-éléments
For
lCpt =
1
To
oAcc.Childcount
' Sous-élement
Set
oTab =
oAcc.GetChild
(
lCpt)
' Si le sous-élément est l'onglet sélectionné dans la liste
If
oTab.Role
=
ROLE_SYSTEM_PAGETAB And
oTab.Name
=
Nz
(
Me.lstOnglets.Value
) Then
' Active l'onglet
oTab.DoDefaultAction
End
If
Next
End
Sub
Choisissez un élément de la liste, l'onglet correspondant s'affiche.
Remarque : on n'a pas filtré les onglets invisibles.
Si vous cliquez sur une entrée de liste correspondant à un onglet invisible, rien ne se produit.
VI-G. Conclusion▲
Les possibilités des fonctions d'accessibilité sont nombreuses.
Parfois on peut utiliser conjointement ces fonctions d'accessibilité et les fonctions de l'API Windows pour encore plus de possibilités.
Dernière remarque : il ne faut pas oublier d'utiliser les outils du SDK pour analyser les objets.
VII. Remerciements▲
Merci à l'équipe Office pour ses tests et relectures.
Merci à developpez.com pour son hébergement de qualité.