首页 > 后端开发 > C++ > 为什么我的 WPF 全局键盘挂钩 (WH_KEYBOARD_LL) 在快速击键后停止工作?

为什么我的 WPF 全局键盘挂钩 (WH_KEYBOARD_LL) 在快速击键后停止工作?

Barbara Streisand
发布: 2024-12-30 17:50:10
原创
961 人浏览过

Why Does My WPF Global Keyboard Hook (WH_KEYBOARD_LL) Stop Working After Rapid Keystrokes?

在 WPF / C# 中使用全局键盘钩子 (WH_KEYBOARD_LL)

此问题讨论了全局键盘钩子在重复点击后停止工作的问题

问题:

使用 WH_KEYBOARD_LL 实现的全局键盘钩子在经过一段时间的剧烈击键后停止接收按键事件。不会引发任何错误,并且无论在何处击键,都会发生错误。

可疑原因:

线程问题被怀疑是根本问题。

键盘代码示例钩子:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Windows.Input;

namespace MYCOMPANYHERE.WPF.KeyboardHelper
{
    public class KeyboardListener : IDisposable
    {
        private static IntPtr hookId = IntPtr.Zero;

        // Delegate to hook callback (method that will handle key events)
        private static InterceptKeys.LowLevelKeyboardProc hookCallback;

        [MethodImpl(MethodImplOptions.NoInlining)]
        private IntPtr HookCallback(
            int nCode, IntPtr wParam, IntPtr lParam)
        {
            // Handle key events here
            return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
        }

        public event RawKeyEventHandler KeyDown;
        public event RawKeyEventHandler KeyUp;

        public KeyboardListener()
        {
            // Create and assign the hook callback delegate
            hookCallback = (nCode, wParam, lParam) =>
            {
                HookCallbackInner(nCode, wParam, lParam);
                return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
            };

            // Set the hook using the delegate as a parameter
            hookId = InterceptKeys.SetHook(hookCallback);
        }

        // Remaining code not shown for brevity
    }

    internal static class InterceptKeys
    {
        public delegate IntPtr LowLevelKeyboardProc(
            int nCode, IntPtr wParam, IntPtr lParam);

        // Hook-related constants
        public const int WH_KEYBOARD_LL = 13;
        public const int WM_KEYDOWN = 0x0100;
        public const int WM_KEYUP = 0x0101;

        public static IntPtr SetHook(LowLevelKeyboardProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                    GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        // Other code not shown for brevity
    }

    // Event args and handlers for key events
    public delegate void RawKeyEventHandler(object sender, RawKeyEventArgs args);
}
登录后复制

解决方案:

根据答案的建议,回调方法的委托是内联创建的,这可能导致它被垃圾收集。为了使委托保持活动状态并防止出现此问题,有必要将委托分配给成员变量。

// Assign the hook callback delegate to a member variable
private InterceptKeys.LowLevelKeyboardProc hookCallback;
登录后复制

通过这样做,委托将在 KeyboardListener 对象的生命周期内保持活动状态。这应该可以解决键盘挂钩在一段时间后停止工作的问题。

以上是为什么我的 WPF 全局键盘挂钩 (WH_KEYBOARD_LL) 在快速击键后停止工作?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板