Получение интерфейса IAccessible2 для окна Firefox / Thunderbird - QueryService всегда возвращает E_INVALIDARG
Я пытаюсь получить доступ к информации в (только Windows) Firefox / Thunderbird с помощью API IAccessible2: http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2 Однако я провалюсь почти на первом этапе. Я могу получить интерфейс IAccessible для любого приложения, а затем интерфейс IServiceProvider. Но когда я вызываю QueryService для получения интерфейса IAccessible2, как описано здесь: http://accessibility.linuxfoundation.org/a11yspecs/ia2/docs/html/_generalinfo.html, он всегда возвращает E_INVALIDARG.
AccProbe успешно возвращает информацию IA2 для обоих приложений. Документация MS для QueryService не перечисляет E_INVALIDARG в качестве возможного возвращаемого значения. Однако, просматривая источник Mozilla, кажется, что он возвращает это, если первый параметр (идентификатор службы) является неожиданным, и в противном случае вызывает QueryInterface (который возвращает 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-битные. Firefox 3.6.24 и Thunderbird 8.0. Visual Studio 2005
Я делаю что-то неправильно?
1 ответ
HRESULT hr = AccessibleObjectFromWindow(hw, OBJID_WINDOW, IID_IAccessible, (void**)&pIA);
if (!SUCCEEDED(hr))
return -1;
Я думаю, что проблема здесь - замените OBJID_WINDOW на OBJID_CLIENT, и это, кажется, работает. (У меня нет зарегистрированной typelib, но я могу QS для IID_IAccessible и интерфейса IUnknown, и, похоже, он работает. Также обязательно CoInitialize() также.)
У IAccessible есть интересная иерархия: каждый HWND имеет как часть "окна", так и часть "клиент". Это частично связано с тем, как Win32 работает внутри; Win32 HWND может иметь такие элементы, как заголовок заголовка, меню, полосы прокрутки и т. д., которые совместно используют один и тот же HWND - наряду с областью содержимого, называемой клиентской областью, где живет фактический управляющий контент. Чтобы эти элементы имели свое собственное представление, разработчики MSAA выбрали двухуровневую структуру, где OBJID_WINDOW представляет все окно, и у него есть дочерние элементы, которые затем представляют такие вещи, как полосы прокрутки, меню, заголовок и т. Д., Если они подарок.
Часть окна, которая реализует доступность, как правило, является клиентской частью, поэтому вам обычно нужно запросить OBJID_CLIENT, чтобы получить "реальный" IAccessible.