You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 19:45:08