天天看點

C++ PostMessage 模拟鍵盤滑鼠

今天寫了點代碼,功能是篩選桌面中符合某些條件的視窗,模拟滑鼠鍵盤實作全選 → 複制 → 檢測剪切闆 → 判斷是否存在某些敏感字元串。

大緻功能是這樣。下面是代碼(如果不想看不相關的内容可以直接跳到底部):

// Test_Console.cpp : 定義控制台應用程式的入口點。
//

#include "stdafx.h"
#include <afx.h>
#include <afxwin.h>
#include <Windows.h>
#include <vector>
#include <iostream>
#include <assert.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <WtsApi32.h>
#include <locale.h>
#include <stdio.h>

#pragma

using namespace std; 

// 擷取剪切闆内容
char* getClipBoardValue(){
    // 初始化
    char *url,*pData;
    size_t length;

    // 打開剪切闆
    OpenClipboard(NULL);

    // 擷取剪切闆内的資料
    HANDLE hData=GetClipboardData(CF_TEXT);
    assert(hData!=NULL);

    // 擷取資料長度
    length=GlobalSize(hData);
    url=(char*)malloc(length+1);

    // 将資料轉換為字元
    pData=(char*)GlobalLock(hData);
    strcpy_s(url, length,pData); 

    // 一系列善後工作
    GlobalUnlock(hData);
    CloseClipboard();
    url[length]=0;
    
    return url;
}

// 周遊視窗
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    // 過濾不可見的視窗
    if(IsWindowVisible(hwnd)){
        // 過濾掉存在标題的視窗
        char szTitle[100];
        GetWindowText(hwnd, szTitle, 100);
        if(strcmp(szTitle,"") == 0){
            // 過濾掉大小不為 650*380 的視窗
            RECT rect;
            GetWindowRect(hwnd,&rect);
            if((rect.right - rect.left) == 650 && (rect.bottom - rect.top) == 380){
                // 過濾掉沒有指定文本的視窗
                for(int i=0;i<5;i++){
                    // 指定位置右鍵
                    PostMessage(hwnd, WM_RBUTTONDOWN, 0,MAKELPARAM(200,200));
                    PostMessage(hwnd, WM_RBUTTONUP,0,MAKELPARAM(200,200));
                    Sleep(10);
                    // 按下 'A'
                    PostMessage(hwnd, WM_KEYDOWN,0x41,0);
                    PostMessage(hwnd, WM_KEYUP,0x41,0);
                    Sleep(10);
                    // 指定位置右鍵
                    PostMessage(hwnd, WM_RBUTTONDOWN, 0,MAKELPARAM(200,200));
                    PostMessage(hwnd, WM_RBUTTONUP,0,MAKELPARAM(200,200));
                    Sleep(10);
                    // 按下 'C'
                    PostMessage(hwnd, WM_KEYDOWN,0x43,0);
                    PostMessage(hwnd, WM_KEYUP,0x43,0);
                }
                // 指定位置左鍵(取消選中)
                PostMessage(hwnd, WM_LBUTTONDOWN, 0,MAKELPARAM(200,200));
                PostMessage(hwnd, WM_LBUTTONUP,0,MAKELPARAM(200,200));
                
                // 輸出剪切闆内容
                cout << getClipBoardValue() << endl;
                
                // 判斷是否比對特征
                string s_clipBoard = getClipBoardValue();
                if(s_clipBoard.find("未來終生的伴侶")!=s_clipBoard.npos){
                    cout << "檢測到特征" << endl;
                }
            }
        }    
    }
    

    return TRUE;
}


int _tmain(int argc, _TCHAR* argv[])
{
    EnumWindows(EnumWindowsProc, 0);
     
    getchar();
    return 0;
}      

下面是 PostMessage 在本代碼中的詳解

// 模拟滑鼠
PostMessage(
  hwnd,          // 目标視窗句柄
  WM_RBUTTONDOWN,    // 更多滑鼠事件宏定義類型參考 : https://docs.microsoft.com/en-us/windows/win32/inputdev/mouse-input-notifications
  0,
  MAKELPARAM(200,200)    // x = 200,y = 200(相對于視窗的坐标,而不是螢幕的坐标)
  );

// 模拟鍵盤
PostMessage(
  hwnd,          // 目标視窗句柄
  WM_KEYDOWN,        // 更多鍵盤事件共定義參考 : https://docs.microsoft.com/en-us/windows/win32/inputdev/keyboard-input
  0x41,          // 更多按鍵種類宏定義參考 : https://docs.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes
  0
  );