获取 Firefox / Thunderbird 窗口的 IAccessible2 接口 - QueryService 始终返回 E_INVALIDARG
我正在尝试使用 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(对于错误的接口 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。 Visual Studio 2005
我做错了什么吗?
I am trying out accessing the information in (Windows only) Firefox / Thunderbird using the IAccessible2 API: http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2
However I'm failing at almost the first step. I can obtain the IAccessible interface for either application, and then the IServiceProvider interface. But when I call QueryService to obtain the IAccessible2 interface, as described here: http://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/_generalinfo.html#_dicoveringInterfaces it always returns E_INVALIDARG.
AccProbe successfully returns IA2 information for both applications. The MS documentation for QueryService doesn't list E_INVALIDARG as a possible return value. However browsing for the mozilla source it appears that it returns this if the first parameter (service ID) is unexpected, and otherwise calls through to QueryInterface (which would return E_NOINTERFACE for a bad interface ID). So... that implies the first parameter to QueryService is wrong; but I've tried pretty much every value I think mozilla expects with no difference.
I started off in c# and then tried again in c++ in case I was losing something in InterOp. Same result in both languages. Here's my current c++ test code:
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();
}
This is all on Win7 - both 32-bit and 64-bit used. Firefox 3.6.24 and Thunderbird 8.0. Visual Studio 2005
Am I doing something wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为问题就在这里 - 将 OBJID_WINDOW 替换为 OBJID_CLIENT,并且它似乎有效。 (我没有注册 typelib,但我可以 QS IID_IAccessible 和 IUnknown 接口,而且它似乎可以工作。另外,请确保也使用 CoInitialize()。)
IAccessible 有一个有趣的层次结构:每个 HWND 都有一个 '窗口”部分和“客户端”部分。这部分是由于 Win32 内部的工作方式所致; Win32 HWND 可以包含标题栏、菜单、滚动条等项目,它们都共享相同的 HWND - 以及实际控制内容所在的内容区域(也称为客户区域)。为了让这些项目有自己的表示形式,MSAA 的设计者选择了一个两级结构,其中 OBJID_WINDOW 表示整个窗口,它的子级表示滚动条、菜单栏、标题栏等内容 - 如果它们是展示。
然而,窗口中实现可访问性的部分通常是客户端部分,因此您通常需要请求 OBJID_CLIENT 来获取“真正的”IAccessible。
I think the problem is here - replace OBJID_WINDOW with OBJID_CLIENT, and it seems to work. (I don't have the typelib registered, but I can QS for IID_IAccessible and the IUnknown interface, and it seems to work. Also, be sure to CoInitialize() also.)
IAccessible has an interesting hierarchy: every HWND has both a 'window' part and a 'client' part. This is partially due to how Win32 works internally; a Win32 HWND can have items like titlebar, menu, scrollbars, and so on, that all share the same HWND - along with the content area aka client area where the actual control content lives. To allow these items to have their own representation, the designers of MSAA picked a two-level structure, where OBJID_WINDOW represents the entire window, and it has children that then represent things like scrollbars, menubar, titlebar, and so on - if they are present.
The part of a window that implements the accessiblity, however, is generally the client part, so you usually need to ask for OBJID_CLIENT to get the 'real' IAccessible.