跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++ 基于 SendInput 的键盘鼠标模拟实现

讲解 C++ 利用 Windows SendInput API 模拟键盘鼠标输入的方法。涵盖输入系统原理、API 结构体说明、完整代码示例(含按键、文本、鼠标移动点击功能)及常见问题解答。旨在帮助开发者理解 OS 输入事件链路,构建自动化测试或辅助工具,强调合规与安全边界。

黑客帝国发布于 2026/3/22更新于 2026/7/1847 浏览

一、项目背景

在实际工程中,我们经常让程序像'人'一样操作电脑:

  • 自动化测试:点击按钮、输入文本
  • 运维/工具:批量操作 GUI 程序
  • 辅助工具:快捷操作、脚本化流程
  • 教学实验:理解 OS 输入事件链路

这些需求的核心,都是:

程序如何向操作系统'注入'键盘与鼠标输入事件?


1. Windows 输入系统的基本认知

Windows 中,键盘和鼠标并不是直接'给应用'的,而是:

硬件 → 驱动 → 系统输入队列 → 消息分发 → 窗口

只要我们向系统输入队列提交合法事件,系统就会像处理真实硬件一样处理它。


2. 常见实现方式对比

方式特点是否推荐
keybd_event / mouse_event老 API❌ 已过时
SendInput官方推荐✅
驱动层复杂/高风险❌
注入 DLL非必要❌

本文只使用官方推荐的 SendInput。


3. 本项目目标

实现一个教学 + 工程可用的输入模拟模块,支持:

  • 键盘按下 / 抬起
  • 鼠标移动
  • 鼠标点击(左 / 右)
  • 简单组合输入
  • 清晰、可复用的封装

二、项目需求


1. 功能需求

实现以下能力:

  1. 模拟单个键按下与释放
  2. 模拟字符串输入
  3. 模拟鼠标移动到屏幕坐标
  4. 模拟鼠标左键 / 右键点击
  5. 支持组合示例(键盘 + 鼠标)

2. 技术约束

  • 平台:Windows
  • 语言:C++(C++11+)
  • API:SendInput
  • 不依赖第三方库

3. 合规与边界说明

  • 仅用于自动化、测试、辅助工具
  • 不包含隐藏、绕过、防检测等行为
  • 不针对任何未授权系统

三、相关技术


1. SendInput 是什么?

SendInput 是 Windows 提供的统一输入注入接口:

UINT SendInput( UINT cInputs, LPINPUT pInputs, int cbSize );

它可以一次性提交多个输入事件,系统会按顺序处理。


2. INPUT 结构体分类

INPUT { type: INPUT_KEYBOARD INPUT_MOUSE }

  • 键盘:KEYBDINPUT
  • 鼠标:MOUSEINPUT

3. 键盘扫描码 vs 虚拟键码

  • 虚拟键码(VK):更常用、更直观
  • 扫描码:更底层(本文不展开)

4. 屏幕坐标说明

SendInput 的绝对坐标范围是:

X: 0 ~ 65535 Y: 0 ~ 65535

需要从屏幕像素转换。


四、实现思路


1. 模块设计

封装一个 InputSimulator,提供:

  • KeyDown / KeyUp
  • SendText
  • MouseMove
  • MouseClick

2. 核心思想

构造 INPUT 结构 → 调用 SendInput → 系统分发


3. 工程可扩展性

后续可扩展:

  • 热键(Ctrl + C)
  • 拖拽
  • 滚轮
  • 多屏支持

五、完整实现代码

/************************************************************
 * 文件:InputSimulator.h
 * 描述:键盘与鼠标模拟工具(SendInput)
 ************************************************************/
#ifndef INPUT_SIMULATOR_H
#define INPUT_SIMULATOR_H
#include <windows.h>
#include <string>

/**
 * @brief 输入模拟器
 */
