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

Posted

技术标签:

【中文标题】SetWindowsHookEx 并单击表单冻结时的最小化/最大化/关闭按钮【英文标题】:SetWindowsHookEx and clicking minimize/maximize/close buttons on form freezing 【发布时间】:2013-07-23 10:50:15 【问题描述】:

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

【问题讨论】:

这是某种全局钩子吗? @KingKing,是的。这是 MouseDoubleClick 事件的钩子 用户双击后你会做什么?需要用钩子吗?我要问的是你为什么要这样做,因为可能还有其他方法。 @TheKingDave,在大多数程序中,双击文本会导致选择光标下的单词。我需要在双击后立即将突出显示的单词添加到我的程序中,我可以继续使用它。出于这个原因,我需要按照双击,诉诸SetWindowsHookEx ... 【参考方案1】:

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

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

...

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

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

【讨论】:

以上是关于SetWindowsHookEx 并单击表单冻结时的最小化/最大化/关闭按钮的主要内容,如果未能解决你的问题,请参考以下文章

SetWindowsHookEx WH_MOUSE 在 Win7 中的断点处冻结

在 Project Navigator 中单击 JSON 文件时 Xcode 冻结(并崩溃)

QT QThread::isrunning 冻结程序在 Pi

单击嵌入式网络中的文本框时冻结的网络视图 - Android 4.3

如何在子表单打开时冻结父表单

视频帧在下一帧 HTML5 视频上冻结