2

我正在尝试使用 IAccessible2 API 访问(仅限 Windows)Firefox / Thunderbird 中的信息:http ://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2 但是我几乎在第一步都失败了。我可以获取任一应用程序的 IAccessible 接口,然后是 IServiceProvider 接口。但是当我调用 QueryService 来获取 IAccessible2 接口时,如下所述:http ://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/_generalinfo.html#_dioveringInterfaces它总是返回 E_INVALIDARG。

AccProbe 成功返回两个应用程序的 IA2 信息。QueryService 的 MS 文档没有将 E_INVALIDARG 列为可能的返回值。但是,浏览 mozilla 源代码时,如果第一个参数(服务 ID)出乎意料,它会返回此值,否则会调用 QueryInterface(对于错误的接口 ID,它将返回 E_NOINTERFACE)。所以...这意味着 QueryService 的第一个参数是错误的;但我已经尝试了几乎所有我认为 mozilla 期望的值,没有任何区别。

我从 c# 开始,然后在 c++ 中再次尝试,以防在 InterOp 中丢失某些东西。两种语言的结果相同。这是我当前的 C++ 测试代码:

    HWND hw = GetForegroundWindow();
    IAccessible *pIA;
    HRESULT hr = AccessibleObjectFromWindow(hw, OBJID_WINDOW, IID_IAccessible, (void**)&pIA);
    if (!SUCCEEDED(hr))
        return -1;

    // SNIP - calls pIA->get_accName to check correct window is being accessed.  This works OK.

    const IID IID_IAccessible2 = {0xE89F726E, 0xC4F4, 0x4c19, 0xbb, 0x19, 0xb6, 0x47, 0xd7, 0xfa, 0x84, 0x78};
    ::IServiceProvider *pService = NULL; 
    hr = pIA->QueryInterface(IID_IServiceProvider, (void **)&pService); 
    if(SUCCEEDED(hr))
    {
        IAccessible2 *pIA2 = NULL; 
        hr = pService->QueryService(IID_IAccessible2, IID_IAccessible2, (void**)&pIA2); 
        if (SUCCEEDED(hr) && pIA2)
        { 
          // Always fails with E_INVALIDARG
            pIA2->Release();
        } 
        pService->Release();
    } 

这都是在 Win7 上 - 使用 32 位和 64 位。火狐 3.6.24 和雷鸟 8.0。视觉工作室 2005

难道我做错了什么?

4

1 回答 1

2
HRESULT hr = AccessibleObjectFromWindow(hw, OBJID_WINDOW, IID_IAccessible, (void**)&pIA);
if (!SUCCEEDED(hr))
    return -1;

我认为问题出在这里 - 用 OBJID_CLIENT 替换 OBJID_WINDOW,它似乎工作。(我没有注册类型库,但我可以对 IID_IAccessible 和 IUnknown 接口进行 QS,而且它似乎可以工作。另外,一定要 CoInitialize() 也。)

IAccessible 有一个有趣的层次结构:每个 HWND 都有一个“窗口”部分和一个“客户端”部分。这部分是由于 Win32 内部的工作方式。Win32 HWND 可以具有标题栏、菜单、滚动条等项目,它们都共享相同的 HWND - 以及实际控制内容所在的内容区域(即客户区域)。为了让这些项目有自己的表现形式,MSAA 的设计者选择了一个两级结构,其中 OBJID_WINDOW 代表整个窗口,并且它有子级代表滚动条、菜单栏、标题栏等等——如果它们是当下。

然而,实现可访问性的窗口部分通常是客户端部分,因此您通常需要请求 OBJID_CLIENT 才能获得“真正的”IAccessible。

于 2011-12-13T11:06:43.997 回答