Получение интерфейса IAccessible2 для окна Firefox / Thunderbird - QueryService всегда возвращает E_INVALIDARG - PullRequest
1 голос
/ 11 декабря 2011

Я пытаюсь получить доступ к информации (только для 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#_dicoveringInterfaces, он всегда возвращает 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 Ответ

1 голос
/ 13 декабря 2011
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.

...