c# - SetWindowsHookEx 并在窗体卡住时单击最小化/最大化/关闭按钮

标签 c# winforms setwindowshookex

设置全局钩子(Hook) 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);
    }
}

最佳答案

您需要一个 native 模块的句柄。不要指望这将作为全局 Hook 工作:您的 Hook 实现需要执行 .NET JIT!

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

...

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

作为引用,我建议an old question of mine .

关于c# - SetWindowsHookEx 并在窗体卡住时单击最小化/最大化/关闭按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17808074/

相关文章:

c# - 你能构造一个正则表达式来用下划线替换不需要的字符吗?

c# - 如何在运行时使用循环获取属性设置的当前值

C# - 等待 WinForms 消息循环

c# - 在 Windows XP 中使用 SetWindowsHookEx 时出错,但在 Windows 7 中没有

c# - 始终检查是否有 Internet 连接 Xamarin 表单

c# - Lucene.Net QueryParser 抛出 IOException(读取过去的 eof)

c++ - 卸载注入(inject)的 DLL

c#-4.0 - 在32位计算机中为.NET 4.0框架进行编译时,SetWindowsHookEx返回0

c# - 基于原生OpenCV的unity上的Android应用

c# - 在C#.net中查找物理路径