class InputSimulator {
public:
    /**
     * @brief 模拟按键按下
     */
    static void KeyDown(WORD vk) {
        INPUT input{};
        input.type = INPUT_KEYBOARD;
        input.ki.wVk = vk;
        input.ki.dwFlags = 0; // 按下
        SendInput(1, &input, sizeof(INPUT));
    }

    /**
     * @brief 模拟按键释放
     */
    static void KeyUp(WORD vk) {
        INPUT input{};
        input.type = INPUT_KEYBOARD;
        input.ki.wVk = vk;
        input.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &input, sizeof(INPUT));
    }

    /**
     * @brief 发送一个按键(按下 + 抬起)
     */
    static void KeyPress(WORD vk) {
        KeyDown(vk);
        Sleep(10);
        KeyUp(vk);
    }

    /**
     * @brief 模拟输入字符串(仅示例英文/ASCII)
     */
    static void SendText(const std::string& text) {
        for (char c : text) {
            SHORT vk = VkKeyScanA(c);
            if (vk == -1) continue;
            bool shift = (vk & 0x0100) != 0;
            WORD vkCode = vk & 0xFF;
            if (shift) KeyDown(VK_SHIFT);
            KeyPress(vkCode);
            if (shift) KeyUp(VK_SHIFT);
            Sleep(5);
        }
    }

    /**
     * @brief 将屏幕像素坐标转换为 SendInput 绝对坐标
     */
    static LONG NormalizeX(int x) {
        return LONG(x * 65535.0f / GetSystemMetrics(SM_CXSCREEN));
    }
    static LONG NormalizeY(int y) {
        return LONG(y * 65535.0f / GetSystemMetrics(SM_CYSCREEN));
    }

    /**
     * @brief 移动鼠标到指定屏幕坐标
     */
    static void MouseMove(int x, int y) {
        INPUT input{};
        input.type = INPUT_MOUSE;
        input.mi.dx = NormalizeX(x);
        input.mi.dy = NormalizeY(y);
        input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
        SendInput(1, &input, sizeof(INPUT));
    }

    /**
     * @brief 鼠标左键点击
     */
    static void MouseLeftClick() {
        INPUT inputs[2]{};
        inputs[0].type = INPUT_MOUSE;
        inputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
        inputs[1].type = INPUT_MOUSE;
        inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
        SendInput(2, inputs, sizeof(INPUT));
    }

    /**
     * @brief 鼠标右键点击
     */
    static void MouseRightClick() {
        INPUT inputs[2]{};
        inputs[0].type = INPUT_MOUSE;
        inputs[0].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
        inputs[1].type = INPUT_MOUSE;
        inputs[1].mi.dwFlags = MOUSEEVENTF_RIGHTUP;
        SendInput(2, inputs, sizeof(INPUT));
    }
};
#endif // INPUT_SIMULATOR_H

/************************************************************
 * 文件:main.cpp
 * 描述:模拟输入示例
 ************************************************************/
#include <iostream>
#include "InputSimulator.h"

int main() {
    // 给用户 3 秒准备时间
    Sleep(3000);
    // 模拟输入文字
    InputSimulator::SendText("Hello World");
    // 回车
    InputSimulator::KeyPress(VK_RETURN);
    // 移动鼠标并点击
    InputSimulator::MouseMove(500, 300);
    Sleep(500);
    InputSimulator::MouseLeftClick();
    return 0;
}

六、代码详细解读


1. KeyDown / KeyUp

作用:

  • 构造键盘 INPUT
  • 提交到系统输入队列
  • 等价于真实按键

2. SendText

作用:

  • 将字符映射为虚拟键码
  • 自动处理 Shift
  • 逐字符发送输入

3. MouseMove

作用:

  • 使用绝对坐标模式
  • 精确移动到屏幕位置

4. MouseLeftClick / MouseRightClick

作用:

  • 组合 Down + Up
  • 模拟完整点击行为

七、项目总结

本项目完整实现了一个:

✅ 官方 API ✅ 行为稳定 ✅ 工程可复用 ✅ 教学价值高

