虚拟桌面模拟查找点击自绘控件

// 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"adasdasdasdasdasdasd.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;
}



原文地址:https://www.cnblogs.com/csnd/p/12062212.html