Uso di IAccessibleEx da un client

Questo argomento illustra come i client accedono all'implementazione IAccessibleEx di un server e lo usano per ottenere Automazione interfaccia utente proprietà e pattern di controllo per gli elementi dell'interfaccia utente.

Le procedure e gli esempi in questa sezione presuppongono un client IAccessible già in-process e un server Microsoft Active Accessibility esistente. Si presuppone inoltre che il client abbia già ottenuto un oggetto IAccessible usando una delle funzioni del framework di accessibilità, ad esempio AccessibleObjectFromEvent, AccessibleObjectFromPoint o AccessibleObjectFromWindow.

Recupero di un'interfaccia IAccessibleEx dall'interfaccia IAccessible

Un client che dispone di un'interfaccia IAccessible per un oggetto accessibile può usarlo per ottenere l'interfaccia IAccessibleEx corrispondente seguendo questa procedura:

Gestione dell'ID figlio

I client devono essere preparati per i server con un ID figlio diverso da CHILDID_SELF. Dopo aver ottenuto un'interfaccia IAccessibleEx da un oggetto IAccessible, i client devono chiamare IAccessibleEx::GetObjectForChild se l'ID figlio non è CHILDID_SELF (che indica un oggetto padre).

Nell'esempio seguente viene illustrato come ottenere un oggetto IAccessibleEx per un particolare oggetto IAccessible e un ID figlio.

   
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;
    }
}

Recupero dell'interfaccia IRawElementProviderSimple

Se un client ha un'interfaccia IAccessibleEx , può usare QueryInterface per accedere all'interfaccia IRawElementProviderSimple , come illustrato nell'esempio seguente.

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;
}

Recupero dei pattern di controllo

Se un client ha accesso all'interfaccia IRawElementProviderSimple , può recuperare le interfacce del pattern di controllo implementate dai provider e quindi chiamare metodi su tali interfacce. L'esempio seguente illustra come farlo.

// 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;
}

Recupero dei valori delle proprietà

Se un client ha accesso a IRawElementProviderSimple, può recuperare i valori delle proprietà. Nell'esempio seguente viene illustrato come ottenere valori per le proprietà AutomationId e LabeledBy Microsoft Automazione interfaccia utente.

#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'esempio precedente si applica alle proprietà non associate a un pattern di controllo. Per accedere alle proprietà del pattern di controllo, un client deve ottenere e usare un'interfaccia del pattern di controllo.

Recupero di un'interfaccia IAccessible da un'interfaccia IRawElementProviderSimple

Se un client ottiene l'interfaccia IRawElementProviderSimple per un elemento dell'interfaccia utente, il client può usare tale interfaccia per ottenere un'interfaccia IAccessible corrispondente per l'elemento. Ciò è utile se il client deve accedere alle proprietà microsoft Active Accessibility per l'elemento .

Un client può ottenere l'interfaccia IRawElementProviderSimple come valore della proprietà (ad esempio, chiamando IRawElementProviderSimple::GetPropertyValue con UIA_LabeledByPropertyId) o come elemento recuperato da un metodo (ad esempio, chiamando ISelectionProvider::GetSelection per recuperare una matrice di interfacce IRawElementProviderSimple degli elementi selezionati). Dopo aver ottenuto l'interfaccia IRawElementProviderSimple , un client può usarlo per ottenere un oggetto IAccessible corrispondente seguendo questa procedura:

Il frammento di codice seguente illustra come ottenere l'interfaccia IAccessible da un'interfaccia IRawElementProviderSimple ottenuta in precedenza.

// 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.
        ...
    }
}