Implémentation du fournisseur d'automatisation de l'interface utilisateur côté serveur

Note

Cette documentation est destinée aux développeurs .NET Framework qui souhaitent utiliser les classes d'automatisation de l'interface utilisateur gérées définies dans le namespace System.Windows.Automation. Pour obtenir les dernières informations sur UI Automation, consultez API Windows Automation : UI Automation.

Cette section explique comment implémenter un fournisseur UI Automation côté serveur pour un contrôle personnalisé.

L’implémentation des éléments WPF (Windows Presentation Foundation) et des éléments non WPF (tels que ceux conçus pour Windows Forms) est fondamentalement différente. Les éléments WPF prennent en charge UI Automation via une classe dérivée de AutomationPeer. Les éléments non WPF prennent en charge les implémentations d’interfaces de fournisseur.

Considérations relatives à la sécurité

Les fournisseurs doivent être conçus pour pouvoir fonctionner dans un environnement de confiance partielle. Étant donné que UIAutomationClient.dll n’est pas configuré pour s’exécuter en cas d’approbation partielle, le code de votre fournisseur ne doit pas référencer cet assembly. Dans ce cas, le code peut s’exécuter dans un environnement de confiance totale, mais échouer dans un environnement de confiance partielle.

En particulier, n’utilisez pas de champs de classes dans UIAutomationClient.dll telles que celles de AutomationElement. Utilisez plutôt les champs équivalents des classes dans UIAutomationTypes.dll, tels que AutomationElementIdentifiers.

Implémentation du fournisseur dans les éléments de Windows Presentation Foundation

Pour plus d’informations sur cette rubrique, consultez UI Automation d’un contrôle personnalisé WPF.

Implémentation du fournisseur par des éléments non WPF

Les contrôles personnalisés qui ne font pas partie de l’infrastructure WPF, mais qui sont écrits dans du code managé (le plus souvent, il s’agit de contrôles Windows Forms), prennent en charge UI Automation en implémentant des interfaces. Chaque élément doit implémenter au moins l’une des interfaces répertoriées dans le premier tableau de la section suivante. En outre, si l’élément prend en charge un ou plusieurs modèles de contrôle, il doit implémenter l’interface appropriée pour chaque modèle de contrôle.

Votre projet de fournisseur d'automatisation de l'interface utilisateur doit référencer les assemblages suivants :

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

Interfaces de fournisseur

Chaque fournisseur UI Automation doit implémenter l’une des interfaces suivantes.

Interface Description
IRawElementProviderSimple Fournit des fonctionnalités pour un contrôle simple hébergé dans une fenêtre, notamment la prise en charge des modèles de contrôle et des propriétés.
IRawElementProviderFragment Hérite de IRawElementProviderSimple. Ajoute des fonctionnalités pour un élément dans un contrôle complexe, notamment la navigation dans le fragment, la définition du focus et le renvoi du rectangle délimitant de l’élément.
IRawElementProviderFragmentRoot Hérite de IRawElementProviderFragment. Ajoute des fonctionnalités pour l’élément racine dans un contrôle complexe, notamment la localisation d’un élément enfant à des coordonnées spécifiées et la définition de l’état du focus pour l’ensemble du contrôle.

Les interfaces suivantes fournissent des fonctionnalités ajoutées, mais ne sont pas requises pour être implémentées.

Interface Description
IRawElementProviderAdviseEvents Permet au fournisseur de suivre les demandes d’événements.
IRawElementProviderHwndOverride Permet le repositionnement d’éléments basés sur des fenêtres dans l’arborescence UI Automation d’un fragment.

Toutes les autres interfaces dans l'espace de noms System.Windows.Automation.Provider sont destinées à la prise en charge des modèles de contrôle.

Conditions requises pour les fournisseurs non WPF

Pour communiquer avec UI Automation, votre contrôle doit implémenter les principaux domaines de fonctionnalités suivants :

Fonctionnalité Mise en œuvre
Exposer le fournisseur à UI Automation En réponse à un message WM_GETOBJECT envoyé à la fenêtre de contrôle, retournez l’objet qui implémente IRawElementProviderSimple (ou une interface dérivée). Pour les fragments, il doit s’agir du fournisseur de la racine du fragment.
Fournir des valeurs de propriété Implémentez GetPropertyValue pour fournir ou remplacer des valeurs.
Permettre au client d’interagir avec le contrôle Implémentez des interfaces qui prennent en charge les modèles de contrôle, tels que IInvokeProvider. Retournez ces fournisseurs de modèles dans votre implémentation de GetPatternProvider.
Déclencher des événements Appelez l'une des méthodes statiques de AutomationInteropProvider pour déclencher un événement auquel un client peut s'abonner.
Activer la navigation et se concentrer dans un fragment Implémentez IRawElementProviderFragment pour chaque élément dans le fragment. (Non nécessaire pour les éléments qui ne font pas partie d’un fragment.)
Activer le focus et l’emplacement de l’élément enfant dans un fragment Implémentez IRawElementProviderFragmentRoot. (Non nécessaire pour les éléments qui ne sont pas des racines de fragment.)

