• 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
    "));
     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

  • 相关阅读:
    四招打造复合型人才
    Eclipse多国语言包的安装
    怎样和人配合(转)
    看海外如何解困建筑信息化(转)
    SSRS重装后不能在SSMS和IIS中打开,报Unauthorized错误的解决办法
    小心调用Replicator, While 和 CAG子活动
    自动备份 SourceSafe
    SQLServer2005新增序列功能的几个函数:ROW_NUMBER, RANK, DENSE_RANK, and NTILE
    分析物语
    定位.Net程序集文件
  • 原文地址:https://www.cnblogs.com/george-cw/p/4958089.html
Copyright © 2020-2023  润新知