如何调用mouse_event不触发mouse hook以避免连点器误判按键状态
解决方案
核心思路是给你自己生成的模拟鼠标事件加专属标识,在鼠标钩子回调中识别到标识就直接跳过处理,不会触发你自己的业务逻辑判断,两种实现方案可选:
方案1:使用SendInput+额外信息标记(推荐,更稳定不会误判)
mouse_event已经是Windows过时API,优先用SendInput实现模拟点击,你可以在INPUT结构体的dwExtraInfo字段传入自定义魔数,钩子回调中读取该字段匹配魔数就忽略事件:
- 首先定义自定义魔数和相关Win32结构体:
// 自定义魔数,随便取个不会和其他程序重复的值即可 private const uint MY_SIMULATION_MAGIC = 0x12345678; [StructLayout(LayoutKind.Sequential)] struct INPUT { public uint type; public InputUnion U; public static int Size => Marshal.SizeOf(typeof(INPUT)); } [StructLayout(LayoutKind.Explicit)] struct InputUnion { [FieldOffset(0)] public MOUSEINPUT mi; } [StructLayout(LayoutKind.Sequential)] struct MOUSEINPUT { public int dx; public int dy; public uint mouseData; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [DllImport("user32.dll", SetLastError = true)] private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
- 改造你的
Utils.Click()方法,用SendInput实现,传入自定义魔数:
public static void Click() { // 按下左键 INPUT downInput = new INPUT { type = 0, // INPUT_MOUSE U = new InputUnion { mi = new MOUSEINPUT { dwFlags = 0x0002, // MOUSEEVENTF_LEFTDOWN dwExtraInfo = (IntPtr)MY_SIMULATION_MAGIC } } }; // 抬起左键 INPUT upInput = new INPUT { type = 0, U = new InputUnion { mi = new MOUSEINPUT { dwFlags = 0x0004, // MOUSEEVENTF_LEFTUP dwExtraInfo = (IntPtr)MY_SIMULATION_MAGIC } } }; SendInput(2, new[] { downInput, upInput }, INPUT.Size); }
- 改造你的鼠标钩子回调方法,最开头加判断:
注:如果你用的第三方鼠标钩子库没有暴露ExtraInfo属性,需要自己实现底层鼠标钩子回调,从
MSLLHOOKSTRUCT结构体中读取dwExtraInfo字段再传递给上层处理逻辑
void mouse_OnMouseActivity(object sender, System.Windows.Forms.MouseEventArgs e) { // 新增判断:如果是自己模拟的事件直接跳过 if (e.ExtraInfo == (IntPtr)MY_SIMULATION_MAGIC || Utils.dont || !mode) { return; } // 剩下的原有逻辑保持不变 // ... }
方案2:全局标记位方案(兼容mouse_event实现)
如果不想改原有mouse_event的实现,可以用全局线程安全标记位实现过滤:
- 先在Utils类中加线程安全的标记:
public static volatile bool isSimulatingClick = false;
- 改造
Utils.Click()方法:
public static void Click() { isSimulatingClick = true; // 你原有mouse_event的调用逻辑保持不变 // ... // 等待事件处理完成再复位标记,延时可以根据实际情况调整 Thread.Sleep(10); isSimulatingClick = false; }
- 钩子回调最开头加判断:
void mouse_OnMouseActivity(object sender, System.Windows.Forms.MouseEventArgs e) { if (Utils.isSimulatingClick || Utils.dont || !mode) { return; } // 原有逻辑保持不变 // ... }
原有代码额外优化建议
你当前代码中判断用户松开左键用的是e.Clicks == 2的逻辑不合理,这是判断双击的条件,你模拟的连续点击很容易触发这个条件导致误判停止,建议你单独监听MouseUp事件来设置down = false,逻辑会更稳定。
内容的提问来源于stack exchange,提问作者Mega
相关产品推荐
相关产品推荐

