// VDesktopClick.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <string>
#include <Oleacc.h>
using namespace std;
#define SET_LIST 1
#define SET_BUT 2
#pragma comment(lib,"Oleacc.lib")
wstring wsTitle = L"title";
wstring wsAppPath = L"adasd\asdasd\asdasd\asd.exe";
DWORD dwX = 60;
DWORD dwY = 20;
/*
目的:模拟点击自绘控件,同时不干扰电脑正常工作,也可以理解成不让使用者察觉到。
测试功能:找到title是wsTitle的窗体,将位置移动到用户看不到的区域,然后以这个窗体为树根,遍历窗体上的所有其他小窗体,目标是找到一个自绘的
byutton,尺寸是dwX,dwY。的自绘控件,然后模拟一次点击。
如果界面程序不存在的话就开启一个虚拟桌面,然后在虚拟桌面上去启动这个界面程序,然后模拟。假设界面程序的路径是wsAppPath。
*/
void GetObjectName(IAccessible* child,VARIANT* varChild,wchar_t* 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;
wcscpy_s(objName,MAX_PATH,tmp);
}
void GetObjectRole(IAccessible* child,VARIANT* varChild,wchar_t* 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;
wcscpy_s(objRole,MAX_PATH,tmp);
free(lpszRoleString);
return /*S_OK*/;
}
void GetObjectClass(IAccessible* child,wchar_t* 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;
wcscpy_s(objClass,MAX_PATH,tmp);
free(strClass);
}
BOOL Find(IAccessible* paccParent,IAccessible** paccChild) {
HRESULT hr;
long numChildren;
unsigned long numFetched;
VARIANT varChild;
int indexCount;
IAccessible* pCAcc = NULL;
IEnumVARIANT* pEnum = NULL;
IDispatch* pDisp = NULL;
BOOL found = false;
wchar_t szObjName[MAX_PATH],szObjRole[MAX_PATH],szObjClass[MAX_PATH],szObjState[MAX_PATH];
//Get the IEnumVARIANT interface
hr = paccParent->QueryInterface(IID_IEnumVARIANT,(PVOID*)&pEnum);
if(pEnum){
pEnum->Reset();
}
// Get child count
paccParent->get_accChildCount(&numChildren);
for(indexCount = 1; indexCount<=numChildren && !found; indexCount++) {
pCAcc = NULL;
// Get next child
if(pEnum)
hr = pEnum->Next(1,&varChild,&numFetched);
else {
varChild.vt = VT_I4;
varChild.lVal = indexCount;
}
// Get IDispatch interface for the child
if(varChild.vt==VT_I4) {
pDisp = NULL;
hr = paccParent->get_accChild(varChild,&pDisp);
}
else
pDisp = varChild.pdispVal;
// Get IAccessible interface for the child
if(pDisp) {
hr = pDisp->QueryInterface(IID_IAccessible,(void**)&pCAcc);
hr = pDisp->Release();
}
// Get information about the child
if(pCAcc) {
VariantInit(&varChild);
varChild.vt = VT_I4;
varChild.lVal = CHILDID_SELF;
*paccChild = pCAcc;
}else{
*paccChild = paccParent;
}
ZeroMemory(szObjName,(MAX_PATH<<1));
ZeroMemory(szObjRole,(MAX_PATH<<1));
ZeroMemory(szObjClass,(MAX_PATH<<1));
GetObjectName(*paccChild,&varChild,szObjName,sizeof(szObjName));
GetObjectRole(*paccChild,&varChild,szObjRole,sizeof(szObjRole));
GetObjectClass(*paccChild,szObjClass,sizeof(szObjClass));
LONG px = 0;
LONG py = 0;
LONG pcx = 0;
LONG pcy = 0;
(*paccChild)->accLocation(&px,&py,&pcx,&pcy,varChild);
if(_wcsicmp(L"Button",szObjClass) == 0){
if(pcx==dwX) {
if(pcy==dwY) {
//wchar_t ccl[1024] = {0};
//wsprintf(ccl,L"-----------%s %s %s %d,%d,%d,%d",szObjName,szObjClass,szObjRole,px,py,pcx,pcy);
//OutputDebugStringW(ccl);
(*paccChild)->accDoDefaultAction(varChild); //模拟点击运行按钮
Sleep(1500);//模拟点击,等待按钮响应。
}
}
}
if(!found && pCAcc) {
// Go deeper
found = Find(pCAcc,paccChild);
if(*paccChild!=pCAcc){
pCAcc->Release();
}
}
}
// Clean up
if(pEnum){
pEnum->Release();
}
return found;
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd,DWORD lParam){
wchar_t temp[200];
ZeroMemory(temp,400);
GetWindowTextW((HWND)hwnd,temp,200);
if(_wcsicmp(wsTitle.c_str(),temp) == 0){
OutputDebugStringW(temp);
if(lParam == SET_BUT){
HWND hwndOneClickBar = (HWND)hwnd;
IAccessible* accT = NULL;
IAccessible* aaaaaaccT = NULL;
HRESULT hr = AccessibleObjectFromWindow(hwndOneClickBar,OBJID_WINDOW,IID_IAccessible,(LPVOID*)&accT);
if(FAILED(hr)) {
return TRUE;
}
Find(accT,&aaaaaaccT);
}
}
return TRUE;
}
void GoClick() {
//方案1:直接就能找到界面的情况,界面开着呢
HWND hw = ::FindWindow(NULL,wsTitle.c_str());
if(hw!=NULL) {
::SetWindowPos(hw,0,-100,-100,100,100,SWP_NOZORDER);
::SetWindowLong(hw,GWL_HWNDPARENT,WS_EX_TOOLWINDOW);
EnumDesktopWindows(0,(WNDENUMPROC)EnumWindowsProc,SET_BUT);
CloseHandle(hw);
return;
}
//方案2:需要自己开启虚拟桌面,然后再启动界面程序,达到隐藏的目的
#define MAX_B_SIZE 1024
wchar_t strS[MAX_B_SIZE] = {0};
ZeroMemory(strS,(MAX_B_SIZE<<1));
wcscpy_s(strS,MAX_B_SIZE,wsAppPath.c_str());
HDESK hDesk = CreateDesktop(L"desktop__vvvv",NULL,NULL,NULL,GENERIC_ALL,NULL);
HDESK hDst = GetThreadDesktop(GetCurrentThreadId());
SetThreadDesktop(hDesk);
STARTUPINFO si = {0};
si.cb = sizeof(si);
si.lpDesktop = L"desktop__vvvv";
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOW;
PROCESS_INFORMATION pi = {0};
if(CreateProcess(NULL,strS,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) {
Sleep(5000);
EnumDesktopWindows(hDesk,(WNDENUMPROC)EnumWindowsProc,SET_BUT);
Sleep(10000);
}
CloseDesktop(hDesk);
SetThreadDesktop(hDst);
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
GoClick();
return 0;
}