共用方式為


將 使用者介面自動化 功能新增至使用中輔助功能伺服器

沒有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 新增控件特定屬性的支援。

更新自訂控制項需要下列主要步驟:

本主題包含下列各節。

公開 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 將 使用者介面自動化 支援新增至自定義控件

使用者介面自動化 提供者程序設計人員指南