Utilisation d’IAccessibleEx à partir d’un client

Cette rubrique explique comment les clients accèdent à l’implémentation IAccessibleEx d’un serveur et l’utilisent pour obtenir des propriétés UI Automation et des modèles de contrôle pour les éléments d’interface utilisateur.

Les procédures et exemples de cette section supposent un client IAccessible déjà en cours de traitement et un serveur Microsoft Active Accessibility existant. Ils supposent également que le client a déjà obtenu un objet IAccessible à l’aide de l’une des fonctions d’infrastructure d’accessibilité telles que AccessibleObjectFromEvent, AccessibleObjectFromPoint ou AccessibleObjectFromWindow.

Obtention d’une interface IAccessibleEx à partir de l’interface IAccessible

Un client disposant d’une interface IAccessible pour un objet accessible peut l’utiliser pour obtenir l’interface IAccessibleEx correspondante en procédant comme suit :

Gestion de l’ID enfant

Les clients doivent être préparés pour les serveurs avec un ID enfant autre que CHILDID_SELF. Après avoir obtenu une interface IAccessibleEx à partir d’un IAccessible, les clients doivent appeler IAccessibleEx::GetObjectForChild si l’ID enfant n’est pas CHILDID_SELF (indiquant un objet parent).

L’exemple suivant montre comment obtenir un IAccessibleEx pour un objet IAccessible et un ID enfant particulier.

   
HRESULT GetIAccessibleExFromIAccessible(IAccessible * pAcc, long idChild, 
                                           IAccessibleEx ** ppaex)
{
    *ppaex = NULL;

    // First, get IServiceProvider from the IAccessible.
    IServiceProvider * pSp = NULL;
    HRESULT hr = pAcc->QueryInterface(IID_IServiceProvider, (void **) & pSp);
    if(FAILED(hr))
        return hr;
    if(pSp == NULL)
        return E_NOINTERFACE;

    // Next, get the IAccessibleEx for the parent object.
    IAccessibleEx * paex = NULL;
    hr = pSp->QueryService(__uuidof(IAccessibleEx), __uuidof(IAccessibleEx),
                                                                 (void **)&paex);
    pSp->Release();
    if(FAILED(hr))
        return hr;
    if(paex == NULL)
        return E_NOINTERFACE;

    // If this is for CHILDID_SELF, we're done. Otherwise, we have a child ID and 
    // can request the object for child.
    if(idChild == CHILDID_SELF)
    {
        *ppaex = paex;
        return S_OK;
    }
    else
    {
        // Get the IAccessibleEx for the specified child.
        IAccessibleEx * paexChild = NULL;
        hr = paex->GetObjectForChild(idChild, &paexChild);
        paex->Release();
        if(FAILED(hr))
            return hr;
        if(paexChild == NULL)
            return E_NOINTERFACE;
        *ppaex = paexChild;
        return S_OK;
    }
}

Obtention de l’interface IRawElementProviderSimple

Si un client a une interface IAccessibleEx , il peut utiliser QueryInterface pour accéder à l’interface IRawElementProviderSimple , comme le montre l’exemple suivant.

HRESULT GetIRawElementProviderFromIAccessible(IAccessible * pAcc, long idChild,
                                                 IRawElementProviderSimple ** ppEl)
{
    * ppEl = NULL;

    // First, get the IAccessibleEx for the IAccessible and child ID pair.
    IAccessibleEx * paex;
    HRESULT hr = GetIAccessibleExFromIAccessible( pAcc, idChild, &paex );
    if(FAILED(hr))
        return hr;

    // Next, use QueryInterface.
    hr = paex->QueryInterface(__uuidof(IRawElementProviderSimple), (void **)ppEl);
    paex->Release();
    return hr;
}

Récupération des modèles de contrôle

Si un client a accès à l’interface IRawElementProviderSimple , il peut récupérer des interfaces de modèle de contrôle qui ont été implémentées par les fournisseurs, puis appeler des méthodes sur ces interfaces. L’exemple suivant vous montre comment procéder.

// Helper function to get a pattern interface from an IAccessible and child ID 
// pair. Gets the IAccessibleEx, then calls GetPatternObject and QueryInterface.
HRESULT GetPatternFromIAccessible(IAccessible * pAcc, long idChild,
                                     PATTERNID patternId, REFIID iid, void ** ppv)
{
    // First, get the IAccesibleEx for this IAccessible and child ID pair.
    IRawElementProviderSimple * pel;
    HRESULT hr = GetIRawElementProviderSimpleFromIAccessible(pAcc, idChild, &pel);
    if(FAILED(hr))
        return hr;
    if(pel == NULL)
        return E_NOINTERFACE;

    // Now get the pattern object.
    IUnknown * pPatternObject = NULL;
    hr = pel->GetPatternProvider(patternId, &pPatternObject);
    pel->Release();
    if(FAILED(hr))
        return hr;
    if(pPatternObject == NULL)
        return E_NOINTERFACE;

    // Finally, use QueryInterface to get the correct interface type.
    hr = pPatternObject->QueryInterface(iid, ppv);
    pPatternObject->Release();
    if(*ppv == NULL)
        return E_NOINTERFACE;
    return hr;
}