Valeurs de propriété dans les fournisseurs qui ne prennent pas en charge WPF

Les fournisseurs UI Automation pour les contrôles personnalisés doivent prendre en charge certaines propriétés qui peuvent être utilisées par le système Automation ainsi que par les applications clientes. Pour les éléments hébergés dans des fenêtres (HWND), UI Automation peut récupérer certaines propriétés du fournisseur de fenêtres par défaut, mais doit obtenir d’autres éléments auprès du fournisseur personnalisé.

Les fournisseurs pour les contrôles HWND n’ont généralement pas besoin de fournir les propriétés suivantes (identifiées par les valeurs de champ) :

Note

L’élément RuntimeIdProperty simple ou la racine de fragment hébergé dans une fenêtre est obtenue à partir de la fenêtre. Toutefois, les éléments de fragment sous la racine (tels que les éléments de liste dans une zone de liste) doivent fournir leurs propres identificateurs. Pour plus d’informations, consultez GetRuntimeId.

Le IsKeyboardFocusableProperty doit être renvoyé pour les fournisseurs hébergés dans un contrôle Windows Forms. Dans ce cas, le fournisseur de fenêtres par défaut peut ne pas pouvoir récupérer la valeur correcte.

Il NameProperty est généralement fourni par le fournisseur hôte. Par exemple, si un contrôle personnalisé est dérivé de Control, le nom est dérivé de la Text propriété du contrôle.

Pour obtenir un exemple de code, consultez Propriétés renvoyées par un fournisseur d’UI Automation.

Événements dans les fournisseurs non WPF

Les fournisseurs UI Automation doivent déclencher des événements pour informer les applications clientes des modifications apportées à l’état de l’interface utilisateur. Les méthodes suivantes sont utilisées pour déclencher des événements.

Méthode Description
RaiseAutomationEvent Déclenche différents événements, y compris les événements déclenchés par des modèles de contrôle.
RaiseAutomationPropertyChangedEvent Déclenche un événement lorsqu’une propriété UI Automation a changé.
RaiseStructureChangedEvent Déclenche un événement lorsque la structure de l’arborescence UI Automation a changé ; par exemple, par la suppression ou l’ajout d’un élément.

L’objectif d’un événement est d’informer le client d’un élément qui se produit dans l’interface utilisateur (IU), que l’activité soit déclenchée ou non par le système UI Automation lui-même. Par exemple, l’événement identifié par InvokedEvent doit être déclenché chaque fois que le contrôle est appelé, par le biais d’une entrée utilisateur directe ou par l’appel de l’application cliente Invoke.

Pour optimiser les performances, un fournisseur peut déclencher sélectivement des événements ou déclencher aucun événement du tout si aucune application cliente n’est inscrite pour les recevoir. Les méthodes suivantes sont utilisées pour l’optimisation.

Méthode Description
ClientsAreListening Cette propriété statique spécifie si les applications clientes se sont abonnées aux événements UI Automation.
IRawElementProviderAdviseEvents L’implémentation par le fournisseur de cette interface dans une racine de fragment lui permet d’être informé lorsque les clients inscrivent et désinscrivent des gestionnaires d’événements pour les événements sur le fragment.

Navigation du fournisseur non WPF

Les fournisseurs de contrôles simples tels qu’un bouton personnalisé hébergé dans une fenêtre (HWND) n’ont pas besoin de prendre en charge la navigation dans l’arborescence UI Automation. La navigation vers et à partir de l’élément est gérée par le fournisseur par défaut pour la fenêtre hôte, qui est spécifiée dans l’implémentation de HostRawElementProvider. Toutefois, lorsque vous implémentez un fournisseur pour un contrôle personnalisé complexe, vous devez prendre en charge la navigation entre le nœud racine du fragment et ses descendants, et entre les nœuds frères.

Note

Les éléments d’un fragment autres que la racine doivent renvoyer une référence null de HostRawElementProvider, car ils ne sont pas directement hébergés dans une fenêtre, et aucun fournisseur par défaut ne peut prendre en charge la navigation vers et depuis eux.

La structure du fragment est déterminée par votre implémentation de Navigate. Pour chaque direction possible de chaque fragment, cette méthode retourne l’objet fournisseur de l’élément dans cette direction. S’il n’existe aucun élément dans cette direction, la méthode retourne une null référence.

