msaa- MS Active Accessibility 接口技术问题

问题描述

MS Active Accessibility 接口技术问题

#include
#include
#include
#include "atlbase.h"
#include
#pragma comment(lib,"oleacc.lib")
BOOL FindChild (IAccessible* paccParent,
char* szName, char* szRole,
char* szClass,
IAccessible** paccChild,
VARIANT* pvarChild);
UINT GetObjectState(IAccessible* pacc,
VARIANT* pvarChild,
LPTSTR lpszState,
UINT cchState);
void GetObjectName(IAccessible* paccChild, VARIANT* varChild, char szObjName[], int s);
void GetObjectRole(IAccessible* paccChild, VARIANT* varChild, char szObjRole[], int s);
void GetObjectClass(IAccessible* paccChild,char szObjClass[], int s);
int main()
{

IAccessible* paccControl = NULL;//输入框的 IAccessible 接口
VARIANT     varControl;         //子ID。
HWND hWndMainWindow;
IAccessible *paccMainWindow = NULL;
HRESULT hr;
//得到标题为"运行"的窗口的句柄
if(NULL == (hWndMainWindow = FindWindow(NULL, "运行")))
{
    MessageBox(NULL, "没有发现窗口!", "错误", MB_OK);
}
else
{
    //通过窗口句柄得到窗口的 IAccessible 接口指针。
    if(S_OK == (hr = AccessibleObjectFromWindow(
        hWndMainWindow,
        OBJID_WINDOW,
        IID_IAccessible,
        (void**)&
        paccMainWindow)))
    {
        //……我们可以通过这个指针paccMainWindow进行操作。
        //paccMainWindow->Release();
        //在文本输入框输入"regedit"
        printf("paccMainWindow:%dn",paccMainWindow);
        if(1 == FindChild (paccMainWindow, "打开(O):",
            "可编辑文字",
            "Edit",
            &paccControl,
            &varControl))
        {
            //在这里修改文本编辑框的值
            printf("xiu gai wenben nei rongn");
            hr = paccControl->put_accValue(varControl,CComBSTR("regedit"));
            printf("xiu gai cheng gongn");
            paccControl->Release();
            VariantClear(&varControl);
        }

        // 找到确定按钮,并执行默认动作。
        if(1 == FindChild (paccMainWindow,
            "确定",
            "按下按钮",
            "Button",
            &paccControl,
            &varControl))
        {
            //这里执行按钮的默认动作,即"按下这个按钮"
            hr = paccControl->accDoDefaultAction(varControl);
            paccControl->Release();
            VariantClear(&varControl);
        }
    }
}
return 0;

}
BOOL FindChild (IAccessible* paccParent,
char* szName, char* szRole,
char* szClass,
IAccessible** paccChild,
VARIANT* pvarChild)
{
HRESULT hr;
long numChildren;
unsigned long numFetched;
VARIANT varChild;
int index;
IAccessible* pCAcc = NULL;
IEnumVARIANT* pEnum = NULL;
IDispatch* pDisp = NULL;
BOOL found = false;
char szObjName[256], szObjRole[256], szObjClass[256], szObjState[256];

//得到父亲支持的IEnumVARIANT接口
if(paccParent==NULL)
{
    printf("paccParent is NULL");
    return false;
}
printf("enter findalln");
hr = paccParent->QueryInterface(IID_IEnumVARIANT,(void**)&pEnum);
if(pEnum)
    pEnum -> Reset();

//取得父亲拥有的可访问的子的数目
paccParent -> get_accChildCount(&numChildren);
printf("numChildren:%dn",numChildren);

//搜索并比较每一个子ID,找到名字、角色、类与输入相一致的。
for(index = 1; index <= numChildren && !found; index++)
{
    printf("%dn",index);
    pCAcc = NULL;
    // 如果支持IEnumVARIANT接口,得到下一个子ID
    //以及其对应的 IDispatch 接口
    printf("pEnum:%dn",pEnum);
    if (pEnum)
    {
        VariantInit(&varChild);
        printf("varChild:%dn",varChild);
        hr = pEnum -> Next(1, &varChild, &numFetched);
        if(hr==S_OK)
            printf("S_OKn");
        printf("varChild:%dn",varChild);
    }
    else
    {
        //如果一个父亲不支持IEnumVARIANT接口,子ID就是它的序号
        varChild.vt = VT_I4;
        varChild.lVal = index;
    }

    // 找到此子ID对应的 IDispatch 接口
    if (varChild.vt == VT_I4)
    {
        //通过子ID序号得到对应的 IDispatch 接口
        pDisp = NULL;
        printf("pDisp:%dn",pDisp);
        hr = paccParent ->get_accChild(varChild,(IDispatch**)&pDisp);
        printf("pDisp:%dn",pDisp);
    }
    else
        //如果父支持IEnumVARIANT接口可以直接得到子IDispatch 接口
        pDisp = varChild.pdispVal;

    // 通过 IDispatch 接口得到子的 IAccessible 接口 pCAcc
    if (pDisp)
    {
        printf("pCAcc:%dn",pCAcc);
        hr = pDisp->QueryInterface(IID_IAccessible, (void**)&pCAcc);
        printf("pCAcc:%dn",pCAcc);
        hr = pDisp->Release();
    }

    // Get information about the child
    if(pCAcc)
    {
        //如果子支持IAccessible 接口,那么子ID就是CHILDID_SELF
        VariantInit(&varChild);
        varChild.vt = VT_I4;
        varChild.lVal = CHILDID_SELF;

        *paccChild = pCAcc;
    }
    else
        //如果子不支持IAccessible 接口
        *paccChild = paccParent;

    //跳过了有不可访问状态的元素
    GetObjectState(*paccChild,
        &varChild,
        szObjState,
        sizeof(szObjState));
    if(NULL != strstr(szObjState, "unavailable"))
    {
        if(pCAcc)
            pCAcc->Release();
        continue;
    }
    //通过get_accName得到Nam
    GetObjectName(*paccChild, &varChild, szObjName, sizeof(szObjName));
    //通过get_accRole得到Role
    GetObjectRole(*paccChild, &varChild, szObjRole, sizeof(szObjRole));
    //通过WindowFromAccessibleObject和GetClassName得到Class
    GetObjectClass(*paccChild, szObjClass, sizeof(szObjClass));
    //以上实现代码比较简单,大家自己看代码吧。
    //如果这些参数与输入相符或输入为NULL
    if ((NULL==szName ||
        0==strcmp(szName, szObjName))&&
        (NULL==szRole ||
        0==strcmp(szRole, szObjRole)) &&
        (NULL==szClass ||
        0==strcmp(szClass, szObjClass)))
    {
        found = true;
        *pvarChild = varChild;
        break;
    }
    if(!found && pCAcc)
    {
        // 以这次得到的子接口为父递归调用
        printf("findall again");
        found = FindChild(pCAcc,
            szName,
            szRole,
            szClass,
            paccChild,
            pvarChild);
        if(*paccChild != pCAcc)
            pCAcc->Release();
    }
}//End for
// Clean up
if(pEnum)
    pEnum -> Release();
printf("exit findalln");
return found;

}