HRESULT CallInvokePatternMethod(IAccessible * pAcc, long idChild)
{
    IInvokeProvider * pPattern;
    HRESULT hr = GetPatternFromIAccessible(pAcc, varChild,
                                  UIA_InvokePatternId, __uuidof(IInvokeProvider),
                                  (void **)&pPattern);
    if(FAILED(hr))
        return hr;

    hr = pPattern->Invoke();
    pPattern->Release();
    return hr;
}

Récupération des valeurs de propriété

Si un client a accès à IRawElementProviderSimple, il peut récupérer des valeurs de propriété. L’exemple suivant montre comment obtenir des valeurs pour les propriétés AutomationId et LabeledBy Microsoft UI Automation.

#include <initguid.h>
#include <uiautomationcoreapi.h> // Includes the UI Automation property GUID definitions.
#include <uiautomationcoreids.h> // Includes definitions of pattern/property IDs.

// Assume we already have a IRawElementProviderSimple * pEl.

VARIANT varValue;

// Get AutomationId property:
varValue.vt = VT_EMPTY;
HRESULT hr = pEl->GetPropertyValue(UIA_AutomationIdPropertyId, &varValue);
if(SUCCEEDED(hr))
{
    if(varValue.vt == VT_BSTR)
    {
        // AutomationId is varValue.bstrVal.
    }
    VariantClear(&varValue);
}


// Get LabeledBy property:
varValue.vt = VT_EMPTY;
hr = pEl->GetPropertyValue(UIA_LabeledByPropertyId, &varValue);
if(SUCCEEDED(hr))
{
    if(varValue.vt == VT_UNKNOWN || varValue.punkVal != NULL)
    {
        // Use QueryInterface to get IRawElementProviderSimple.
        IRawElementProviderSimple * pElLabel = NULL;
        hr = varValue.punkVal->QueryInterface(__uuidof(IRawElementProviderSimple),
                                              (void**)& pElLabel);
        if (SUCCEEDED(hr))
        {
            if(pElLabel != NULL)
            {
            // Use the pElLabel pointer here.
            pElLabel ->Release();
            }
        }
    }
    VariantClear(&varValue);
}

L’exemple précédent s’applique aux propriétés qui ne sont pas associées à un modèle de contrôle. Pour accéder aux propriétés du modèle de contrôle, un client doit obtenir et utiliser une interface de modèle de contrôle.

Récupération d’une interface IAccessible à partir d’une interface IRawElementProviderSimple

Si un client obtient l’interface IRawElementProviderSimple pour un élément d’interface utilisateur, le client peut utiliser cette interface pour obtenir une interface IAccessible correspondante pour l’élément. Cela est utile si le client doit accéder aux propriétés Microsoft Active Accessibility pour l’élément.

Un client peut obtenir l’interface IRawElementProviderSimple en tant que valeur de propriété (par exemple, en appelant IRawElementProviderSimple::GetPropertyValue avec UIA_LabeledByPropertyId), ou en tant qu’élément récupéré par une méthode (par exemple, en appelant ISelectionProvider::GetSelection pour récupérer un tableau d’interfaces IRawElementProviderSimple d’éléments sélectionnés). Après avoir obtenu l’interface IRawElementProviderSimple , un client peut l’utiliser pour obtenir un IAccessible correspondant en procédant comme suit :

L’extrait de code suivant montre comment obtenir l’interface IAccessible à partir d’une interface IRawElementProviderSimple obtenue précédemment.

// IRawElementProviderSimple * pVal - an element returned by a property or method
// from another IRawElementProviderSimple.

IAccessible * pAcc = NULL;
long idChild;

// First, try to use QueryInterface to get the IAccessibleEx interface.
IAccessibleEx * pAccEx;
HRESULT hr = pVal->QueryInterface(__uuidof(IAccessibleEx), (void**)&pAccEx);
if (SUCCEEDED(hr)
{
    if (!pAccEx)
    {
        // If QueryInterface fails, and the IRawElementProviderSimple was 
              // obtained as a property or return value from another 
              // IRawElementProviderSimple, pass it to the 
              // IAccessibleEx::ConvertReturnedValue method of the
        // originating element.

        pAccExOrig->ConvertReturnedElement(pVal, &pAccEx);
    }

    if (pAccEx)
    {
        // Call GetIAccessiblePair to get an IAccessible interface and 
              // child ID.
        pAccEx->GetIAccessiblePair(&pAcc, &idChild);
    }

    // Finally, use the IAccessible interface and child ID.
    if (pAcc)
    {
        // Use IAccessible methods to get further information about this UI
              // element, or pass it to existing code that works in terms of 
              // IAccessible.
        ...
    }
}