La racine du fragment prend en charge la navigation uniquement vers les éléments enfants. Par exemple, une zone de liste renvoie le premier élément de la liste lorsque la direction est FirstChild, et le dernier élément lorsque la direction est LastChild. La racine du fragment ne prend pas en charge la navigation vers un parent ou un frère ; ceci est géré par le fournisseur de fenêtres hôte.

Les éléments d’un fragment qui ne sont pas la racine doivent permettre la navigation vers le parent, ainsi que vers leurs frères et enfants.

Réparentation du fournisseur non WPF

Les fenêtres contextuelles sont en fait des fenêtres de niveau supérieur. Par défaut, elles apparaissent dans l’arborescence UI Automation en tant qu’enfants du bureau. Toutefois, dans de nombreux cas, les fenêtres contextuelles sont logiquement des enfants d’un autre contrôle. Par exemple, la liste déroulante d’une zone de liste est logiquement un sous-élément de celle-ci. De même, une fenêtre contextuelle de menu est logiquement un enfant du menu. UI Automation prend en charge la réassignation des fenêtres contextuelles afin qu'elles paraissent être des enfants du contrôle associé.

Pour réparer une fenêtre contextuelle :

  1. Créez un fournisseur pour la fenêtre contextuelle. Cela nécessite que la classe de la fenêtre contextuelle soit connue à l’avance.

  2. Implémentez toutes les propriétés et modèles comme d’habitude pour cette fenêtre contextuelle, comme s’il s’agissait d’un contrôle à part entière.

  3. Implémentez la propriété HostRawElementProvider afin qu’elle retourne la valeur obtenue à partir de HostProviderFromHandle, dont le paramètre est le handle de la fenêtre contextuelle.

  4. Mettez en œuvre Navigate pour la fenêtre contextuelle et son parent afin que la navigation soit gérée correctement du parent logique aux enfants logiques et entre les enfants de même niveau.

Lorsque UI Automation rencontre la fenêtre contextuelle, il reconnaît que la navigation est remplacée par la valeur par défaut et ignore la fenêtre contextuelle lorsqu’elle est rencontrée en tant qu’enfant du bureau. Au lieu de cela, le nœud n’est accessible qu’à travers le fragment.

La réparentation n’est pas adaptée aux cas où un contrôle peut héberger une fenêtre de n’importe quelle classe. Par exemple, une barre d'outils peut contenir n'importe quel type de HWND dans ses bandes. Pour gérer ces cas, UI Automation prend en charge une autre forme de réaffectation HWND, comme décrit dans la section suivante.

Repositionnement du fournisseur non-WPF

Les fragments UI Automation peuvent contenir deux éléments ou plus contenus dans une fenêtre (HWND). Étant donné que chaque HWND a son propre fournisseur par défaut qui considère que le HWND est un enfant d’un HWND contenant, l’arborescence UI Automation affiche, par défaut, les HWND dans le fragment en tant qu’enfants de la fenêtre parente. Dans la plupart des cas, il s’agit d’un comportement souhaitable, mais il peut parfois entraîner une confusion, car il ne correspond pas à la structure logique de l’interface utilisateur.

Voici un bon exemple de contrôle de l'armature. Une barre de renfort contient des bandes, chacune pouvant à son tour contenir un contrôle basé sur HWND, tel qu'une barre d’outils, une zone de texte ou une zone de liste déroulante. Le fournisseur de fenêtre par défaut pour le HWND de la barre de rebord considère les HWND de contrôle de bande comme des enfants, et le fournisseur de bande voit les bandes comme des enfants. Étant donné que le fournisseur HWND et le fournisseur de barres de rébar travaillent de concert et combinent leurs sous-éléments, les bandes ainsi que les contrôles basés sur HWND apparaissent comme des sous-éléments de la barre de rébar. Toutefois, logiquement, seules les bandes doivent apparaître en tant qu’enfants du rebar, et chaque gestionnaire de bande doit être couplé avec le fournisseur HWND par défaut pour le contrôle qu’il accompagne.

Pour ce faire, le fournisseur racine de fragment pour la barre d'armature expose un ensemble d’enfants représentant les bandes. Chaque bande a un seul fournisseur qui peut exposer des propriétés et des modèles. Dans son implémentation, le fournisseur de bande HostRawElementProvider retourne le fournisseur de fenêtre par défaut pour le contrôle HWND, qu’il obtient en appelant HostProviderFromHandle, en passant le descripteur de fenêtre du contrôle. Enfin, le fournisseur racine de fragment pour la barre de renfort réalise l’interface IRawElementProviderHwndOverride et, dans son exécution de GetOverrideProviderForHwnd, il retourne le fournisseur de bande approprié pour le contrôle contenu dans le HWND spécifié.

Voir également