代码之家  ›  专栏  ›  技术社区  ›  Itay Karo

使用WH\u MOUSE设置WindowsHookex会使鼠标减速几秒钟

  •  3
  • Itay Karo  · 技术社区  · 14 年前

    我使用以下代码来获取当前进程上的鼠标消息。

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

    由于某些原因,当此代码运行时,鼠标会慢几秒钟,然后恢复正常。

    有什么想法吗?

    编辑钩子方法

    private static IntPtr mouseEvent(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
        {
            MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));     
            LastLeftClick = new ClickInfo { Time = DateTime.Now, X = hookStruct.pt.x, Y = hookStruct.pt.y };
        }
        return CallNextHookEx(hookID, nCode, wParam, lParam);
    }
    
    public class ClickInfo
    {
        public int X { get; set; }
        public int Y { get; set; }
        public DateTime Time { get; set; }
    }
    
    6 回复  |  直到 14 年前
        2
  •  3
  •   Bobrovsky Jesse DeGuire    14 年前

    有趣的是,在我写的时候,使用WH\u MOUSE \u LL的代码做得很好(没有鼠标冻结等),似乎Windows的一些安全更新改变了鼠标挂钩的行为,以前的好代码变成了一个问题。

        3
  •  3
  •   Romout    6 年前

    我很抱歉在这么长时间之后继续跟进,但是我已经通过生成一个单独的线程来解决了这个问题,该线程处理钩子(我没有向代码中添加所有内容,因为它也会翻译消息,但主要思想应该很清楚):

        public Form1()
        {
            InitializeComponent();
    
            Thread thread = new Thread(HookThread);
            thread.IsBackground = true;
            thread.Start();
        }
    
        private void HookThread()
        {
            _hookControl = new Control();
            IntPtr handle = _hookControl.Handle;
    
            _hookProc = new HookProc(HookFunction);
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                _hook = SetWindowsHookEx(HookType.WH_MOUSE_LL, _hookProc, GetModuleHandle(curModule.ModuleName), 0);// (uint)AppDomain.GetCurrentThreadId());
            }
    
            Application.Run();
    
            UnhookWindowsHookEx(_hook);
            _hook = IntPtr.Zero;
        }
    
        private IntPtr HookFunction(int code, IntPtr wParam, IntPtr lParam)
        {
            if (code < 0)
            {
                //you need to call CallNextHookEx without further processing
                //and return the value returned by CallNextHookEx
                return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
            }
    
            int msg = wParam.ToInt32();
            string messages = string.Join(", ", _messageMapping.Where(t => t.Item1 == msg).Select(t => t.Item2));
            if (string.IsNullOrWhiteSpace(messages))
                messages = msg.ToString();
            Trace.WriteLine($"Messages: { messages }");
    
            //return the value returned by CallNextHookEx
            return CallNextHookEx(IntPtr.Zero, code, wParam, lParam);
        }
    

    通过在创建的\u hookControl上调用BeginInvoke,可以从任何其他线程终止线程:

            _hookControl.BeginInvoke(((Action)(() => Application.ExitThread())));
    
        4
  •  2
  •   David Ewen    13 年前

    通过设置一个低级别的钩子,鼠标的响应性现在取决于您的主线程是否有响应,一个常见的错误是在启动过程的早期设置钩子。

    套钩
    龙润宁工艺
    老鼠在这里才有反应

    在启动过程中,最好将钩子分派到线程上,以便在启动过程结束时发生。 Dispatcher.CurrentDispatcher.BeginInvoke(new Action(SetHook));

    调度钩
    龙润宁工艺
    SetHook(回调)
    老鼠变得有反应

    这在应用程序中仍然存在管理问题,以确保主线程不会执行任何长时间运行的进程,因为这也会锁定鼠标。这可以通过设置钩子然后执行 Thread.Sleep 在主线程上。

        5
  •  1
  •   Martin Blore    13 年前

    当你收到钩子事件时,关掉书,然后做你的工作,如果真的还需要,把钩子放回去。

    这将阻止鼠标滞后。

        6
  •  1
  •   user229044 Sam Hogarth    13 年前

    你的钩子程序是昂贵的;你只需要弄清楚为什么以及如何修复它。

    如果您将代码更改为尽可能多地在此线程之外进行处理,问题应该会消失。作为一个C++开发者,我甚至担心Marshal.PtrToStructure,因为低级钩子非常敏感,我不能说我的头可以保证这个操作很便宜,不会损害鼠标移动。