首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >12.2 实现键盘模拟按键

12.2 实现键盘模拟按键

作者头像
王 瑞
发布于 2023-10-11 07:50:58
发布于 2023-10-11 07:50:58
67401
代码可运行
举报
运行总次数:1
代码可运行

本节将向读者介绍如何使用键盘鼠标操控模拟技术,键盘鼠标操控模拟技术是一种非常实用的技术,可以自动化执行一些重复性的任务,提高工作效率,在Windows系统下,通过使用各种键盘鼠标控制函数实现动态捕捉和模拟特定功能的操作。

键盘鼠标的模拟是实现自动化的必备流程,通常我们可以使用keybd_event()实现对键盘的击键模拟,使用SetCursorPos()实现对鼠标的模拟,使用两者的配合读者可以很容易的实现对键盘鼠标的控制,本节将依次封装实现,模拟键盘鼠标控制功能,读者可根据自己的实际需求选用不同的函数片段。

12.2.1 模拟键盘按键

模拟按键的核心功能是通过调用keybd_event()函数实现的,如下是这段代码的完整实现,首先MySetKeyBig()函数该函数用于设置键盘状态是否为大小写,用户可以传入一个状态值来设置当前输入法大小写模式,MyAnalogKey()函数用于实现模拟键盘按键,该函数接收一个英文字符串,并自动实现击键操作,代码实现并不复杂,读者可自行测试功能。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <windows.h>
#include <iostream>

using namespace std;

// 设置键盘大小写状态 为TRUE则切换大写状态,否则切换小写状态
VOID MySetKeyBig(BOOL big = FALSE)
{
  // 判断键盘CapsLock键是否开启状态,开启状态则为大写,否则为小写
  if (GetKeyState(VK_CAPITAL))
  {
    // 如果当前键盘状态为大写,要求改小写,则模拟按键CapsLock切换状态
    if (!big)
    {
      keybd_event(VK_CAPITAL, NULL, KEYEVENTF_EXTENDEDKEY | 0, NULL);
      keybd_event(VK_CAPITAL, NULL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, NULL);
    }

    std::cout << "[键盘状态] " << "切换大写" << std::endl;
  }
  else
  {
    // 如果当前键盘状态为小写,要求改大写,则模拟按键CapsLock切换状态
    if (big)
    {
      keybd_event(VK_CAPITAL, NULL, KEYEVENTF_EXTENDEDKEY | 0, NULL);
      keybd_event(VK_CAPITAL, NULL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, NULL);
    }

    std::cout << "[键盘状态] " << "切换小写" << std::endl;
  }
}

// 模拟键盘按键
VOID MyAnalogKey(char* str)
{
  int iLen = 0;
  char* tmp = NULL;
  INPUT* keys = NULL;
  BOOL bOldState = FALSE;

  // 保存此操作前的键盘状态
  bOldState = (BOOL)GetKeyState(VK_CAPITAL);
  iLen = lstrlen(str);
  tmp = (char*)malloc(iLen);
  memmove(tmp, str, iLen);
  for (int i = 0; i < iLen; i++)
  {
    // 某些符号非直属键盘按键,这里只过滤转换两个,以后用到其它字符自行添加过滤
    if (tmp[i] == ' ')
    {
      // 产生一个击键消息步骤:按下->抬起
      keybd_event(VK_SPACE, NULL, KEYEVENTF_EXTENDEDKEY | 0, NULL);
      keybd_event(VK_SPACE, NULL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, NULL);
    }
    else if (tmp[i] == ',')
    {
      keybd_event(VK_OEM_COMMA, NULL, KEYEVENTF_EXTENDEDKEY | 0, NULL);
      keybd_event(VK_OEM_COMMA, NULL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, NULL);
    }
    else if (tmp[i] >= 'a' && tmp[i] <= 'z')
    {
      // 根据字符大小写切换键盘大小写状态
      MySetKeyBig(0);
      // keybd_event只识别大写
      keybd_event((BYTE)tmp[i] - 32, NULL, KEYEVENTF_EXTENDEDKEY | 0, NULL);
      keybd_event((BYTE)tmp[i] - 32, NULL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, NULL);
    }
    else if ((tmp[i] >= 'A' && tmp[i] <= 'Z') || (tmp[i] >= '0' && tmp[i] <= '9'))
    {
      MySetKeyBig(1);
      keybd_event((BYTE)tmp[i], NULL, KEYEVENTF_EXTENDEDKEY | 0, NULL);
      keybd_event((BYTE)tmp[i], NULL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, NULL);
    }
    else
    {
      keybd_event((BYTE)tmp[i] + 64, NULL, KEYEVENTF_EXTENDEDKEY | 0, NULL);
      keybd_event((BYTE)tmp[i] + 64, NULL, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, NULL);
    }
    Sleep(50);
  }
  // 恢复此操作之前的键盘状态
  MySetKeyBig(bOldState);
  free(tmp);
}

