优先使用 SendInput 模拟鼠标点击,因其兼容高 DPI、多显示器和 UIPI;若必须用 mouse_event,需归一化坐标至 0–65535 并用 MOUSEEVENTF_ABSOLUTE。

怎么用 mouse_event 模拟鼠标点击(C#)
Windows API 的 mouse_event 已废弃,但仍在 .NET Framework 项目中常见。它不区分高 DPI 缩放,也不支持多显示器坐标偏移,直接调用容易点偏或失效。
实操建议:
- 优先改用
SendInput—— 它是微软当前推荐的输入模拟方式,兼容 DPI、多屏、UIPI(用户界面特权隔离) - 若必须用
mouse_event,确保传入屏幕绝对坐标(MOUSEEVENTF_ABSOLUTE),且把坐标归一化到 0–65535 范围:(int)(x * 65535.0 / screen.Width) - 不要在 WPF 或 WinForms 的 UI 线程里直接调用,避免被 UI 线程挂起或触发安全拦截;建议用
Task.Run包一层
C# 调用 SendInput 的最小可用写法
SendInput 需要构造 INPUT 结构体,最容易出错的是字段对齐、dwType 类型误设、以及未清零 padding 字段导致内存越界。
关键点:
-
INPUT必须用[StructLayout(LayoutKind.Sequential)],且显式指定SizeConst = 28(x64 下)或24(x86) - 鼠标事件必须设
dwType = 0,然后用dwFlags组合:比如左键按下是MOUSEEVENTF_LEFTDOWN,抬起是MOUSEEVENTF_LEFTUP - 坐标参数
dx/dy是相对还是绝对,取决于是否设置了MOUSEEVENTF_ABSOLUTE;绝对坐标下单位是 0–65535,不是像素 - 调用前检查返回值:如果
SendInput返回 0,说明输入被系统拦截(如锁屏、UAC 提权窗口前台)或结构体格式错误
示例片段(仅左键单击):
var input = new INPUT { type = 0, mi = new MOUSEINPUT { dx = 10000, dy = 10000, dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN } };
SendInput(1, ref input, INPUT.Size);
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP;
SendInput(1, ref input, INPUT.Size);
为什么模拟点击在远程桌面或最小化窗口里经常失效
不是代码写错了,而是 Windows 的输入模型限制:默认情况下,SendInput 和 mouse_event 只能向「当前活动桌面」和「前台进程」投递输入。远程桌面会切到自己的会话桌面,而程序最小化时通常失去前台焦点。
应对方式:
- 确认目标窗口是否处于活跃桌面(
GetThreadDesktop+OpenInputDesktop可查,但需权限) - 用
SetForegroundWindow+BringWindowToTop尝试激活目标窗口(不一定成功,尤其跨会话或高完整性级别进程) - 真正可靠的方案是注入目标进程并调用其内部消息循环(如
PostMessage发送WM_LBUTTONDOWN),但这需要目标窗口句柄和消息结构知识,且受 UIPI 限制 - 自动化测试场景建议换用 UI Automation(
System.Windows.Automation),它绕过输入队列,直接调用控件的InvokePattern
WPF/WinForms 程序里别用 API 模拟点击来“触发按钮逻辑”
这是最常被忽略的陷阱:你用 SendInput 点了界面上的按钮,但按钮的 Click 事件根本没执行。因为 UI 框架的事件是靠消息泵解析 WM_COMMAND 或路由事件触发的,API 级点击只产生原始鼠标消息,不走框架事件链。
正确做法:
- WinForms:直接调用
button.PerformClick() - WPF:获取按钮的
ICommand或手动触发button.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)) - 只有当你确实需要测试「真实鼠标行为」(比如验证鼠标坐标响应、拖拽反馈、第三方控件兼容性)时,才动用 Windows API
跨进程、跨会话、高 DPI、UAC、多显示器——这些不是边缘情况,是日常环境。API 模拟点击不是“写完就能跑”,得先想清楚你要模拟的是「输入动作」本身,还是「点击带来的业务效果」。后者几乎永远有更稳的替代路径。


















