SetWindowsHookEx并单击窗体冻结时的最小化/最大化/关闭按钮

时间:2013-07-23 10:50:15

标签: c# winforms setwindowshookex

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

我找到了同样问题的主题C# low level mouse hook and form event handling 但只有一个答案。而且我不喜欢这个解决方案,因为它需要每次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);
    }
}

1 个答案:

答案 0 :(得分:1)

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

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

...

重新阅读你的代码后,似乎你不想要一个全局钩子('this'在其他进程中没有意义)。所以,SetWindowsHookEx的RTFM并适当地设置最后一个参数。

作为参考,我建议an old question of mine