获取Firefox / Thunderbird窗口的IAccessible2接口 - QueryService始终返回E_INVALIDARG

时间:2011-12-11 12:50:50

标签: firefox accessibility thunderbird iaccessible

我正在尝试使用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#_dicoveringInterfaces它总是返回E_INVALIDARG。

AccProbe成功返回两个应用程序的IA2信息。 QueryService的MS文档未将E_INVALIDARG列为可能的返回值。但是,浏览mozilla源时,如果第一个参数(服务ID)是意外的,它会返回此值,否则会调用QueryInterface(这将返回E_NOINTERFACE以获取错误的接口ID)。所以...这意味着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位。 Firefox 3.6.24和Thunderbird 8.0。 Visual Studio 2005

我做错了吗?

1 个答案:

答案 0 :(得分:1)

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

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

IAccessible有一个有趣的层次结构:每个HWND都有一个“窗口”部分和一个“客户端”部分。这部分是由于Win32如何在内部工作; Win32 HWND可以包含标题栏,菜单,滚动条等项目,它们共享相同的HWND - 以及实际控制内容所在的内容区域(客户区域)。为了允许这些项目有自己的表示,MSAA的设计者选择了一个两级结构,其中OBJID_WINDOW代表整个窗口,它有子项,然后代表滚动条,菜单栏,标题栏等等 - 如果它们是本。

然而,实现accessiblity的窗口部分通常是客户端部分,因此您通常需要请求OBJID_CLIENT来获取“真正的”IAccessible。