简体   繁体   English

如何使用 C# 在系统范围内禁用鼠标单击事件?

[英]How can I disable mouse click event system wide using C#?

I have a laptop with a very sensitive touch pad, and wanted to code a small program that could block the mouse input when I was typing a paper or something.我有一台带有非常敏感的触摸板的笔记本电脑,我想编写一个小程序,当我打字时可以阻止鼠标输入。

I didn't think it would be hard to do, considering everything I've seen on low-level hooks, but I was wrong (astounding, right?).考虑到我在低级钩子上看到的所有内容,我认为这并不难,但我错了(令人震惊,对吧?)。

I looked at a few examples, but the examples I've seen either block both keyboard and mouse, or just hide the mouse.我查看了一些示例,但我所看到的示例要么同时阻止了键盘和鼠标,要么只是隐藏了鼠标。

Any help with this would be great.对此的任何帮助都会很棒。

As you mentioned, you can do this using a low-level mouse hook ( WH_MOUSE_LL) , albeit somewhat incorrectly.正如您所提到的,您可以使用低级鼠标钩子( WH_MOUSE_LL)来执行此操作,尽管有些不正确。 What happens when you set a hook is that you'll receive notifications on each mouse input event ( WM_MOUSEMOVE , WM_LBUTTONDOWN , WM_RBUTTONDOWN , WM_MBUTTONDOWN , WM_XBUTTONDOWN , WM_NCXBUTTONDOWN , the equivalent up events for each of those, WM_MOUSEWHEEL , and WM_MOUSEHWHEEL ).什么,当你设置一个挂钩的情况是,您会收到每个鼠标输入事件通知( WM_MOUSEMOVEWM_LBUTTONDOWNWM_RBUTTONDOWNWM_MBUTTONDOWNWM_XBUTTONDOWNWM_NCXBUTTONDOWN ,相当于最多的事件为每个的WM_MOUSEWHEELWM_MOUSEHWHEEL )。 Once you've finished processing each event, you're supposed to call the CallNextHookEx function , which passes the event information on to the next application in the hook chain.处理完每个事件后,您应该调用CallNextHookEx函数,该函数将事件信息传递给挂钩链中的下一个应用程序。 However, if you want to prevent any other program from getting mouse input information, you can just skip calling that function at the end of your hook procedure.但是,如果您想阻止任何其他程序获取鼠标输入信息,您可以在钩子过程结束时跳过调用该函数。 The "Remarks" section of the above-linked documentation explains it thusly:上述链接文档的“备注”部分对此进行了解释:

Calling CallNextHookEx is optional, but it is highly recommended;调用CallNextHookEx是可选的,但强烈推荐; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result.否则,安装了钩子的其他应用程序将不会收到钩子通知,因此可能会出现不正确的行为。 You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications.除非您绝对需要防止其他应用程序看到通知,否则您应该调用CallNextHookEx

And as it turns out, low-level mouse hooks aren't actually that difficult in C#.事实证明,低级鼠标挂钩在 C# 中实际上并不困难。 I just coded one up myself, actually.实际上,我只是自己编码了一个。 But rather than posting that monstrosity of a library, I'll refer you to the simpler code snippet posted on Stephen Toub's blog , which I've reprinted here with syntax highlighting for convenience:但是,我不会发布库的那个怪物,而是将您推荐给Stephen Toub 的博客上发布的更简单的代码片段,为了方便起见,我在此处重印了语法突出显示:

class InterceptMouse
{
    private static LowLevelMouseProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;

    public static void Main()
    {
        _hookID = SetHook(_proc);
        Application.Run();
        UnhookWindowsHookEx(_hookID);
    }

    private static IntPtr SetHook(LowLevelMouseProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_MOUSE_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(
        int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 &&
            MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
        {
            MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    private const int WH_MOUSE_LL = 14;

    private enum MouseMessages
    {
        WM_LBUTTONDOWN = 0x0201,
        WM_LBUTTONUP = 0x0202,
        WM_MOUSEMOVE = 0x0200,
        WM_MOUSEWHEEL = 0x020A,
        WM_RBUTTONDOWN = 0x0204,
        WM_RBUTTONUP = 0x0205
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct POINT
    {
        public int x;
        public int y;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MSLLHOOKSTRUCT
    {
        public POINT pt;
        public uint mouseData;
        public uint flags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook,
        LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
}

As I explained above, you'll want to modify his HookCallback method not to call CallNextHookEx once you've finished processing the mouse event, but return something like new IntPtr(1) instead.正如我上面所解释的,一旦您完成处理鼠标事件,您将需要修改他的HookCallback方法,不要调用CallNextHookEx ,而是返回类似new IntPtr(1)

EDIT: And yeah, as others mentioned, there are probably other easier, cleaner solutions to this problem.编辑:是的,正如其他人提到的,对于这个问题,可能还有其他更简单、更清洁的解决方案。 Your trackpad drivers are a great place to look for an option like "Ignore accidental mouse input while typing".您的触控板驱动程序是寻找“键入时忽略意外的鼠标输入”等选项的好地方。 If you don't have this option, you're probably using the standard Windows mouse drivers.如果您没有此选项,则您可能正在使用标准的 Windows 鼠标驱动程序。 Try to download the drivers from your trackpad's manufacturer from the laptop manufacturer's website (for what it's worth, most of the non-Apple trackpads I've seen are Synaptics ).尝试从笔记本电脑制造商的网站上从触控板制造商处下载驱动程序(就其价值而言,我见过的大多数非 Apple 触控板都是Synaptics )。

A lot of touchpad drivers have this as an option.许多触摸板驱动程序都将此作为选项。 Ie When you are typing, it ignores touchpad input.即当您打字时,它会忽略触摸板输入。 You could also turn off the tap-click, relying on the actual touchpad buttons to click.您还可以关闭点击点击,依靠实际的触摸板按钮进行点击。

First try the driver's configuration utility, before you try to write your own.首先尝试驱动程序的配置实用程序,然后再尝试编写自己的配置实用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM