有时我们可能会在某个程序中用到模拟按钮点击事件。
本文中的例子在MFC程序中调试通过,duilib的没试过,还需探索
不多说,上代码:
1 #include "stdafx.h" 2 #include "windows.h" 3 #include "Psapi.h" 4 #include "atlstr.h" 5 #include <string.h> 6 #include<iostream> 7 using namespace std; 8 9 #pragma comment(lib,"Psapi"); 10 #define ID_EXEC_CURFILE 32807 11 #define ID_RCL_HELP 32804 12 CString str; 13 14 //根据exe名字一部分查找进程id,返回 15 DWORD FindProcess(char *strProcessName) 16 { 17 DWORD aProcesses[1024], cbNeeded, cbMNeeded; 18 HMODULE hMods[1024]; 19 HANDLE hProcess; 20 char szProcessName[MAX_PATH]; 21 if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) ) return 0; 22 for(int i=0; i< (int) (cbNeeded / sizeof(DWORD)); i++) 23 { 24 hProcess = OpenProcess( /*PROCESS_QUERY_INFORMATION | PROCESS_VM_READ*/PROCESS_ALL_ACCESS, FALSE, aProcesses[i]); 25 if (hProcess == NULL) 26 continue; 27 EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbMNeeded); 28 GetModuleFileNameEx( hProcess, hMods[0], szProcessName,sizeof(szProcessName)); 29 30 if(strstr(szProcessName, strProcessName)) 31 { 32 OutputDebugString(_T("Find Process ok ")); 33 cout<<szProcessName<<endl; 34 return(aProcesses[i]); 35 } 36 } 37 OutputDebugString(_T("Find Process fail ")); 38 return 0; 39 } 40 41 42 /******************************************************************* 43 * 函数名称:GetWindowHandleByPID 44 * 功 能:根据进程ID找窗口句柄 45 * 参 数:dwProcessID:进程Id号 46 * 返 回 值:成功返回窗口句柄,失败返回NULL 47 *******************************************************************/ 48 HWND GetWindowHandleByPID(DWORD dwProcessID) 49 { 50 HWND h = GetTopWindow(0); 51 while ( h ) 52 { 53 DWORD pid = 0; 54 DWORD dwTheardId = GetWindowThreadProcessId( h,&pid); 55 56 if (dwTheardId != 0) 57 { 58 if ( pid == dwProcessID/*your process id*/ ) 59 { 60 // here h is the handle to the window 61 OutputDebugString(_T("GetWindowHandleByPID ok ")); 62 return h; 63 } 64 } 65 66 67 h = GetNextWindow( h , GW_HWNDNEXT); 68 } 69 70 OutputDebugString(_T("GetWindowHandleByPID faild ")); 71 return NULL; 72 } 73 74 75 /******************************************************************* 76 * 函数名称:SendMsgChildWindow 77 * 功 能:遍历子窗口句柄并发送按钮消息 78 * 参 数:hWnd:父窗口句柄 79 * 返 回 值:null 80 *******************************************************************/ 81 void SendMsgChildWindow(HWND hWnd, UINT command, UINT ID, UINT eventType) 82 { 83 HWND hd = ::GetWindow(hWnd,GW_HWNDNEXT); 84 if (hd == NULL) 85 { 86 cout << "can not find window" <<endl; 87 } 88 while(hd!=NULL) //循环得到所有的子窗口 89 { 90 PostMessage(hd,command,MAKEWPARAM(ID, eventType),0); 91 hd=GetNextWindow(hd,GW_HWNDNEXT); 92 } 93 //PostMessage(HWND_BROADCAST,command,MAKEWPARAM(ID, eventType),0);//广播,不建议使用,其他窗口也会收到 94 } 95 96 /******************************************************************* 97 * 函数名称:FindWhndByName 98 * 功 能:根据exe名字找窗口句柄 99 * 参 数:exeName 100 * 返 回 值:窗口句柄,找不到返回NULL 101 *******************************************************************/ 102 HWND FindWhndByName(char *exeName) 103 { 104 HANDLE handle; 105 handle = OpenProcess( 106 // PROCESS_QUERY_INFORMATION | // Required by Alpha 107 // PROCESS_CREATE_THREAD | // For CreateRemoteThread 108 // PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx 109 // PROCESS_VM_WRITE, // For WriteProcessMemory 110 PROCESS_ALL_ACCESS, 111 FALSE, FindProcess(exeName)); 112 if (handle == NULL) 113 { 114 OutputDebugString(_T("error: handle null ")); 115 } 116 DWORD ProcessId = GetProcessId(handle); 117 118 return GetWindowHandleByPID(ProcessId); 119 } 120 121 int CharToInt(char* str) 122 { 123 int ret = atoi(str); 124 return ret; 125 } 126 127 int HexstrToInt(char *str) 128 { 129 int nValude = 0; 130 sscanf(str,"%x",&nValude); 131 return nValude; 132 } 133 134 int _tmain(int argc, _TCHAR* argv[]) 135 { 136 HWND wHnd; 137 if (argc < 5) 138 { 139 OutputDebugString(_T("parameters not enough ")); 140 return 0; 141 } 142 else if (argc == 5) 143 { 144 wHnd = FindWhndByName(argv[1]); 145 SendMsgChildWindow(wHnd,HexstrToInt(argv[2]),CharToInt(argv[3]),CharToInt(argv[4])); 146 } 147 else if (argc == 6) 148 { 149 wHnd = FindWhndByName(argv[1]); 150 if (wHnd == NULL) 151 { 152 wHnd = FindWhndByName(argv[2]); 153 cout << "second exeName" <<endl; 154 } 155 SendMsgChildWindow(wHnd,HexstrToInt(argv[3]),CharToInt(argv[4]),CharToInt(argv[5])); 156 } 157 158 return 1; 159 }
四个参数:
第一个参数:进程的名字 例如:QQ.exe
第二个参数:消息类型 例如: 0x0111 代表 WM_CZMMAND
第三个参数:资源ID(按钮,菜单等)例如:32807(按钮ID可在程序源码中找到)
第四个参数:事件类型 例如:0 代表按钮单击(BN_CLICKED)
第二第四个参数具体值可在:WinUser.h 头文件中找到
调用实例:PostMsgProcess.exe QQ.exe 0x0111 32807 0
五个参数:
第一个参数:进程的名字 例如:QQ
第二个参数:进程的名字 例如:QQ.exe
第三个参数:消息类型 例如: 0x0111 代表 WM_CZMMAND
第四个参数:资源ID(按钮,菜单等)例如:32807(按钮ID可在程序源码中找到)
第五个参数:事件类型 例如:0 代表按钮单击(BN_CLICKED)
第二第四个参数具体值可在:WinUser.h 头文件中找到
调用实例:PostMsgProcess.exe QQ QQ.exe 0x0111 32807 0
如果有多个符合条件的窗口,先根据第一个参数找对应的窗口,找到就不再寻找,只能找一个符合条件的窗口发送消息
需要的库和头文件:https://files.cnblogs.com/files/george-cw/psapi.rar