// UI元素的状态也表示成整型形式。因为一个状态可以有多个值,
//例如可选的、可做焦点的,该整数是反映这些值的位的或操作结果。
//将这些或数转换成相应的用逗号分割的状态字符串。
UINT GetObjectState(IAccessible* pacc,
VARIANT* pvarChild,
LPTSTR lpszState,
UINT cchState)
{
HRESULT hr;
VARIANT varRetVal;

*lpszState = 0;

VariantInit(&varRetVal);

hr = pacc->get_accState(*pvarChild, &varRetVal);

if (!SUCCEEDED(hr))
    return(0);

DWORD dwStateBit;
int cChars = 0;
if (varRetVal.vt == VT_I4)
{
    // 根据返回的状态值生成以逗号连接的字符串。
    for (dwStateBit = STATE_SYSTEM_UNAVAILABLE;
           dwStateBit < STATE_SYSTEM_ALERT_HIGH;
           dwStateBit <<= 1)
    {
        if (varRetVal.lVal & dwStateBit)
        {
            cChars += GetStateText(dwStateBit,
                                   lpszState + cChars,
                                   cchState - cChars);
            *(lpszState + cChars++) = ',';
        }
    }
    if(cChars > 1)
        *(lpszState + cChars - 1) = '';
}
else if (varRetVal.vt == VT_BSTR)
{
    WideCharToMultiByte(CP_ACP,
                        0,
                        varRetVal.bstrVal,
                        -1,
                        lpszState,
                        cchState,
                        NULL,
                        NULL);
}

VariantClear(&varRetVal);

return(lstrlen(lpszState));

}
void GetObjectName(IAccessible* paccChild, VARIANT* varChild, char szObjName[], int s)
{
printf("getnamen");
if(paccChild==NULL)
{
printf("IAccessible is NULL");
return;
}
CComBSTR buf;
paccChild->get_accName(*varChild,&buf);
unsigned int i,len;
len=buf.Length();
memset(szObjName,0,s);
for(i=0;i
*(szObjName+i)=*(buf.m_str+i);
}
void GetObjectRole(IAccessible* paccChild, VARIANT* varChild, char szObjRole[], int s)
{
printf("getrolen");
if(paccChild==NULL)
{
printf("IAccessible is NULL");
return;
}
VARIANT buf;
paccChild->get_accRole(*varChild,&buf);
buf.vt=VT_I2;
szObjRole=(char*)buf.bstrVal;
}
void GetObjectClass(IAccessible* paccChild,char szObjClass[], int s)
{
printf("getclassn");
if(paccChild==NULL)
{
printf("IAccessible is NULLn");
return;
}
HWND hwnd;
LPSTR buf;
WindowFromAccessibleObject(paccChild,&hwnd);
GetClassName(hwnd,buf,s);
szObjClass=buf;
printf("getclass endn");
}
我第二次for循环一直运行出错,pDisp的值一直为0

解决方案

使用pDisp之前判断一下指针是否为空,为空就不要调用。同时输出一下返回的错误码信息来分析具体原因。

解决方案二:

!程序运行到第二次for循环的 paccParent ->get_accChild(varChild,&pDisp);就会出现这个](http://img.ask.csdn.net/upload/201504/22/1429668328_835708.png)

解决方案三:

我发现问题好像是IEnumVARIANT得到的值都是负值,应该是枚举到的不对,但是应该怎么写啊

时间: 2025-01-26 12:48:17

msaa- MS Active Accessibility 接口技术问题的相关文章

MS Active Accessibility接口技术编程尝试

Microsoft Active Accessibility 2.0 is a COM-based technology that improves the way accessibility aids work with applications running on Microsoft Windows?. It provides dynamic-link libraries that are incorporated into the operating system as well as

msaa-Active Accessibility 接口技术 遍历元素,如何取得句柄

问题描述 Active Accessibility 接口技术 遍历元素,如何取得句柄 我现在已经能做到使用 Active Accessibility 接口技术 遍历元素出IE里面所有元素了,但是不知道如何取对应的句柄 这是我的部分代码 foreach (var childChild1 in clientChilren) { if (childChild1.GetType().ToString().IndexOf("Object") > -1) { IAccessible chil

【ARM】ARM接口技术

0开发工具的使用 1安装keil4 2运行MDK411EXE安装 3选择好要安装的目的位置 4安装完成并运行 5安装JLink驱动 6运行测试例程验证开发板是否OK 1自己做一个例子 1新建一个项目 2选择与开发板对应的CPU型号 3设置一个好的目标和组 4配置目标 5创建一个测试文件 51创建mainc文件 52建一个汇编文件 53建立一个ini文件 6设置参数 7上板子调试 2ARM接口原理 1查看原理图 2GPIO控制原理 21GPBCON 22GPBDAT 3程序怎么写 4练习自己实现b

《工业控制网络安全技术与实践》一2.5.5 PLC的接口技术

2.5.5 PLC的接口技术 本文讲的是工业控制网络安全技术与实践一2.5.5 PLC的接口技术 1.对接口电路的要求 1)能够可靠地传送控制机床动作的相应控制信息,并能够输入控制机床所需的有关状态信息.信息形式有数字量(以8位二进制形式表示的数字信息).开关量(以1位二进制数"0"或"1"表示的信息)和模拟量3种. 2)能够进行相应的信息转换,以满足CNC(数控装置)系统的输入与输出要求(常把数控机床分为CNC侧和MT(Machine Tool,机床)侧,PLC位

【黑科技】新一代脑机接口技术基石:通过大脑扫描数据重建图像

近日,中国科学院自动化研究所的研究团队提出了一种令人既兴奋又恐慌的大脑黑科技:"读脑术".据 5月6号的MIT Technology Review 头条报道,读脑术算法可以通过大脑扫描数据重建图像,其评论道,"新提出的技术有效克服了这个领域的一系列难点,能够更加精确地读懂人类大脑信号,还原出人眼所看到的视觉场景.该技术不仅对计算神经科学意义重大,也是研发新一代脑-机接口技术的基石."   That's interesting work with significan

113_《DELPHI接口技术开发实例解析》

<DELPHI接口技术开发实例解析> Delphi 教程 系列书籍 (113) <DELPHI接口技术开发实例解析> 网友(邦)整理 EMail: shuaihj@163.com 下载地址: 下载 作者: 张仿彦 出版社:机械工业出版社 ISBN:7111203216 上架时间:2006-12-28 出版日期:2007 年1月 开本:16开 版次:1-1 内容简介 本书包括食堂管理系统.程控电话计费系统.批发零售管理系统.vod点播系统.钢筋拉伸试验管理系统5个案例,这5个不同行业

精神控制?心灵感应?脑机接口技术让科幻成为现实

你希望像X战警中的X教授那样拥有精神控制的能力吗?或者你也曾想过和亲人能够心灵感应呢?最近大脑-计算机对接的进展正在将脑间直接传递思想的科学幻想变成现实.过去几年发表的一系列研究宣告了动物之间.人之间甚至人鼠之间脑活动的直接传输.这种"脑脑对接"(BBI)通过连接两个个体的大脑实现了脑活动的实时直接传递.虽然目前的脑机接口技术与科幻作品中的描述无法比拟,但通过意念简单操纵机器,正一点一点走进现实. ECAI 2016 精选论文摘要 标题:基于脑电波的脑机接口高阶相关系数分析 摘要:基于

php面向对象全攻略 (十四) php5接口技术_php基础

20.PHP5 接口技术 PHP 与大多数面向对象编程语言一样,不支持多重继承.也就是说每个类只能继承一个父 类.为了解决这个问题,PHP 引入了接口,接口的思想是指定了一个实现了该接口的类必须 实现的一系列方法.接口是一种特殊的抽象类,抽象类又是一种特殊的类,所以接口也是一 种特殊的类,为什么说接口是一种特殊的抽象类呢?如果一个抽象类里面的所有的方法都是 抽象方法,那么我们就换一种声明方法使用"接口":也就是说接口里面所有的方法必须都是 声明为抽象方法,另外接口里面不能声明变量,而且

php接口技术实例详解_php技巧

本文实例讲述了php接口技术.分享给大家供大家参考,具体如下: 1.接口是一种特殊的抽象类,为什么这么说呢?如果一个抽象类中所有的方法都是抽象方法,那么我们就换一种称呼,称为"接口". 2.另外接口中不能声明变量. 3.接口中所有的成员都是public权限的.所有的子类在实现时,也一定要使用public权限去实现. 4.声明一个类的时候,我们用关键字"class",而声明接口的时候,我们用关键字"interface". <?php //定义