Menggunakan IAccessibleEx dari Klien

Topik ini menjelaskan bagaimana klien mengakses implementasi IAccessibleEx server dan menggunakannya untuk mendapatkan properti Automation UI dan pola kontrol untuk elemen UI.

Prosedur dan contoh di bagian ini mengasumsikan klienIAccessible yang sudah dalam proses, dan server Aksesibilitas Aktif Microsoft yang ada. Mereka juga berasumsi bahwa klien telah mendapatkan objek IAccessible dengan menggunakan salah satu fungsi kerangka kerja aksesibilitas seperti AccessibleObjectFromEvent, AccessibleObjectFromPoint, atau AccessibleObjectFromWindow.

Mendapatkan Antarmuka IAccessibleEx dari Antarmuka IAccessible

Klien yang memiliki antarmuka IAccessible untuk objek aksesibel dapat menggunakannya untuk mendapatkan antarmuka IAccessibleEx yang sesuai dengan mengikuti langkah-langkah berikut:

Menangani ID Anak

Pengguna harus siap untuk server dengan ID anak selain CHILDID_SELF. Setelah memperoleh antarmuka IAccessibleEx dari IAccessible, klien harus memanggil IAccessibleEx::GetObjectForChild jika ID anak tidak sama dengan CHILDID_SELF (yang menunjukkan objek induk).

Contoh berikut menunjukkan cara mendapatkan IAccessibleEx untuk objek IAccessible dan ID anak tertentu.

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

Mendapatkan Antarmuka IRawElementProviderSimple

Jika klien memiliki antarmukaIAccessibleEx, klien dapat menggunakan QueryInterface untuk masuk ke antarmukaIRawElementProviderSimple, seperti yang ditunjukkan contoh berikut.

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

Mengambil Pola Kontrol

Jika klien memiliki akses ke antarmukaIRawElementProviderSimple, klien dapat mengambil antarmuka pola kontrol yang telah diimplementasikan oleh penyedia, dan kemudian dapat memanggil metode pada antarmuka tersebut. Contoh berikut menunjukkan cara melakukan ini.

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

Mengambil Nilai Properti

Jika klien memiliki akses ke IRawElementProviderSimple, klien dapat mengambil nilai properti. Contoh berikut menunjukkan cara mendapatkan nilai untuk properti AutomationId dan 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);
}

Contoh sebelumnya berlaku untuk properti yang tidak terkait dengan pola kontrol. Untuk mengakses properti pola kontrol, klien harus mendapatkan dan menggunakan antarmuka pola kontrol.

Mengambil Antarmuka IAccessible dari Antarmuka IRawElementProviderSimple

Jika klien mendapatkan antarmukaIRawElementProviderSimpleuntuk elemen UI, klien dapat menggunakan antarmuka tersebut untuk mendapatkan antarmuka IAccessible yang sesuai untuk elemen tersebut. Ini berguna jika klien perlu mengakses properti Aksesibilitas Aktif Microsoft untuk elemen tersebut.

Klien dapat memperoleh IRawElementProviderSimple antarmuka sebagai nilai properti (misalnya, dengan memanggil IRawElementProviderSimple::GetPropertyValue dengan UIA_LabeledByPropertyId), atau sebagai item yang diambil oleh metode (misalnya, dengan memanggil ISelectionProvider::GetSelection untuk mengambil array antarmuka IRawElementProviderSimple dari elemen yang dipilih). Setelah mendapatkan antarmuka IRawElementProviderSimple, klien dapat menggunakannya untuk mendapatkan IAccessibleyang sesuai dengan mengikuti langkah-langkah berikut:

Cuplikan kode berikut menunjukkan cara mendapatkan antarmuka IAccessible dari antarmuka IRawElementProviderSimple yang sudah diperoleh sebelumnya.

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