為提供者實作 IAccessibleEx
本節說明如何實 作 IAccessibleEx 介面,將 Microsoft 消費者介面自動化 提供者功能新增至 Microsoft Active Accessibility 伺服器。
實作 IAccessibleEx 之前,請考慮下列需求:
- 基準 Microsoft Active Accessibility 可存取物件階層必須乾淨。 IAccessibleEx 無法更正現有可存取物件階層的問題。 實作 IAccessibleEx 之前 ,必須在 Microsoft Active Accessibility 實作中更正物件模型結構任何問題。
- IAccessibleEx 實作必須符合 Microsoft Active Accessibility 規格和消費者介面自動化規格。 工具可在這兩個規格下驗證合規性。 如需詳細資訊,請參閱 測試協助工具和 消費者介面自動化驗證 (UIA 驗證) 測試自動化架構 。
實作 IAccessibleEx 需要下列主要步驟:
- 在可存取物件上實 作 IServiceProvider , 以便在此或個別物件上找到 IAccessibleEx 介面。
- 在可存取的物件上實 作 IAccessibleEx 。
- 為任何 Microsoft Active Accessibility 子專案建立可存取的物件,其中在 Microsoft Active Accessibility 中是由父物件上的 IAccessible 介面表示 (例如清單專案)。 在這些物件上實 作 IAccessibleEx 。
- 在所有可存取的物件上實 作 IRawElementProviderSimple 。
- 在可存取的物件上實作適當的控制項模式介面。
實作 IServiceProvider 介面
由於控制項的 IAccessibleEx 實作 可能位於不同的 物件中,用戶端應用程式無法依賴 QueryInterface 來取得這個介面。 相反地,用戶端應該呼叫 IServiceProvider::QueryService 。 在下列這個方法的範例實作中,假設 IAccessibleEx 未實作于個別物件上,因此方法只會呼叫 QueryInterface 。
HRESULT CListboxAccessibleObject::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
{
if (ppvObject == NULL)
{
return E_INVALIDARG;
}
*ppvObject = NULL;
if (guidService == __uuidof(IAccessibleEx))
{
return QueryInterface(riid, ppvObject);
}
else
{
return E_NOINTERFACE;
}
};
實作 IAccessibleEx 介面
在 Microsoft Active Accessibility 中,UI 元素一律由 IAccessible 介面和子識別碼識別。 IAccessible 的單 一實例可以代表多個 UI 元素。
因為每個 IAccessibleEx 實例只代表單一 UI 元素,因此每個 IAccessible 和子識別碼組都必須對應至單 一 IAccessibleEx 實例。 IAccessibleEx 包含兩種方法來處理此對應:
- GetObjectForChild — 擷取指定子系的 IAccessibleEx 介面。 如果 IAccessibleEx 實作無法辨識指定的子識別碼、沒有 指定子系的 IAccessibleEx 或表示子專案,這個方法會傳回 Null 。
- GetIAccessiblePair — 擷取 IAccessibleEx 元素的 IAccessible 介面和子識別碼。 針對 不使用子識別碼的 IAccessible 實作,此方法會擷取對應的 IAccessible 物件並CHILDID_SELF。
下列範例顯示 自訂清單檢視中專案的 GetObjectForChild 和 GetIAccessiblePair 方法實作。 方法可讓消費者介面自動化將 IAccessible 和子識別碼組對應至對應的 IAccessibleEx 實例。
HRESULT CListboxAccessibleObject::GetObjectForChild(
long idChild, IAccessibleEx **ppRetVal)
{
VARIANT vChild;
vChild.vt = VT_I4;
vChild.lVal = idChild;
HRESULT hr = ValidateChildId(vChild);
if (FAILED(hr))
{
return E_INVALIDARG;
}
// List item accessible objects are stored as an array of
// pointers; for the purpose of this example it is assumed that
// the list contents will not change. Accessible objects are
// created only when needed.
if (itemProviders[idChild - 1] == NULL)
{
// Create an object that supports UI Automation and
// IAccessibleEx for the item.
itemProviders[idChild - 1] =
new CListItemAccessibleObject(idChild,
g_pListboxControl);
if (itemProviders[idChild - 1] == NULL)
{
return E_OUTOFMEMORY;
}
}
IAccessibleEx* pAccEx = static_cast<IAccessibleEx*>
(itemProviders[idChild - 1]);
if (pAccEx != NULL)
{
pAccEx->AddRef();
}
*ppRetVal = pAccEx;
return S_OK;
}
HRESULT CListItemAccessibleObject::GetIAccessiblePair(
IAccessible **ppAcc, long *pidChild)
{
if (ppAcc == NULL || pidChild == NULL)
{
return E_INVALIDARG;
}
CListboxAccessibleObject* pParent =
m_control->GetAccessibleObject();
HRESULT hr = pParent->QueryInterface(
__uuidof(IAccessible), (void**)ppAcc);
if (FAILED(hr))
{
*pidChild = 0;
return E_NOINTERFACE;
}
*pidChild = m_childID;
return S_OK;
}
}
如果可存取的物件實作不使用子識別碼,仍然可以實作方法,如下列程式碼片段所示。
// This sample implements IAccessibleEx on the same object; it could use a tear-off
// or inner object instead.
class MyAccessibleImpl: public IAccessible,
public IAccessibleEx,
public IRawElementProviderSimple
{
public:
...
HRESULT STDMETHODCALLTYPE GetObjectForChild( long idChild, IAccessibleEx **ppRetVal )
{
// This implementation does not support child IDs.
*ppRetVal = NULL;
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetIAccessiblePair( IAccessible ** ppAcc, long * pidChild )
{
// This implementation assumes that IAccessibleEx is implemented on same object as
// IAccessible.
*ppAcc = static_cast<IAccessible *>(this);
(*ppAcc)->AddRef();
*pidChild = CHILDID_SELF;
return S_OK;
}
實作 IRawElementProviderSimple 介面
伺服器會使用 IRawElementProviderSimple 來公開消費者介面自動化屬性和控制模式的相關資訊。 IRawElementProviderSimple 包含下列方法:
- GetPatternProvider - 這個方法可用來公開控制項模式介面。 它會傳回支援指定控制項模式的物件,如果不支援控制項模式,則 傳回 Null 。
- GetPropertyValue — 這個方法可用來公開消費者介面自動化屬性值。
- HostRawElementProvider — 此方法不會與 IAccessibleEx 實作搭配 使用。
- ProviderOptions - 這個方法不會與 IAccessibleEx 實作搭配 使用。
IAccessibleEx 伺服器會藉由實 作 IRawElementProviderSimple::GetPatternProvider 來公開控制項模式。 這個方法會採用指定控制項模式的整數參數。 如果不支援模式,伺服器會 傳回 Null 。 如果支援控制項模式介面,伺服器會傳回 IUnknown ,用戶端接著呼叫 QueryInterface 以取得適當的控制項模式。
IAccessibleEx 伺服器可以藉由實 作 IRawElementProviderSimple::GetPropertyValue 並提供整數 PROPERTYID,以支援消費者介面自動化屬性(例如 LabeledBy 和 IsRequiredForForm)。 這項技術僅適用于未包含在控制項模式介面中的消費者介面自動化屬性。 與控制項模式介面相關聯的屬性會透過控制項模式介面方法公開。 例如,SelectionItem 控制項模式中的 IsSelected 屬性會以 ISelectionItemProvider::get_IsSelected 公開。