首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

, IAccessible 的有关问题

2013-07-04 
求助, IAccessible 的问题本帖最后由 hiroyukki 于 2013-05-30 17:16:20 编辑有个需求是遍历某个 HWND 上

求助, 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++也只是看到这一层吧。不懂帮顶

热点排行