Partager via


Ajout de fonctionnalités UI Automation aux serveurs Active Accessibility

Les contrôles qui n’ont pas de fournisseur d’automatisation de l’interface utilisateur Microsoft mais qui implémentent IAccessible peuvent facilement être mis à niveau pour fournir certaines fonctionnalités d’automatisation de l’interface utilisateur, en implémentant l’interface IAccessibleEx. Cette interface permet au contrôle d’exposer les propriétés d’automatisation de l’interface utilisateur et les modèles de contrôle, sans avoir besoin d’une implémentation complète des interfaces de fournisseur d’automatisation de l’interface utilisateur telles que IRawElementProviderFragment. Pour implémenter IAccessibleEx, la hiérarchie d’objets Microsoft Active Accessibility de base ne doit contenir aucune erreur ou incohérence (comme un objet enfant dont l’objet parent ne le répertorie pas en tant qu’enfant), et ne doit pas être en conflit avec les spécifications de l’automatisation de l’interface utilisateur. Si la hiérarchie d’objets Microsoft Active Accessibility répond à ces exigences, elle est un bon candidat pour ajouter des fonctionnalités en utilisant IAccessibleEx ; sinon, vous devez implémenter l’automatisation de l’interface utilisateur seule ou en parallèle avec l’implémentation de Microsoft Active Accessibility.

Prenons le cas d’un contrôle personnalisé qui a une valeur de plage. Le serveur Microsoft Active Accessibility pour le contrôle définit son rôle et est capable de renvoyer sa valeur actuelle, mais il ne peut pas renvoyer les valeurs minimales et maximales du contrôle, car ces propriétés ne sont pas définies dans Microsoft Active Accessibility. Un client d’automatisation de l’interface utilisateur est capable de récupérer le rôle du contrôle, la valeur actuelle et d’autres propriétés Microsoft Active Accessibility, car le noyau d’automatisation de l’interface utilisateur peut les obtenir via IAccessible. Cependant, sans accès à une interface IRangeValueProvider sur l’objet, l’automatisation de l’interface utilisateur ne peut pas non plus récupérer les valeurs maximales et minimales.

Le développeur de contrôle pourrait fournir un fournisseur d’automatisation de l’interface utilisateur complet pour le contrôle, mais cela signifierait dupliquer une grande partie de la fonctionnalité existante de l’implémentation IAccessible : par exemple, la navigation et les propriétés communes. Au lieu de cela, le développeur peut continuer à s’appuyer sur IAccessible pour fournir cette fonctionnalité, tout en ajoutant la prise en charge des propriétés spécifiques au contrôle via IRangeValueProvider.

La mise à jour du contrôle personnalisé nécessite les étapes principales suivantes :

  • Implémentez IServiceProvider sur l'objet accessible de sorte que l'interface IAccessibleEx se trouve sur cet objet ou sur un objet séparé.
  • implémentez IAccessibleEx sur l'objet accessible.
  • Créer des objets accessibles distincts pour tous les éléments enfants Microsoft Active Accessibility, qui dans Microsoft Active Accessibility pourraient avoir été représentés par l’interface IAccessible sur l’objet parent (par exemple, les éléments de liste). Implémentez IAccessibleEx sur ces objets.
  • Implémentez IRawElementProviderSimple sur tous les objets accessibles.
  • Implémentez les interfaces de modèle de contrôle appropriées sur les objets accessibles.

Cette rubrique contient les sections suivantes.

Exposition de IAccessibleEx

L'implémentation d'IAccessibleEx pour un contrôle peut résider dans un objet distinct. Par conséquent, les applications clientes ne peuvent pas compter sur QueryInterface pour obtenir cette interface. Les clients devraient plutôt émettre un appel IServiceProvider::QueryService. Dans l'exemple d'implémentation suivant de cette méthode, il est supposé que IAccessibleEx n'est pas implémenté sur un objet distinct. Par conséquent, la méthode émet des appels simplement via QueryInterface.

HRESULT CListboxAccessibleObject::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
{
    if (!ppvObject)
    {
        return E_INVALIDARG;
    }
    *ppvObject = NULL;
    if (guidService == __uuidof(IAccessibleEx))
    {
        return QueryInterface(riid, ppvObject);
    }
    else 
    {
        return E_INVALIDARG;
    }
};

Implémentation de IAccessibleEx

La méthode de IAccessibleEx qui est la plus intéressante est GetObjectForChild. Cette méthode donne au serveur Microsoft Active Accessibility l’opportunité de créer un objet accessible (un qui expose, au minimum, IAccessibleEx) pour un élément enfant. Dans Microsoft Active Accessibility, les éléments enfants ne sont généralement pas représentés comme des objets accessibles mais comme des enfants d’un objet accessible. Cependant, parce que l’automatisation de l’interface utilisateur exige que chaque élément soit représenté par un objet accessible distinct, GetObjectForChild doit créer un objet distinct pour chaque enfant à la demande.

L’exemple d’implémentation suivant renvoie un objet accessible pour un élément dans un affichage en mode liste personnalisé.

HRESULT CListboxAccessibleObject::GetObjectForChild(long idChild, IAccessibleEx **pRetVal)
{ 
    *pRetVal = NULL;
    VARIANT vChild;
    vChild.vt = VT_I4;
    vChild.lVal = idChild;

    // ValidateChildId is an application-defined function that checks whether
    // the child ID is valid. This is similar to code that validates the varChild
    // parameter in IAccessible methods.
    //
    // Additionally, if this idChild corresponds to a child that has its own
    // IAccessible, we should also return E_INVALIDARG here. (The caller
    // should instead be using the IAccessibleEx from that child's own
    // IAccessible in that case.)
    if (idChild == CHILDID_SELF || FAILED(ValidateChildId(vChild)))
    {
        return E_INVALIDARG;
    }

    // Return a suitable provider for this specific child.
    // This implementation returns a new instance each time; an implementation
    // can cache these if desired.

    // _pListboxControl is a member variable pointer to the owning control.
    IAccessibleEx* pAccEx  = new CListItemAccessibleObject(idChild, _pListboxControl);
    if (pAccEx == NULL)
    {
        return E_OUTOFMEMORY;
    }
    *pRetVal = pAccEx;
    return S_OK; 
}

Pour une implémentation d’exemple complète, veuillez consulter la section Rendre les contrôles personnalisés accessibles, Partie 5 : Utilisation de IAccessibleEx pour ajouter la prise en charge de l’automatisation de l’interface utilisateur à un contrôle personnalisé.

Guide du programmeur de fournisseur UI Automation