的 C++ 键盘鼠标模拟模块。

通过它,你应当真正理解:

  • Windows 输入事件是如何产生的
  • SendInput 的正确使用方式
  • 输入模拟与自动化测试的核心原理

八、项目常见问题及解答


Q1:为什么有些程序收不到模拟输入?

答:

  • 高权限程序需要同等权限
  • 某些游戏/安全软件会主动屏蔽
  • 这是系统安全策略,不是代码问题

Q2:可以模拟中文输入吗?

答:

  • 简单示例不支持
  • 中文需:
    • 输入法状态
    • 或使用 KEYEVENTF_UNICODE

Q3:会被系统识别为'假输入'吗?

答:

  • SendInput 是官方 API
  • 行为等同真实输入(但受安全策略限制)

九、扩展方向与性能优化


1. Unicode 输入支持

  • 使用 KEYEVENTF_UNICODE
  • 支持中文/多语言

2. 组合键支持

  • Ctrl + C / Alt + Tab
  • 自动化测试高频需求

3. 鼠标拖拽与滚轮

  • 拖动文件
  • 模拟滚动

4. UI 自动化封装

  • 结合窗口查找(FindWindow)
  • 构建自动化测试框架

目录

  1. 一、项目背景
  2. 1. Windows 输入系统的基本认知
  3. 2. 常见实现方式对比
  4. 3. 本项目目标
  5. 二、项目需求
  6. 1. 功能需求
  7. 2. 技术约束
  8. 3. 合规与边界说明
  9. 三、相关技术
  10. 1. SendInput 是什么?
  11. 2. INPUT 结构体分类
  12. 3. 键盘扫描码 vs 虚拟键码
  13. 4. 屏幕坐标说明
  14. 四、实现思路
  15. 1. 模块设计
  16. 2. 核心思想
  17. 3. 工程可扩展性
  18. 五、完整实现代码
  19. 六、代码详细解读
  20. 1. KeyDown / KeyUp
  21. 2. SendText
  22. 3. MouseMove
  23. 4. MouseLeftClick / MouseRightClick
  24. 七、项目总结
  25. 八、项目常见问题及解答
  26. Q1:为什么有些程序收不到模拟输入?
  27. Q2:可以模拟中文输入吗?
  28. Q3:会被系统识别为“假输入”吗?
  29. 九、扩展方向与性能优化
  30. 1. Unicode 输入支持
  31. 2. 组合键支持
  32. 3. 鼠标拖拽与滚轮
  33. 4. UI 自动化封装
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 多模态大模型 API 调用与本地部署成本深度对比
  • Spring Boot 后端开发核心注解详解
  • 枚举问题两大利器:深度优先搜索 DFS 与下一个排列算法详解
  • SQL Prompt 工具介绍与正版使用建议
  • 前端请求后端返回 404/405/500 状态码排查与解决指南
  • 攻防世界 Web 题解:Lottery 与 ics-05 漏洞分析
  • VSCode Git 插件详解与配置指南
  • AI 训练师算法与模型训练从入门到精通
  • GraphQL在Python中的完整实现:从基础到企业级实战
  • ROS2 + Gazebo + PX4 环境搭建与无人机仿真起飞指南
  • WhisperLiveKit 翻译引擎深度评测:NLLB 600M vs 1.3B 速度与质量对比
  • Windows 系统下安装 Mamba 全流程指南
  • VS Code 远程连接服务器后 GitHub Copilot 无法使用解决方案
  • YOLOv8 旋转框角度回归优化:CSL 与 DCL 编码实战
  • Windows 系统下 PostgreSQL 安装与配置指南
  • Vivado 2019.2 开发环境搭建指南
  • Trae 集成 Figma MCP 实现前端代码自动生成
  • 基于 SpringBoot 的游戏账号在线交易系统设计与实现
  • Stable Diffusion 与 kohya_ss 安装指南
  • 用 Java 设计一个随机验证码生成器

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online