windows/linux 模拟鼠标键盘输入

windows 使用 SendInput (用户空间 API)

cpp 复制代码
#include <Windows.h>


// UINT SendInput(
//   UINT nInputs,             // 输入结构体数量
//   LPINPUT pInputs,          // 指向输入结构体数组的指针
//   int cbSize                // 每个结构体的大小(单位:字节)
// );



void SimulateMouseClick(int x, int y) {
    // 设置鼠标位置(绝对坐标)
    SetCursorPos(x, y);

    // 创建鼠标事件结构体
    INPUT input = {0}
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;  // 鼠标按下
    SendInput(1, &input, sizeof(INPUT));

    Sleep(50);  // 等待 50ms

    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;    // 鼠标释放
    SendInput(1, &input, sizeof(INPUT));
}

void SimulateKeyPress(WORD keyCode) {
    INPUT input = {0};
    input.type = INPUT_KEYBOARD;
    input.ki.wVk = keyCode;        // 虚拟键码(如 VK_RETURN)
    input.ki.dwFlags = 0;          // 按下
    SendInput(1, &input, sizeof(INPUT));

    Sleep(50);  // 等待 50ms

    input.ki.dwFlags = KEYEVENTF_KEYUP;  // 释放
    SendInput(1, &input, sizeof(INPUT));
}


// 模拟 Ctrl + C(复制)操作
void ControlC() {
    INPUT inputs[4] = {0};

    // Ctrl down
    inputs[0].type = INPUT_KEYBOARD;
    inputs[0].ki.wVk = VK_CONTROL;

    // C down
    inputs[1].type = INPUT_KEYBOARD;
    inputs[1].ki.wVk = 'C';

    // C up
    inputs[2].type = INPUT_KEYBOARD;
    inputs[2].ki.wVk = 'C';
    inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;

    // Ctrl up
    inputs[3].type = INPUT_KEYBOARD;
    inputs[3].ki.wVk = VK_CONTROL;
    inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;

    SendInput(4, inputs, sizeof(INPUT));

}


int main() {
    SimulateMouseClick(500, 300);
    Sleep(100);
    SimulateKeyPress(VK_RETURN);
    return 0;
}

linux 使用 X11 库 (用户空间 API)

cpp 复制代码
#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>
#include <unistd.h>
#include <X11/keysym.h>

void SimulateKeyPress(Display* display, KeySym keysym) {
    KeyCode keycode = XKeysymToKeycode(display, keysym);
    XTestFakeKeyEvent(display, keycode, True, 0);   // True 按下
    XTestFakeKeyEvent(display, keycode, False, 0);  // False 释放
    XFlush(display);                                // 强制刷新事件队列,把事件立即发送给 X Server。
}

void SimulateMouseClick(Display* display, int button) {
    XTestFakeButtonEvent(display, button, True, 0);  // True 按下
    XTestFakeButtonEvent(display, button, False, 0); // False 释放
    XFlush(display);
}

int main() {
    Display* display = XOpenDisplay(nullptr);
    if (!display) return -1;

    SimulateMouseClick(display, 1);             // 1:鼠标左键,2:中键,3:右键
    sleep(1);
    SimulateKeyPress(display, XK_Return);       // 模拟回车键

    XCloseDisplay(display);
    return 0;
}

以上方式都是调用了用户空间的 API 来实现。

接下来介绍驱动层模拟的方式

输入子系统(Input Subsystem)结构

cpp 复制代码
[用户层] → /dev/uinput → 内核 input 子系统 → 事件发送至 X Server/Wayland
                                     ↓
                            应用程序收到输入
cpp 复制代码
[用户层] → DeviceIoControl → HID 驱动层 → 输入堆栈(Kbdclass/Mouclass) → Win32 消息

Linux 驱动层:使用 /dev/uinput 创建虚拟输入设备

