將 使用者介面自動化 功能新增至使用中輔助功能伺服器
沒有Microsoft 使用者介面自動化 提供者,但實作 IAccessible 的控件可以藉由實作 IAccessibleEx 介面,輕鬆地升級以提供一些 使用者介面自動化 功能。 這個介面可讓控件公開 使用者介面自動化 屬性和控件模式,而不需要完整實作 使用者介面自動化 提供者介面,例如 IRawElementProviderFragment。 若要實作 IAccessibleEx,基準Microsoft Active Accessibility 物件階層不得包含任何錯誤或不一致(例如父物件未將它列為子系的子物件),且不得與 使用者介面自動化 規格衝突。 如果Microsoft Active Accessibility 物件階層符合這些需求,則使用 IAccessibleEx 新增功能是很好的候選專案;否則,您必須單獨實作 使用者介面自動化,或與 Microsoft Active Accessibility 實作一起實作。
採用具有範圍值的自定義控件案例。 控件的 Microsoft Active Accessibility 伺服器會定義其角色,而且能夠傳回其目前值,但缺少傳回控件最小值和最大值的方法,因為這些屬性未定義於 Microsoft Active Accessibility 中。 使用者介面自動化 客戶端能夠擷取控件的角色、目前值和其他Microsoft Active Accessibility 屬性,因為 使用者介面自動化 核心可以透過 IAccessible 取得這些屬性。 不過,若無法存取 物件上的IRangeValueProvider 介面,使用者介面自動化 也無法擷取最大值和最小值。
控件開發人員可以提供控件的完整 使用者介面自動化 提供者,但這表示複製 IAccessible 實作的大部分現有功能:例如流覽和通用屬性。 相反地,開發人員可以繼續依賴 IAccessible 提供這項功能,同時透過 IRangeValueProvider 新增控件特定屬性的支援。
更新自訂控制項需要下列主要步驟:
- 在可存取對象上實作 IServiceProvider,以便在此或個別物件上找到 IAccessibleEx 介面。
- 在可存取的對象上實作 IAccessibleEx。
- 為任何Microsoft Active Accessibility 子專案建立不同的可存取物件,其中Microsoft Active Accessibility 可能已由 父物件上的 IAccessible 介面表示(例如列表專案)。 在這些對象上實作 IAccessibleEx。
- 在所有可存取的對象上實作 IRawElementProviderSimple。
- 在可存取的對象上實作適當的控制項模式介面。
本主題包含下列各節。
公開 IAccessibleEx
由於控件的 IAccessibleEx 實作可能位於不同的 物件中,用戶端應用程式無法依賴 QueryInterface 來取得這個介面。 相反地,客戶端應該呼叫 IServiceProvider::QueryService。 在下列這個方法的範例實作中,假設 IAccessibleEx 未實作於個別物件上,因此方法只會呼叫 QueryInterface。
HRESULT CListboxAccessibleObject::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
{
if (!ppvObject)
{
return E_INVALIDARG;
}
*ppvObject = NULL;
if (guidService == __uuidof(IAccessibleEx))
{
return QueryInterface(riid, ppvObject);
}
else
{
return E_INVALIDARG;
}
};
實作 IAccessibleEx
最感興趣的 IAccessibleEx 方法是 GetObjectForChild。 這個方法可讓Microsoft Active Accessibility 伺服器有機會為子專案建立可存取的物件(至少 公開 IAccessibleEx)。 在 Microsoft Active Accessibility 中,子專案通常不會表示為可存取的物件,而是表示為可存取物件的子系。 不過,由於 使用者介面自動化 要求每個元素都以個別的可存取物件表示,GetObjectForChild 必須依需求為每個子系建立個別的物件。
下列範例實作會傳回自定義清單檢視中專案的可存取物件。
HRESULT CListboxAccessibleObject::GetObjectForChild(long idChild, IAccessibleEx **pRetVal)
{
*pRetVal = NULL;
VARIANT vChild;
vChild.vt = VT_I4;
vChild.lVal = idChild;
// ValidateChildId is an application-defined function that checks whether
// the child ID is valid. This is similar to code that validates the varChild
// parameter in IAccessible methods.
//
// Additionally, if this idChild corresponds to a child that has its own
// IAccessible, we should also return E_INVALIDARG here. (The caller
// should instead be using the IAccessibleEx from that child's own
// IAccessible in that case.)
if (idChild == CHILDID_SELF || FAILED(ValidateChildId(vChild)))
{
return E_INVALIDARG;
}
// Return a suitable provider for this specific child.
// This implementation returns a new instance each time; an implementation
// can cache these if desired.
// _pListboxControl is a member variable pointer to the owning control.
IAccessibleEx* pAccEx = new CListItemAccessibleObject(idChild, _pListboxControl);
if (pAccEx == NULL)
{
return E_OUTOFMEMORY;
}
*pRetVal = pAccEx;
return S_OK;
}
如需完整的範例實作,請參閱讓自定義控件可供存取,第 5 部分:使用 IAccessibleEx 將 使用者介面自動化 支援新增至自定義控件。
相關主題