Verwenden von IAccessibleEx über einen Client

In diesem Thema wird erläutert, wie Clients auf die IAccessibleEx-Implementierung eines Servers zugreifen und diese verwenden, um Benutzeroberflächenautomatisierung Eigenschaften und Steuerelementmuster für Benutzeroberflächenelemente zu erhalten.

Bei den Prozeduren und Beispielen in diesem Abschnitt wird davon ausgegangen, dass ein bereits ausgeführter IAccessible-Client und ein vorhandener Microsoft Active Accessibility sind. Außerdem wird davon ausgegangen, dass der Client bereits ein IAccessible-Objekt mithilfe einer der Frameworkfunktionen für die Barrierefreiheit wie AccessibleObjectFromEvent, AccessibleObjectFromPointoder AccessibleObjectFromWindow erhalten hat.

Abrufen einer IAccessibleEx-Schnittstelle von der IAccessible-Schnittstelle

Ein Client, der über eine IAccessible-Schnittstelle für ein barrierefreies Objekt verfügt, kann es verwenden, um die entsprechende IAccessibleEx-Schnittstelle mithilfe der folgenden Schritte zu erhalten:

Behandeln der untergeordneten ID

Clients müssen für Server mit einer anderen untergeordneten ID als CHILDID SELF vorbereitet _ werden. Nach dem Abrufen einer IAccessibleEx-Schnittstelle von einem IAccessible-Objektmüssen Clients IAccessibleEx::GetObjectForChild aufrufen, wenn die untergeordnete ID nicht CHILDID SELF ist (was ein übergeordnetes Objekt _ angibt).

Das folgende Beispiel zeigt, wie IAccessibleEx für ein bestimmtes IAccessible-Objekt und eine untergeordnete ID erhalten wird.

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

Abrufen der IRawElementProviderSimple-Schnittstelle

Wenn ein Client über eine IAccessibleEx-Schnittstelle verfügt, kann er QueryInterface verwenden, um zur IRawElementProviderSimple-Schnittstelle zu kommen, wie im folgenden Beispiel gezeigt.

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

Abrufen von Steuerelementmustern

Wenn ein Client Zugriff auf die IRawElementProviderSimple-Schnittstelle hat, kann er Steuerelementmusterschnittstellen abrufen, die von Anbietern implementiert wurden, und dann Methoden für diese Schnittstellen aufrufen. Das folgende Beispiel zeigt die erforderliche Vorgehensweise.

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

Abrufen von Eigenschaftswerten

Wenn ein Client Zugriff auf IRawElementProviderSimplehat, kann er Eigenschaftswerte abrufen. Das folgende Beispiel zeigt, wie Werte für die Eigenschaften AutomationId und LabeledBy Microsoft Benutzeroberflächenautomatisierung werden.

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

Das vorherige Beispiel gilt für Eigenschaften, die nicht einem Steuerelementmuster zugeordnet sind. Für den Zugriff auf Steuerelementmustereigenschaften muss ein Client eine Steuerelementmusterschnittstelle abrufen und verwenden.

Abrufen einer IAccessible-Schnittstelle von einer IRawElementProviderSimple-Schnittstelle

Wenn ein Client die IRawElementProviderSimple-Schnittstelle für ein Benutzeroberflächenelement erhält, kann der Client diese Schnittstelle verwenden, um eine entsprechende IAccessible-Schnittstelle für das Element zu erhalten. Dies ist nützlich, wenn der Client auf die eigenschaften Microsoft Active Accessibility für das Element zugreifen muss.

Ein Client kann die IRawElementProviderSimple-Schnittstelle als Eigenschaftswert abrufen (z. B. durch Aufrufen von IRawElementProviderSimple::GetPropertyValue mit UIA LabeledByPropertyId) oder als Element, das von einer Methode abgerufen wird (z. B. durch Aufrufen von _ ISelectionProvider::GetSelection, um ein Array von IRawElementProviderSimple-Schnittstellen ausgewählter Elemente abzurufen). Nach dem Abrufen der IRawElementProviderSimple-Schnittstelle kann ein Client sie verwenden, um eine entsprechende IAccessible-Schnittstelle zu erhalten, indem sie die folgenden Schritte ausführen:

Der folgende Codeausschnitt veranschaulicht, wie sie die IAccessible-Schnittstelle von einer zuvor erhaltenen IRawElementProviderSimple-Schnittstelle abrufen.

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