您的位置:首页 > 其它

IAccessiable的学习和使用

2016-04-07 22:24 197 查看
前几天听群里大神讨论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先。



很明显不认识IAccessiable这个类型啊。查阅MADN需要包含头文件,和lib文件

#include <OleAcc.h>


添加完成,再次编译,果然错误少了很多。



查阅代码发现有如下函数调用

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>


大功告成,运行结果果然如预期一样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  IAccessiab COM