C++怎么模拟鼠标点击 C++ mouse_event自动化操作实现【脚本】

9次阅读

应使用Sendinput替代mouse_event,因其更可靠、支持高DPI和uiPI绕过;需归一化坐标至0–65535范围,分DOWN/UP两步点击,并注意管理员权限与前台激活要求。

C++怎么模拟鼠标点击 C++ mouse_event自动化操作实现【脚本】

windows 下用 mouse_event 模拟点击已经过时,改用 SendInput

直接调 mouse_event 在现代 windows(尤其是 win10/11 启用 UIPI 或高 DPI 缩放时)大概率失效,或被拦截、坐标偏移、权限拒绝。微软自 Windows XP SP2 起就标记它为 deprecated,推荐统一走 SendInput —— 它更可靠、支持多点触控模拟、能绕过部分 UIPI 限制,且是当前自动化工具(如 AutoHotkey、PyAutoGUI 底层)的实际依赖。

关键区别mouse_event 是“发事件”,SendInput 是“发输入流”,系统按队列处理,行为更接近真实硬件输入。

  • SendInput 需要构造 INPUT 结构体,类型设为 INPUT_MOUSE
  • 鼠标坐标默认是**相对屏幕左上角的绝对像素值**,但需先调用 SetThreadDpiAwarenessContext 或启用 manifest 高 DPI 感知,否则在缩放 >100% 时坐标会错乱
  • 点击必须拆成两步:MOUSEEVENTF_LEFTDOWN + MOUSEEVENTF_LEFTUP,不能只发一个“click”标志

绝对坐标点击的完整代码片段(c++

以下是最小可用示例,不依赖第三方库,仅需 Windows.h

#include  

void ClickAt(int x, int y) { // 转换为绝对坐标系统(单位:1/65535 屏幕宽高) double scaleX = GetSystemMetrics(SM_CXSCREEN); double scaleY = GetSystemMetrics(SM_CYSCREEN); int dx = static_cast((x 65535.0) / (scaleX - 1)); int dy = static_cast((y 65535.0) / (scaleY - 1));

INPUT input[2] = {}; input[0].type = INPUT_MOUSE; input[0].mi.dx = dx; input[0].mi.dy = dy; input[0].mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;  input[1].type = INPUT_MOUSE; input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;  SendInput(2, input, sizeof(INPUT));

}

注意:MOUSEEVENTF_ABSOLUTE 要求坐标范围是 0–65535,不是像素值,必须做归一化转换;漏掉 MOUSEEVENTF_MOVE 就不会移动光标,只执行点击当前位置。

立即学习C++免费学习笔记(深入)”;

为什么点击没反应?常见卡点排查

即使代码编译通过,实际运行常静默失败,原因集中在权限与上下文:

  • 程序未以**管理员权限运行**:UAC 级别高的目标窗口(如任务管理器、某些游戏全屏界面)会拒绝非提升进程的输入
  • 目标窗口处于**前台被锁定状态**(例如锁屏后远程桌面连接断开),SendInput 仍会成功返回,但输入被丢弃
  • 没调 SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIred | ES_DISPLAY_REQUIRED),系统可能休眠或黑屏导致输入丢失
  • 使用 GetCursorPos + SetCursorPos 移动后再点击,不如直接用 SendInput 绝对坐标稳定——后者不触发钩子拦截,也不受鼠标加速影响

需要后台点击?PostMessage 不可靠,别硬试

有人想绕过焦点问题,用 PostMessageWM_LBUTTONDOWN/WM_LBUTTONUP 到目标窗口句柄。这几乎总是失败,因为:

  • 大多数 GUI 框架(qtwpf、WinForms)根本不响应后台发来的鼠标消息,它们只处理来自 SendInput 或真实驱动的输入
  • PostMessage 不触发底层输入,没有鼠标捕获、拖拽状态、双击计时等逻辑
  • 即便 Win32 原生窗口能收到,坐标系也常是客户区相对坐标,且需手动计算窗口偏移和 DPI 缩放,极易出错

真要后台操作,唯一较稳路径是:用 SetForegroundWindow 激活目标窗口 → 短暂延时(switchToThisWindow + Sleep(50))→ 再 SendInput。复杂场景建议直接用 UI Automation(IUIAutomation)API,它专为后台控件交互设计。

text=ZqhQzanResources