Linux 提供了 uinput 接口,可在用户空间模拟底层输入事件,但从内核角度 看,是通过驱动层完成,在用户空间创建一个虚拟输入设备。通过 ioctl() 设置设备能力,然后通过写 input_event 结构体模拟键盘事件(比如按下 A 键),最后发送同步事件使其生效。这种方式运行在驱动层之上,绕过常规用户空间 API,常用于自动化测试或底层输入模拟。

/dev 文件夹的作用

  • /dev/tty:终端设备

  • /dev/console:系统控制台

  • /dev/input/eventX:键盘鼠标等输入设备

  • /dev/uinput:用户空间模拟输入设备

实现步骤:

  1. 打开 /dev/uinput

  2. 配置一个虚拟设备(设置支持的事件、按键)

  3. 写入 input_event 结构体发送事件

  4. 内核将其当作真实输入设备处理

伪代码如下:

cpp 复制代码
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);

// 设置设备支持按键
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, KEY_A);

// 配置虚拟设备信息,在 /proc/bus/input/devices 或 evtest 工具中能看到这个"虚拟键盘"。
struct uinput_user_dev uidev = {};
strcpy(uidev.name, "virtual-keyboard");
write(fd, &uidev, sizeof(uidev));
ioctl(fd, UI_DEV_CREATE);

// 模拟按下 'A'
struct input_event ev = {};
ev.type = EV_KEY;    // 键盘事件
ev.code = KEY_A;     // 对应 'A' 键
ev.value = 1;        // 按下
write(fd, &ev, sizeof(ev));

// 释放 'A'
ev.value = 0;        // 0 = 松开
write(fd, &ev, sizeof(ev));

// 同步事件,告诉内核:"我一组输入事件已经发完了,请立即处理它们"。
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
write(fd, &ev, sizeof(ev));

Windows 驱动层:写 HID 模拟驱动或使用驱动框架

在 Windows 中,驱动层模拟键盘鼠标通常通过以下方式实现:

方式 1:HID 模拟驱动

  • 编写一个虚拟 HID 设备(Human Interface Device)

  • 使用 KMDF/UMDF(内核/用户模式驱动框架)

  • 模拟输入数据包送入 HID Class 驱动堆栈

  • 类似于:软件伪造一个"插入的 USB 键盘"

相关推荐
双翌视觉4 小时前
高精度视觉对位实现键盘线路薄膜定位纠偏
数码相机·计算机外设
今夕资源网12 小时前
windows11无法启用投屏功能 无线显示器无法添加可选功能 解决办法 Miracast修复脚本
windows·计算机外设·miracast·系统修复·无线显示器·投屏功能·投屏功能无法添加
人工智能导论实践课1 天前
从零到一:用 ROS Noetic 搭建可键盘控制的 Gazebo 小车模型
计算机外设
站长工具箱1 天前
鼠标在线测试工具:全维度检测鼠标性能,本地处理更安全
测试工具·计算机外设
开开心心就好1 天前
免费轻量级PDF阅读器,打开速度快
windows·计算机视觉·visualstudio·pdf·计算机外设·excel·myeclipse
春日见2 天前
Matlab快速入门 基础语法教学
java·开发语言·驱动开发·matlab·docker·计算机外设
Saniffer_SH2 天前
【高清视频】AI服务器调试利器:PCIe功耗分析设备 Quarch PAM 深度解析
网络·人工智能·驱动开发·嵌入式硬件·测试工具·计算机外设·压力测试
Never_Satisfied2 天前
在JavaScript / HTML中,监听鼠标滚动事件
javascript·html·计算机外设
触想工业平板电脑一体机3 天前
【触想智能】工业触摸屏显示器的主要特点以及其应用领域分析
计算机外设
TESmart碲视4 天前
Mac+PC双系统如何共享双屏?KVM切换器选购的5个关键指标|TESmart用户真实体验复盘
macos·计算机外设·kvm切换器·tesmart·双屏kvm切换器·碲视