zoukankan      html  css  js  c++  java
  • 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 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
    	);
    
  • 相关阅读:
    LVS基于DR模式负载均衡的配置
    Linux源码安装mysql 5.6.12 (cmake编译)
    HOSt ip is not allowed to connect to this MySql server
    zoj 3229 Shoot the Bullet(无源汇上下界最大流)
    hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割
    poj 2391 Ombrophobic Bovines(最大流+floyd+二分)
    URAL 1430 Crime and Punishment
    hdu 2048 神、上帝以及老天爷(错排)
    hdu 3367 Pseudoforest(最大生成树)
    FOJ 1683 纪念SlingShot(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/csnd/p/15613562.html
Copyright © 2011-2022 走看看