使用 MSAA 使无窗口 ActiveX 控件易于访问

介绍如何使用 Microsoft Active Accessibility API 确保辅助技术 (AT) 客户端应用程序可以访问无窗口 Microsoft ActiveX 控件。

需要了解的事项

技术

先决条件

  • C/C++
  • Microsoft Win32 和组件对象模型 (COM) 编程
  • 无窗口 ActiveX 控件
  • Microsoft Active Accessibility 服务器

Instructions

步骤 1:实现 IAccessible 接口。

若要使无窗口 ActiveX 控件易于访问,必须实现 Microsoft Active Accessibility IAccessible 接口,就像实现基于窗口的控件一样,但以下步骤中所述。 有关实现 IAccessible 的详细信息,请参阅 Active Accessibility Servers 开发人员指南

步骤 2:实现 IServiceProvider 接口。

当客户端请求有关无窗口控件的辅助功能信息时,容器会调用控件的 IServiceProvider::QueryService 方法来检索 IAccessible 接口指针。

此示例演示如何实现 QueryService 方法。

STDMETHODIMP CMyAccessibleMSAAControl::QueryService(REFGUID guidService, 
        REFIID riid, void **ppvObject)
{      
    if (ppvObject == NULL)
    {
        return E_INVALIDARG;
    }

    *ppvObject = NULL;  
    HRESULT hr = E_FAIL;  

    if (guidService == __uuidof(IAccessible))
    {  
        hr = QueryInterface(riid, ppvObject);  
    }  
    return hr;  
}

步骤 3:将 IAccessible::get_accParent 方法调用委托给控件网站的 IAccessibleWindowlessSite::GetParentAccessible 方法。

当客户端请求无窗口控件的父对象时,容器会调用控件的 IAccessible::get_accParent 方法。 get_accParent实现应委托给容器的 IAccessibleWindowlessSite::GetParentAccessible 方法。

此示例演示如何实现 get_accParent 方法。

HRESULT CMyAccessibleMSAAControl::get_accParent(IDispatch **ppdispParent)  
{  
    if (ppdispParent == NULL)
    {
        return E_INVALIDARG;
    }

    HRESULT hr = S_FALSE;  
    *ppdispParent = NULL;  

    IAccessibleWindowlessSite *pWindowlessSite = NULL;  

    if (SUCCEEDED(m_pClientSite->QueryInterface(IID_PPV_ARGS(&pWindowlessSite))))  
    {  
        IAccessible *pParentAcc = NULL;
        if (SUCCEEDED(pWindowlessSite->GetParentAccessible(&pParentAcc)))
        {
            hr = pParentAcc->QueryInterface(IID_PPV_ARGS(ppdispParent));  
        }
    }  

    SafeRelease(&pWindowlessSite);
    return hr;  
}

步骤 4:获取要分配给无窗口控件中的事件源的对象 ID 的范围。

与基于窗口的控件一样,无窗口 ActiveX 控件调用 NotifyWinEvent 函数来通知客户端重要事件。 函数参数包括引发事件的项的对象 ID。 无窗口控件必须使用通过调用控件站点的 IAccessibleWindowlessSite::AcquireObjectIdRange 方法获取的范围中的值来分配对象 ID。

此示例演示如何从控制容器获取一系列对象 ID 值。

IAccessibleWindowlessSite *pWindowlessSite = NULL;

if (SUCCEEDED(m_pClientSite->QueryInterface(
        IID_PPV_ARGS(&pWindowlessSite))))  
{  
    if (FAILED(pWindowlessSite->AcquireObjectIdRange(100, this, 
            &m_idObjectBase)))  
    {  
        m_idObjectBase = -1;  
    } 
}

SafeRelease(&pWindowlessSite);

步骤 5:实现 IAccessibleHandler 接口。

当无窗口控件调用 NotifyWinEvent 函数时,控件指定引发事件的 UI 项的对象 ID,并将控件容器指定为代表控件响应 WM_GETOBJECT 消息的窗口。

如果客户端应用程序响应事件,则控件容器会收到 一条WM_GETOBJECT 消息,其中包含引发该事件的 UI 项的对象 ID。 控件容器通过查找“拥有”对象 ID 的无窗口控件,然后调用该控件的 IAccessibleHandler::AccessibleObjectFromID 方法进行响应。 AccessibleObjectFromID 方法返回 UI 项的 IAccessible 接口指针,控件容器将指针转发到客户端应用程序。

使用 UI 自动化 使无窗口 ActiveX 控件易于访问

无窗口 ActiveX 控件辅助功能