C/C++ 实现模拟键盘鼠标

今天写了点代码,功能是筛选桌面中符合某些条件的窗口,模拟鼠标键盘实现全选 → 复制 → 检测剪切板 → 判断是否存在某些敏感字符串。

这段代码使用了Windows API和一些其他库来遍历窗口,并对指定的窗口进行操作和判断。下面是对代码的解释:

  1. 引入了一系列头文件,包括afx.hafxwin.hWindows.h等。这些头文件提供了所需的API函数和类型定义。

  2. 使用using namespace std;来指定使用std命名空间。

  3. 定义了一个函数getClipBoardValue,用于获取剪贴板的文本内容。该函数打开剪贴板,获取数据,然后转换为字符,并进行一些善后工作。

  4. 定义了一个回调函数EnumWindowsProc,用于遍历窗口。该函数在每个窗口被枚举时调用。在函数内部,过滤了不可见窗口、存在标题的窗口和大小不为650x380的窗口。

  5. 在满足条件的窗口中,进行了一系列操作,包括模拟鼠标右键点击、模拟按键操作以获取剪贴板内容,并对剪贴板内容进行判断和输出。

  6. _tmain函数中,调用EnumWindows函数来枚举所有顶层窗口,并将回调函数EnumWindowsProc作为参数传入。

  7. 程序执行完毕后,调用getchar函数暂停程序,以便查看结果。

需要注意的是,这段代码使用了一些Windows特定的API函数和数据类型,因此只能在Windows平台上运行。另外,代码中还存在一些使用C-style字符串和C风格的输入输出函数的情况,建议在使用C++时使用更安全的字符串和输入输出方式。

#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 comment(lib,"WtsApi32.lib")

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 而不用 SendMessage ?因为 SendMessage 会等待目标返回的结果,如果你发送消息的窗口一直不返回结果,它就会一直等待下去,导致程序卡死在这里,而 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
	);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微软技术分享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值