读书人

IAccessible 的有关问题

发布时间: 2013-07-04 11:45:40 作者: rapoo

求助, IAccessible 的问题
本帖最后由 hiroyukki 于 2013-05-30 17:16:20 编辑 有个需求是遍历某个 HWND 上的 IAccessible 对象,查文档拼凑如类似如下的代码,但似乎只能枚举到直接的一层子 IAccessible,孙子辈的就枚举不到了。
有做过的大牛指点一下吗,感激不尽


#include <windows.h>
#include <oleacc.h>
#include <stdio.h>
#include <comutil.h>
#include <Shlwapi.h>
#include <string>

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "oleacc.lib")
#pragma comment(lib, "comsuppw.lib")
#pragma comment(lib, "Shlwapi.lib")

using namespace std;

typedef BOOL (WINAPI* pfnAccHandler)(IAccessible*, void*);

#define _HRELEASE(p) \
if (p) \
{ \
p->Release(); \
p = NULL; \
} \
p \

string ToMultiByte(const wstring &str)
{
string ret;

int count = WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, NULL, 0, NULL, NULL);

if (count > 0)
{
char* buffer = (char*)malloc(count);

if (buffer)
{
WideCharToMultiByte(CP_ACP, 0, str.c_str(), -1, buffer, count, NULL, NULL);
ret = buffer;

free((void*)buffer);
}
}

return ret;
}

BOOL WINAPI AccGetRole(IAccessible* pAcc, LPWSTR wszRole, DWORD dwRoleSize)
{
BOOL bRet = FALSE;
VARIANT varRole;
VARIANT varSelf;
VariantInit(&varRole);
VariantInit(&varSelf);

varSelf.vt = VT_I4;
varSelf.lVal = CHILDID_SELF;

if (S_OK == (pAcc->get_accRole(varSelf, &varRole)))
{
if (VT_I4 == varRole.vt)
{
UINT nRole = varRole.lVal;
GetRoleTextW(nRole, wszRole, dwRoleSize);
bRet = TRUE;
}
else if (VT_BSTR == varRole.vt)
{
_bstr_t bRole(varRole.bstrVal, TRUE);
wnsprintfW(wszRole, dwRoleSize, L"%s", (wchar_t*)bRole);


bRet = TRUE;
}
}

VariantClear(&varRole);
VariantClear(&varSelf);

return bRet;
}

BOOL WINAPI AccGetName(IAccessible* pAcc, LPWSTR wszName, DWORD dwNameSize)
{
BOOL bRet = FALSE;
VARIANT varSelf;
VariantInit(&varSelf);

varSelf.vt = VT_I4;
varSelf.lVal = CHILDID_SELF;

BSTR bName;
if (S_OK == pAcc->get_accName(varSelf, &bName))
{
wnsprintfW(wszName, dwNameSize, L"%s", bName);
SysFreeString(bName);
bRet = TRUE;
}

VariantClear(&varSelf);

return bRet;
}

static BOOL WINAPI _AccEnumChild(IAccessible* pAccParent, pfnAccHandler pfnHandler, void* lpParam)
{
BOOL bRet = FALSE;
VARIANT varChild;
IEnumVARIANT* pEnum = NULL;
IAccessible* pAccChild = NULL;
VariantInit(&varChild);

do
{
if (!pAccParent || !pfnHandler)
{
break;
}

if (!pfnHandler(pAccParent, lpParam))
{
break;
}
pAccParent->QueryInterface(IID_IEnumVARIANT, (void**)(&pEnum));
if (pEnum)
{
pEnum->Reset();
}

long lChildCount = 0;
pAccParent->get_accChildCount(&lChildCount);
// 没有子就跳过
if (!lChildCount)
{
bRet = TRUE;
break;
}
printf("有子 %d 个\n", lChildCount);

BOOL bBreak = FALSE;
ULONG ulFetched = 0;
for (long index = 1; index <= lChildCount; ++index)
{


VariantClear(&varChild);
_HRELEASE(pAccChild);

if (pEnum)
{
if (!SUCCEEDED(pEnum->Next(1, &varChild, &ulFetched)))
{
continue;
}
}
else
{
varChild.vt = VT_I4;
varChild.lVal = index;
}

if (VT_I4 == varChild.vt)
{
pAccParent->get_accChild(varChild, (IDispatch**)(&pAccChild));
}

if (!pAccChild)
{
printf("!pAccChild\n");
continue;
}

if (!_AccEnumChild(pAccChild, pfnHandler, lpParam))
{
bBreak = TRUE;
break;
}
}

if (!bBreak)
{
bRet = TRUE;
}
} while (FALSE);

_HRELEASE(pAccChild);
_HRELEASE(pEnum);

VariantClear(&varChild);

return bRet;
}

BOOL WINAPI _AccIterator(IAccessible* pAcc, void* lpParam)
{
WCHAR wszRole[1024] = {0};
if (AccGetRole(pAcc, wszRole, RTL_NUMBER_OF(wszRole)))
{
printf("Role: %s\n", ToMultiByte(wszRole).c_str());


}
WCHAR wszName[1024] = {0};
if (AccGetName(pAcc, wszName, RTL_NUMBER_OF(wszName)))
{
printf("Name: %s\n", ToMultiByte(wszName).c_str());
}

return TRUE;
}

int main()
{
HWND hWnd = FindWindowA("Chrome_WidgetWin_1", NULL);
if (!IsWindow(hWnd))
{
printf("未找到窗口\n");
return 1;
}

IAccessible* pAccMain = NULL;
AccessibleObjectFromWindow(hWnd, OBJID_WINDOW, IID_IAccessible, (void**)(&pAccMain));
if (!pAccMain)
{
return 1;
}

_AccEnumChild(pAccMain, _AccIterator, NULL);

_HRELEASE(pAccMain);

return 0;
}

#undef _HRELEASE


[解决办法]
一般来说肯定是把当前的节点当做父节点再递归调用枚举函数哦...
[解决办法]
用VS自带的Spy++也只是看到这一层吧。不懂帮顶

读书人网 >VC/MFC

热点推荐