IAccessiable的学习和使用

来源:互联网 发布:微视频神器软件 编辑:程序博客网 时间:2024/05/22 00:18

前几天听群里大神讨论IAccessiable借口,于是动念学习一下。打开百度,输入IAccessiable,得到一大堆的词条,仔细看就可以搞懂IAccessiable到底是个什么东东。以下摘自MSDN的一段描述:

The IAccessible interface and all of its exposed members are part of a
managed wrapper for the Component Object Model (COM) IAccessible
interface.

概念啥的一百就出来,但是这个东西到底怎么用呢?还是老办法,看看别人怎么用。以下为我找的一篇博客:
IAccessible ( 二 )
根据这篇博客弄了一个demo编译一下。结果,啊哈,果然有错,有错误不打紧,debug先。
debug1
很明显不认识IAccessiable这个类型啊。查阅MADN需要包含头文件,和lib文件

#include <OleAcc.h>

添加完成,再次编译,果然错误少了很多。
Debug2
查阅代码发现有如下函数调用

GetObjectName(*paccChild, &varChild, szObjName, sizeof(szObjName));GetObjectRole(*paccChild, &varChild, szObjRole, sizeof(szObjRole));GetObjectClass(*paccChild, szObjClass, sizeof(szObjClass));

这三个函数在给定的Demo代码中并没有给出实现。仔细分析代码流程会发现,这三个函数功能其实很简单,就是获取给定子空间的Name, Role 和Class。没有枪没有炮,我们自己造。先造第一个GetObjectName函数原型很容易推断出,返回值我们不妨先不设,因为程序中也没有用到。以下函数原型:

void GetObjectName(IAccessible* child, VARIANT* varChild, char* objName, int len)

那么如何实现这个功能呢。翻阅MSDN我们发现IAccessable接口有这么个函数

HRESULT get_accName(  [in]          VARIANT varID,  [out, retval] BSTR    *pszName);

参数返回一个BSTR类型的Name,而我们需要一个char*类型。如何搞?用下微软的_bstr_t转换下。上代码:

void GetObjectName(IAccessible* child, VARIANT* varChild, char* objName, int len){    BSTR strTmp;    HRESULT hr = child->get_accName(*varChild, &strTmp);    if (S_OK != hr)    {        return;    }    _bstr_t str = strTmp;    char* tmp = str;    strcpy_s(objName, MAX_PATH, tmp);}

调试下,果然成功获取到Name值。
接下来的Class和Role过程大致类似,直接上代码:

void GetObjectRole(IAccessible* child, VARIANT* varChild, char* objRole, int len){    VARIANT pvarRole;    DWORD roleId;    child->get_accRole(*varChild, &pvarRole);    if (varChild->vt != VT_I4)    {        pvarRole.vt = VT_EMPTY;        return /*E_INVALIDARG*/;    }    roleId = pvarRole.lVal;    UINT   roleLength;    LPTSTR lpszRoleString;    // Get the length of the string.    roleLength = GetRoleText(roleId, NULL, 0);    // Allocate memory for the string. Add one character to    // the length you got in the previous call to make room    // for the null character.    lpszRoleString = (LPTSTR)malloc((roleLength + 1) * sizeof(TCHAR));    if (lpszRoleString != NULL)    {        // Get the string.        GetRoleText(roleId, lpszRoleString, roleLength + 1);    }    char* tmp = TCHAR2char(lpszRoleString);    free(lpszRoleString);    strcpy_s(objRole, MAX_PATH, tmp);    return /*S_OK*/;}void GetObjectClass(IAccessible* child, char* objClass, int len){    HWND htmp;    LPTSTR strClass;    strClass = (LPTSTR)malloc(MAX_PATH);    ::WindowFromAccessibleObject(child, &htmp);    if (0 == ::GetClassName(htmp, strClass, MAX_PATH))    {        free(strClass);        return;    }    char* tmp = TCHAR2char(strClass);    strcpy_s(objClass, MAX_PATH, tmp);    free(strClass);}

其中涉及到一个问题,VS的默认编码是Unicode而我们需要一个char*这个绝对需要转换一下。如何转换呢?百一下得到了一个如下答案:

char* TCHAR2char(TCHAR* tchStr){    int iLen = 2 * wcslen(tchStr);    char* chRtn = new char[iLen + 1];    int len = wcstombs(chRtn,tchStr, iLen + 1);    return chRtn;}

还需要注意我们用到了_bstr_t和CComBSTR所以需要包含头文件和库文件查阅MSDN需要comsuppw.lib和头文件

#include <atlbase.h>

至此应该能编译通过了,但是回到宿舍,运行在中文环境的VS2015下并不能得到预期的结果。Debug之。发现,GetObjectName中的下列代码

wcstombs(buf, lpString, len);

返回值为-1,这个不科学啊,百度之。得到一个答案。没看明白,但是修改之后确实可以获取成功了。修改之后的代码:

char* TCHAR2char(TCHAR* tchStr){    int iLen = 2 * wcslen(tchStr);    char* chRtn = new char[iLen + 1];    _tsetlocale(LC_ALL, _T(""));    int len = wcstombs(chRtn,tchStr, iLen + 1);    return chRtn;}

当然需要先加上头文件:

#include <locale.h>

大功告成,运行结果果然如预期一样。

0 0
原创粉丝点击