C++用PostMessage模拟按钮点击

有时我们可能会在某个程序中用到模拟按钮点击事件。

本文中的例子在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\n"));
 33             cout<<szProcessName<<endl;
 34             return(aProcesses[i]);  
 35         }  
 36     }  
 37     OutputDebugString(_T("Find Process fail\n"));
 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\n"));
 62                 return h;
 63             }
 64         }
 65 
 66 
 67         h = GetNextWindow( h , GW_HWNDNEXT);
 68     }
 69 
 70     OutputDebugString(_T("GetWindowHandleByPID faild\n"));
 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\n"));
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\n"));
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

 

posted @ 2015-11-12 10:08  george_cw  阅读(9660)  评论(0编辑  收藏  举报