int main(int argc, char *argv[])
{
  Sleep(5000);
  MyAnalogKey((char*)"Love life , Love LyShark WelCome LyShark Cpp Home ...");

  system("pause");
  return 0;
}

读者可自行编译并运行上述代码片段,将光标移动到记事本中,等待五秒钟,则会依次敲击如下所示的键盘按键;

12.2.2 设置窗体最大化

如下代码实现了设置一个窗体置顶并将该窗体最大化显示的效果,该代码实现原理是通过使用EnumWindows函数传递一个回调函数,实现对特定窗体的枚举,当找到对应窗体句柄后则将该窗体句柄传递给global_hwnd全局句柄中,当获取到Google浏览器句柄之后则通过GetSystemMetrics函数得到当前全屏窗体的像素比,通过调用SetWindowPos可将一个窗体设置为置顶显示,最后可调用SendMessage函数向特定窗体句柄发送最大化消息,使其填充满整个屏幕,代码如下所示;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <windows.h>

using namespace std;

HWND global_hwnd = 0;

// 将字符串逆序
char * Reverse(char str[])
{
  int n = strlen(str);
  int i;
  char temp;
  for (i = 0; i < (n / 2); i++)
  {
    temp = str[i];
    str[i] = str[n - i - 1];
    str[n - i - 1] = temp;
  }
  return str;
}

// 窗体枚举回调函数
BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam)
{
  char WindowName[MAXBYTE] = { 0 };
  DWORD ThreadId, ProcessId = 0;

  GetWindowText(hwnd, WindowName, sizeof(WindowName));
  ThreadId = GetWindowThreadProcessId(hwnd, &ProcessId);
  printf("句柄: %-9d --> 线程ID: %-6d --> 进程ID: %-6d --> 名称: %s \n", hwnd, ThreadId, ProcessId, WindowName);

  // 首先逆序输出字符串,然后比较前13个字符
  if (strncmp(Reverse(WindowName), "emorhC elgooG", 13) == 0)
  {
    global_hwnd = hwnd;
  }
  return TRUE;
}

