// 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;
- }