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
    	);
    
  • 相关阅读:
    【设计模式:单例模式】使用单例模式载入properties文件
    Java 强引用,软引用,弱引用
    sharepreference实现记住password功能
    WWDC2015
    activity之栈管理
    LeetCode:Palindrome Number
    ZOJ 3822 Domination(概率dp)
    WCF报 当前已禁用此服务的元数据发布的错误
    HTML常见标签总结
    xml基础总结
  • 原文地址:https://www.cnblogs.com/csnd/p/15613562.html
Copyright © 2011-2022 走看看