int main(int argc, char* argv[])
{
  // 枚举Google浏览器句柄
  EnumWindows(lpEnumFunc, 0);
  std::cout << "浏览器句柄: " << global_hwnd << std::endl;

  if (global_hwnd != 0)
  {
    // 获取系统屏幕宽度与高度 (像素)
    int cx = GetSystemMetrics(SM_CXSCREEN);
    int cy = GetSystemMetrics(SM_CYSCREEN);
    std::cout << "屏幕X: " << cx << " 屏幕Y: " << cy << std::endl;

    // 传入指定的HWND句柄
    HWND hForeWnd = GetForegroundWindow();
    DWORD dwCurID = GetCurrentThreadId();
    DWORD dwForeID = GetWindowThreadProcessId(hForeWnd, NULL);
    AttachThreadInput(dwCurID, dwForeID, TRUE);

    // 将该窗体呼出到顶层
    ShowWindow(global_hwnd, SW_SHOWNORMAL);
    SetWindowPos(global_hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
    SetWindowPos(global_hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
    SetForegroundWindow(global_hwnd);
    AttachThreadInput(dwCurID, dwForeID, FALSE);

    // 发送最大化消息
    SendMessage(global_hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);    // 最大化
    // SendMessage(global_hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); // 最小化
    // SendMessage(global_hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);    // 关闭
  }

  system("pause");
  return 0;
}

读者可自行编译并运行上述程序,此时会将谷歌浏览器全屏并置顶显示,输出信息如下图所示;

12.2.3 读取与设置剪辑板

读取与设置剪辑版可用于对数据的拷贝与设置,调用setClipbar函数并传入一段字符串可实现将传入字符串拷贝到剪辑版的功能,使用getClipBoardValue则可实现读取剪辑版中的内容到程序内。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
#include <windows.h>
#include <time.h>

// 将字符串写入到剪切板
BOOL setClipbar(const char* data)
{
  int contentSize = strlen(data) + 1;
  HGLOBAL hMemory; LPTSTR lpMemory;

  // 打开剪切板
  if (!OpenClipboard(NULL))
  {
    return FALSE;
  }
  // 清空剪切板
  if (!EmptyClipboard())
  {
    return FALSE;
  }
  // 对剪切板分配内存
  if (!(hMemory = GlobalAlloc(GMEM_MOVEABLE, contentSize)))
  {
    return FALSE;
  }
  // 锁定内存区域
  if (!(lpMemory = (LPTSTR)GlobalLock(hMemory)))
  {
    return FALSE;
  }

  // 复制数据到内存区域,解除内存锁定
  memcpy_s(lpMemory, contentSize, data, contentSize);
  GlobalUnlock(hMemory);

  // 设置剪切板数据
  if (!SetClipboardData(CF_TEXT, hMemory))
  {
    return FALSE;
  }
  
  // std::cout << "已复制: " << data << " 长度: " << contentSize << std::endl;
  return CloseClipboard();
}

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

  // 打开剪切板
  if (!OpenClipboard(NULL))
  {
    return FALSE;
  }

  // 获取剪切板内的数据
  HANDLE hData = GetClipboardData(CF_TEXT);
  if (hData == NULL)
  {
    return FALSE;
  }

  // 获取数据长度
  length = GlobalSize(hData);
  url = (char*)malloc(length + 1);

  // 将数据转换为字符
  pData = (char*)GlobalLock(hData);
  strcpy_s(url, length, pData);

  // 清理工作
  url[length] = 0;
  GlobalUnlock(hData);
  CloseClipboard();

  // 返回结果并释放内存
  char* result = _strdup(url);
  free(url);
  return result;
}

int main(int argc, char *argv[])
{
  Sleep(5000);

  for (size_t i = 0; i < 10; i++)
  {
    // 填充字符串
    char MyData[256] = { 0 };
    sprintf(MyData, "hello lyshark --> %d", i);

    // 设置到剪辑版
    BOOL set_flag = setClipbar(MyData);
    if (set_flag == TRUE)
    {
      // std::cout << "[*] 已设置" << std::endl;

      // 获取剪辑版
      char *data = getClipBoardValue();
      std::cout << "[剪辑版数据] = " << data << std::endl;
    }
  }

  system("pause");
  return 0;
}

运行上述程序,依次实现填充字符串并设置到剪辑版,最后再通过getClipBoardValue函数从剪辑版内读出数据,如下图所示;

本文作者: 王瑞 本文链接: https://www.lyshark.com/post/95b1ad6c.html 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
模拟键盘与鼠标操作 C++
今天给大家带来,模拟键盘与鼠标操作的C++代码 都是独立的函数模块 废话不多说,直接上代码 #include "stdafx.h" #include "Shunli.h" #include "conio.h" #include <iostream> #include <sstream> #include <string> #include <algorithm> #include <vector> #include <imm.h> #include <stdio.h> #include <Wi
Shunnet
2021/06/11
2K0
C#控制键盘按键(大小写按键等)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace sn设置键盘大小写 { public partial class Form1
用户8671053
2021/11/02
1.5K0
C#实现的三种方式实现模拟键盘按键
SendKeys.SendWait // 同步模拟按键(会阻塞UI直到对方处理完消息后返回)
用户7108768
2021/09/23
2.3K0
Electron中使用Node-ffi模拟键鼠操作
折腾这个东西就是要实现一个很简单的功能:在我的应用中控制处于后台的PPT进行翻页。
码客说
2020/05/09
4.7K0
C++实现一键关闭桌面
本程序使用C语言编写,调用的Windows API,所以只能在windows上运行
芯动大师
2023/10/14
3360
C++实现一键关闭桌面
python模拟键盘输入_python控制鼠标键盘
该函数原型:keybd_event(bVk, bScan, dwFlags, dwExtraInfo)
全栈程序员站长
2022/11/18
2.1K0
FindWindow使用方法_find do
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/170225.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/21
7310
pywin32模拟鼠标键盘操作
第三个参数:函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP则该按键被释放;
周小董
2019/03/25
2.9K0
python-sendkeys 模拟键
因为特殊需要, 想找一套能简单发送键盘消息,模拟键盘操作的模块。  类似于 C#.net  或 VB  的  sendKeys  函数。
py3study
2020/01/13
2.3K0
C/C++ 实现模拟键盘鼠标
今天写了点代码,功能是筛选桌面中符合某些条件的窗口,模拟鼠标键盘实现全选 → 复制 → 检测剪切板 → 判断是否存在某些敏感字符串。
王 瑞
2022/12/28
1.7K0
WPF桌面端开发-音视频录制、获取缩略图(使用OpenCvSharp)
音视频分开录制,音频如果麦克风和扬声器都录制的话,也要分开录制,最后再合并所有的流。
码客说
2023/07/11
1.8K0
使用VC内嵌Python实现的一个代码检测工具
        最近组内准备整顿代码,领导让我写个简单的python脚本分析代码中注释的行数和无效注释。因为这个需求不是很急,所以我想把简单的事情做复杂点。于是就写了一个用VC内嵌Python,并通过模拟按键和发消息去控制其他软件的工具。(转载请指明出处)
方亮
2019/01/16
1.1K0
外挂基础_开挂的正确姿势
  所谓游戏外挂,其实是一种游戏外辅程序,它可以协助玩家自动产生游戏动作、修改游戏网络数据包以及修改游戏内存数据等,以实现玩家用最少的时间和金钱去完成功力升级和过关斩将。虽然,现在对游戏外挂程序的“合法”身份众说纷纭,在这里我不想对此发表任何个人意见,让时间去说明一切吧。
全栈程序员站长
2022/11/10
2.6K0
Python PyWin32 模块
Python的生产效率极高,通过使用pypiwin32模块可以快速调用windows API函数,结合Python的高效开发能力,同等时间内比C++能更快的达到目标,pypiwin32模块封装了Win32下的常用定义,函数方法等。
王 瑞
2022/12/28
2.4K0
Python PyWin32 模块
Python 实现指定窗口置顶激活
通过Python实现对特定窗口的置顶操作以及对特定窗体发送按键,这里需要安装一个第三方pip包,执行命令pywin32安装好以后,我们运行试试。
王 瑞
2022/12/28
2.9K0
python之模拟键盘
对于python来说,模拟键盘的方式据我了解有三种方式,其中有pyuserinput,win32api,以及winio。
sjw1998
2019/09/28
5.6K0
Python制作回合制手游外挂简单教程(
会发现鼠标瞬间移动到坐标(1,1)的位置,我的电脑是1920*1080的,最右下角的坐标就是(1920,1080)。
py3study
2020/01/19
3.2K0
Python制作回合制手游外挂简单教程(
selenium 模拟键盘事件 复制粘贴、右键、回车等
#coding=utf-8 ''' selenium ''' from selenium import webdriver as wd import time bc=wd.Chrome(executable_path='f:\\chromedriver') #bc=wd.Ie(executable_path='f:\\IEDriverServer') bc.get('https://www.sogou.com') #模拟键盘事件 from selenium.webdriver.common.keys im
用户8449980
2021/07/11
2.4K0
12.1 使用键盘鼠标监控钩子
本节将介绍如何使用Windows API中的SetWindowsHookEx和RegisterHotKey函数来实现键盘鼠标的监控。这些函数可以用来设置全局钩子,通过对特定热键挂钩实现监控的效果,两者的区别在于SetWindowsHookEx函数可以对所有线程进行监控,包括其他进程中的线程,而RegisterHotKey函数只能对当前线程进行监控。
王 瑞
2023/10/07
6700
12.1 使用键盘鼠标监控钩子
Python 制作按键触发Windows通知的脚本
对于键盘没有背光灯的同学而言,切换大小写或控制Num键开关的时候没有提示,经常需要试探性地输入一些字符来判断开关是否打开,体验非常糟糕。
abs_zero
2020/12/15
2K0
Python 制作按键触发Windows通知的脚本
相关推荐
模拟键盘与鼠标操作 C++
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档