Использование IAccessible с Google Chrome возвращает неполное дерево

Я пытаюсь создать автоматизацию контроля качества для Google Chrome, чтобы имитировать клики и получать события кликов на кнопках вкладок.

Я использую IAccessible интерфейс а также AccessibleChildren API получить полное доступное дерево элементов.

При использовании AccExplorer 2.0 для просмотра дерева — оно выглядит великолепно (см. Изображение в конце).

Но моя программа показывает только частичное дерево, и имена не совпадают с теми, что я вижу в AccExplorer.

Я бегу:

  • Chrome 37 beta
  • Win 7 64 бит

Есть идеи, почему я не могу просмотреть полное дерево?

Спасибо

Это источник моей программы (C ++): (аналогично примеру MSDN)

int _tmain(int argc, _TCHAR* argv[])
{
int i=0;
HWND hWndChrome = NULL;
hWndChrome = (HWND)0x000702c0;
wcout << L"\n\nChrome_WidgetWin_1 = "<< hex << hWndChrome << "\n--------------------------";

CComPtr<IAccessible> pAccMain;
::AccessibleObjectFromWindow(hWndChrome, OBJID_CLIENT, IID_IAccessible, (void**)(&pAccMain));

WalkTreeWithAccessibleChildren(pAccMain, 0);
_getch();

return 0;
}

HRESULT WalkTreeWithAccessibleChildren(__in CComPtr<IAccessible> pAcc, __in int depth)
{
long childCount = 0;
long returnCount = 0;

HRESULT hr = pAcc->get_accChildCount(&childCount);

if (childCount == 0)
return S_FALSE;

CComVariant* pArray = new CComVariant[childCount];
hr = ::AccessibleChildren(pAcc, 0L, childCount, pArray, &returnCount);
if (FAILED(hr))
return hr;

// Iterate through children.
for (int x = 0; x < returnCount; x++)
{
CComVariant vtChild = pArray[x];
// If it's an accessible object, get the IAccessible, and recurse.
if (vtChild.vt == VT_DISPATCH)
{
CComPtr<IDispatch> pDisp = vtChild.pdispVal;
CComQIPtr<IAccessible> pAccChild = pDisp;
if (!pAccChild)
continue;

// Print current accessible element
wcout << endl;
for (int y = 0; y < depth; y++) wcout << L"    ";
wcout << L"* " << GetName(pAccChild, CHILDID_SELF).data() << L"  |  " << GetRole(pAccChild, CHILDID_SELF).data() << L" (Object)";

WalkTreeWithAccessibleChildren(pAccChild, depth + 1);
}
// Else it's a child element so we have to call accNavigate on the parent,
//   and we do not recurse because child elements can't have children.
else
{
// Print current accessible element
wcout << endl;
for (int y = 0; y < depth; y++) wcout << L"    ";
wcout << L"* " << GetName(pAcc, vtChild.lVal).data() << L"  |  " << GetRole(pAcc, vtChild.lVal).data() << " (Child)";
}
}
delete[] pArray;
return S_OK;
}

wstring GetName(__in CComPtr<IAccessible> pAcc, __in CComVariant varChild)
{
if (!pAcc)
return L"";
CComBSTR bstrName;
HRESULT hr = pAcc->get_accName(varChild, &bstrName);
if (FAILED(hr))
return L"";
if (!bstrName.m_str)
return L"<NULL>";
return bstrName.m_str;
}

wstring GetRole(__in CComPtr<IAccessible> pAcc, __in CComVariant varChild)
{
if (!pAcc)
return L"";
CComVariant varRoleID;
HRESULT hr = pAcc->get_accRole(varChild, &varRoleID);
if (FAILED(hr))
return L"";
WCHAR sRoleBuff[1024] = {0};
hr = ::GetRoleText(varRoleID.lVal, sRoleBuff, 1024);
if (FAILED(hr))
return L"";
return sRoleBuff;
}

И это вывод консоли:

    Chrome_WidgetWin_1 = 000702C0
--------------------------
* Chrome Legacy Window  |  window (Object)
* System  |  menu bar (Object)
* <NULL>  |  title bar (Object)
* IME  |  push button (Child)
* Minimize  |  push button (Child)
* Maximize  |  push button (Child)
* Context help  |  push button (Child)
* Close  |  push button (Child)
* Application  |  menu bar (Object)
* Chrome Legacy Window  |  client (Object)
//  -----> { there should be a big sub-tree here } <----- //
* Vertical  |  scroll bar (Object)
* Line up  |  push button (Child)
* Page up  |  push button (Child)
* Position  |  indicator (Child)
* Page down  |  push button (Child)
* Line down  |  push button (Child)
* Horizontal  |  scroll bar (Object)
* Column left  |  push button (Child)
* Page left  |  push button (Child)
* Position  |  indicator (Child)
* Page right  |  push button (Child)
* Column right  |  push button (Child)
* <NULL>  |  grip (Object)

Вот скриншот AccExplorer, показывающий полное дерево: (некоторые узлы свернуты)
Рабочий пример AccExplorer


Редактировать:
Когда используешь OBJID_WINDOW вместо OBJID_WINDOW (как в примере, в AccessibleObjectFromWindow) — Я получаю дерево с большим количеством узлов, но все еще не вижу элементы вкладки.

5

Решение

Хорошо, так что после слишком долгого времени я нашел небольшую мелочь, которая имела все значение …
Я забыл использовать CoInitialize ()

Интересно то, что без CoInitialize () это работает, но только частично, и HRESULT не указал это (не получил ничего подобного CO_E_NOTINITIALIZED).

Во всяком случае — если вы используете IAccessible wihtout CoInitialize — ожидать, что вещи не будут работать должным образом …

3

Другие решения


По вопросам рекламы [email protected]