本主題說明用戶端如何存取伺服器 IAccessibleEx 實作,並用它來取得UI元素的UI自動化屬性和控制模式。
本節中的程式和範例假設已進行中的 IAccessible 用戶端,以及現有的 Microsoft Active Accessibility 伺服器。 他們也會假設客戶端已經使用下列其中一個輔助功能架構函式取得 IAccessible 物件,例如 AccessibleObjectFromEvent、AccessibleObjectFromPoint或 AccessibleObjectFromWindow。
從 IAccessible 介面取得 IAccessibleEx 介面
具有可存取物件的 IAccessible 介面的用戶端,可以依照下列步驟取得對應的 IAccessibleEx 介面:
- 在原始 IAccessible 物件上呼叫 QueryInterface,並搭配__uuidof(IServiceProvider) 的 IID。
- 呼叫 IServiceProvider::QueryService,以取得 IAccessibleEx。
處理兒童身份識別
客戶端必須針對具有CHILDID_SELF以外的子標識碼的伺服器做好準備。 從 IAccessible取得 IAccessibleEx 介面之後,如果子標識符不是CHILDID_SELF(表示父物件),客戶端必須呼叫 IAccessibleEx::GetObjectForChild。
以下範例示範如何為特定的 IAccessible 物件及其子標識碼取得 IAccessibleEx。
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;
}
}
取得 IRawElementProviderSimple 介面
如果用戶端具有 IAccessibleEx 介面,則可以使用 QueryInterface 來取得 IRawElementProviderSimple 介面,如下列範例所示。
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;
}
控制模式擷取
如果用戶端可以存取 IRawElementProviderSimple 介面,它可以擷取提供者已實作的控制模式介面,然後可以在這些介面上呼叫方法。 下列範例示範如何執行這項作。
// 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;
}
擷取屬性值
如果用戶端可以存取 IRawElementProviderSimple,它可以擷取屬性值。 以下例子展示如何取得 Microsoft UI 自動化屬性的 AutomationId 和 LabeledBy 的值。
#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);
}
上述範例適用於與控件模式無關的屬性。 若要存取控制模式屬性,客戶端必須取得並使用控制項模式介面。
從 IRawElementProviderSimple 介面中取得 IAccessible 介面
如果用戶端取得 UI 元件的 IRawElementProviderSimple 介面,用戶端可以使用該介面來取得該元件的對應 IAccessible 介面。 如果用戶端需要存取專案的 Microsoft Active Accessibility 屬性,這會很有用。
用戶端可以取得 IRawElementProviderSimple 介面作為屬性值(例如, 藉由呼叫 IRawElementProviderSimple::GetPropertyValue 搭配 UIA_LabeledByPropertyId),或做為方法所擷取的專案(例如,藉由呼叫 ISelectionProvider::GetSelection 來擷取 IRawElementProviderSimple 介面選取的專案)。 取得 IRawElementProviderSimple 介面之後,用戶端可以依照下列步驟取得對應的 IAccessible:
- 嘗試使用 QueryInterface 來取得 IAccessibleEx 介面。
- 如果 QueryInterface 失敗,請在原本取得屬性的 IAccessibleEx 實例上呼叫 IAccessibleEx::ConvertReturnedElement。
- 在新的 IAccessibleEx 實例上呼叫 GetIAccessiblePair 方法,來獲得 IAccessible 介面和子標識符。
以下程式碼片段示範如何從先前獲得的 IRawElementProviderSimple 介面獲取 IAccessible 介面。
// 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.
...
}
}