2

设置全局挂钩 SetWindowsHookEx 标准表单的按钮后,工作异常。例如,如果我单击关闭按钮,则鼠标会冻结 5-10 秒并形成。

我找到了具有相同问题的主题C# 低级鼠标钩子和表单事件处理 ,但只有一个答案。而且我不喜欢那个解决方案,因为它需要每次 Hook,当表单停用时,以及 UnHook,当程序激活时......

有没有更好的方法来解决这个问题?

已编辑

这是我的代码:

using System.Windows.Forms;
using Gma.UserActivityMonitor;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace WinFormsHook
{
    public partial class Form1 : Form
    {
        int s_MouseHookHandle;

        public Form1()
        {
            InitializeComponent();
            IntPtr hInst = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
            s_MouseHookHandle = SetWindowsHookEx( WH_MOUSE_LL, MouseHookProc, hInst, 0);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnhookWindowsHookEx(s_MouseHookHandle);
        }

        private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                Debug.WriteLine(wParam);
                if (wParam == WM_LBUTTONDOWN)
                {
                    Action action = () => this.Text += ".";
                    this.Invoke(action);
                }
            }

            //call next hook
            return CallNextHookEx(s_MouseHookHandle, nCode, wParam, lParam);
        }

        private const int WH_MOUSE_LL = 14;
        private const int WM_LBUTTONDOWN = 0x201;

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

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string name);

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

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
        private static extern int UnhookWindowsHookEx(int idHook);

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        private static extern int CallNextHookEx( int idHook, int nCode, int wParam, IntPtr lParam);
    }
}
4

1 回答 1

2

您需要本机模块的句柄。不要期望这将作为一个全局钩子工作:您的钩子实现需要执行 .NET JIT!

事实上,每个非托管进程都将无法执行您的处理程序!我想这是系统阻塞的原因。

...

重新阅读您的代码后,您似乎不需要全局挂钩(“this”在其他进程中没有意义)。因此,SetWindowsHookEx 的 RTFM 并适当地设置了最后一个参数。

作为参考,我建议我的一个老问题

于 2013-07-23T14:55:57.567 回答