实例介绍
【实例截图】
【核心代码】
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <oleacc.h>
#include <atlcomcli.h>
#pragma comment(lib, "Oleacc.lib")
BOOL Init(HWND hWnd, CComQIPtr<IAccessible, &IID_IAccessible>& ppAcc)
{
HRESULT hr = AccessibleObjectFromWindow(hWnd, OBJID_WINDOW, IID_IAccessible, (void**)&ppAcc);
if (hr != S_OK)
return FALSE;
return TRUE;
}
UINT GetObjectState(IAccessible* pacc,
VARIANT* pvarChild,
LPSTR 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 = GetStateTextA(dwStateBit,
lpszState cChars,
cchState - cChars);
*(lpszState cChars ) = ',';
}
}
if(cChars > 1)
*(lpszState cChars - 1) = '\0';
}
else if (varRetVal.vt == VT_BSTR)
{
WideCharToMultiByte(CP_ACP,
0,
varRetVal.bstrVal,
-1,
lpszState,
cchState,
NULL,
NULL);
}
VariantClear(&varRetVal);
return(strlen(lpszState));
}
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;
//wchar_t* tmp = str;
wchar_t* tmp = strTmp;
WideCharToMultiByte(CP_ACP,
0,
tmp,
-1,
objName,
len,
NULL,
NULL);
}
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);
}
wchar_t* tmp = lpszRoleString;
WideCharToMultiByte(CP_ACP,
0,
tmp,
-1,
objRole,
len,
NULL,
NULL);
free(lpszRoleString);
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;
}
wchar_t* tmp = strClass;
WideCharToMultiByte(CP_ACP,
0,
tmp,
-1,
objClass,
len,
NULL,
NULL);
free(strClass);
}
BOOL FindChild (IAccessible* paccParent,
LPSTR szName, LPSTR szRole,
LPSTR 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接口
hr = paccParent -> QueryInterface(IID_IEnumVARIANT, (PVOID*) & pEnum);
if(pEnum)
pEnum -> Reset();
//取得父亲拥有的可访问的子的数目
paccParent -> get_accChildCount(&numChildren);
//搜索并比较每一个子ID,找到名字、角色、类与输入相一致的。
for(index = 1; index <= numChildren && !found; index )
{
pCAcc = NULL;
// 如果支持IEnumVARIANT接口,得到下一个子ID
//以及其对应的 IDispatch 接口
if (pEnum)
hr = pEnum -> Next(1, &varChild, &numFetched);
else
{
//如果一个父亲不支持IEnumVARIANT接口,子ID就是它的序号
varChild.vt = VT_I4;
varChild.lVal = index;
}
// 找到此子ID对应的 IDispatch 接口
if (varChild.vt == VT_I4)
{
//通过子ID序号得到对应的 IDispatch 接口
pDisp = NULL;
hr = paccParent -> get_accChild(varChild, &pDisp);
}
else
//如果父支持IEnumVARIANT接口可以直接得到子IDispatch 接口
pDisp = varChild.pdispVal;
// 通过 IDispatch 接口得到子的 IAccessible 接口 pCAcc
if (pDisp)
{
hr = pDisp->QueryInterface(IID_IAccessible, (void**)&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得到Name
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 ((!szName ||
!strcmp(szName, szObjName)) &&
(!szRole ||
!strcmp(szRole, szObjRole)) &&
(!szClass ||
!strcmp(szClass, szObjClass)))
{
found = true;
*pvarChild = varChild;
break;
}
if(!found && pCAcc)
{
// 以这次得到的子接口为父递归调用
found = FindChild(pCAcc,
szName,
szRole,
szClass,
paccChild,
pvarChild);
if(*paccChild != pCAcc)
pCAcc->Release();
}
}//End for
// Clean up
if(pEnum)
pEnum -> Release();
return found;
}
void EnumWechat()
{
// 获取微信窗口
HWND hWnd = FindWindow(TEXT("WeChatMainWndForPC"), TEXT("微信"));
// 转成ACC接口
CComQIPtr<IAccessible,&IID_IAccessible> m_pAcc;
if( !Init(hWnd, m_pAcc) )
{
printf("打开失败!\n");
return ;
}
// 获取控件
VARIANT varControl;
IAccessible* paccControl = NULL;
if( FindChild(m_pAcc,
"聊天",
"按下按钮",
NULL,
&paccControl,
&varControl) )
{
printf("找到控件!\n");
// 操作控件
HRESULT hr = paccControl->accDoDefaultAction(varControl);
// 发送事件
long pxLeft = 0;
long pyTop = 0;
long pcxWidth = 0;
long pcyHeight = 0;
if (S_OK == paccControl->accLocation(&pxLeft, &pyTop, &pcxWidth, &pcyHeight, varControl)) // 获取到坐标 是全局坐标
{
printf("%u\n", pxLeft);
HDC hdc = GetDC(GetDesktopWindow());
// 在控件上画个矩形
HPEN hPen = CreatePen(PS_SOLID,0,RGB(255,0,0));
HBRUSH hBrush = CreateSolidBrush(RGB(255,0,0));
SelectObject(hdc, hPen);
SelectObject(hdc, hBrush);
Ellipse(hdc, pxLeft, pyTop, pxLeft pcxWidth, pyTop pcyHeight);
ReleaseDC(GetDesktopWindow(), hdc);
// 点击聊天
RECT rect = {0};
GetWindowRect(hWnd, &rect);
int xpoint, ypoint;
xpoint = pxLeft-rect.left pcxWidth/2;
ypoint = pyTop-rect.top pcyHeight/2;
printf("坐标(%u, %u)\n", xpoint, ypoint);
SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(xpoint, ypoint));
SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELONG(xpoint, ypoint));
Sleep(800);
// 切换到联系人
ypoint = pcyHeight;
SendMessage(hWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(xpoint, ypoint));
SendMessage(hWnd, WM_LBUTTONUP, 0, MAKELONG(xpoint, ypoint));
}
paccControl->Release();
VariantClear(&varControl);
}
}
INT _tmain(INT argc, TCHAR **argv)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
EnumWechat();
CoUninitialize();
return 0;
}
标签: 测试
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论