要求されたようデュベ私は私の修正版掲載していSiarhei Kuchukの答えを。
私の変更を確認したい場合は、を検索してください// EDT。私はそれのほとんどにコメントしました。
セットアップ
class GlobalKeyboardHookEventArgs : HandledEventArgs
{
    public GlobalKeyboardHook.KeyboardState KeyboardState { get; private set; }
    public GlobalKeyboardHook.LowLevelKeyboardInputEvent KeyboardData { get; private set; }
    public GlobalKeyboardHookEventArgs(
        GlobalKeyboardHook.LowLevelKeyboardInputEvent keyboardData,
        GlobalKeyboardHook.KeyboardState keyboardState)
    {
        KeyboardData = keyboardData;
        KeyboardState = keyboardState;
    }
}
class GlobalKeyboardHook : IDisposable
{
    public event EventHandler<GlobalKeyboardHookEventArgs> KeyboardPressed;
    
    
    
    
    
    
    public GlobalKeyboardHook(Keys[] registeredKeys = null)
    {
        RegisteredKeys = registeredKeys;
        _windowsHookHandle = IntPtr.Zero;
        _user32LibraryHandle = IntPtr.Zero;
        _hookProc = LowLevelKeyboardProc; 
        _user32LibraryHandle = LoadLibrary("User32");
        if (_user32LibraryHandle == IntPtr.Zero)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new Win32Exception(errorCode, $"Failed to load library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
        }
        _windowsHookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, _hookProc, _user32LibraryHandle, 0);
        if (_windowsHookHandle == IntPtr.Zero)
        {
            int errorCode = Marshal.GetLastWin32Error();
            throw new Win32Exception(errorCode, $"Failed to adjust keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
        }
    }
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            
            if (_windowsHookHandle != IntPtr.Zero)
            {
                if (!UnhookWindowsHookEx(_windowsHookHandle))
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    throw new Win32Exception(errorCode, $"Failed to remove keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
                }
                _windowsHookHandle = IntPtr.Zero;
                
                _hookProc -= LowLevelKeyboardProc;
            }
        }
        if (_user32LibraryHandle != IntPtr.Zero)
        {
            if (!FreeLibrary(_user32LibraryHandle)) 
            {
                int errorCode = Marshal.GetLastWin32Error();
                throw new Win32Exception(errorCode, $"Failed to unload library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}.");
            }
            _user32LibraryHandle = IntPtr.Zero;
        }
    }
    ~GlobalKeyboardHook()
    {
        Dispose(false);
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    private IntPtr _windowsHookHandle;
    private IntPtr _user32LibraryHandle;
    private HookProc _hookProc;
    delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary(string lpFileName);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern bool FreeLibrary(IntPtr hModule);
    
    
    
    
    
    
    
    
    
    
    [DllImport("USER32", SetLastError = true)]
    static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
    
    
    
    
    
    [DllImport("USER32", SetLastError = true)]
    public static extern bool UnhookWindowsHookEx(IntPtr hHook);
    
    
    
    
    
    
    
    
    
    [DllImport("USER32", SetLastError = true)]
    static extern IntPtr CallNextHookEx(IntPtr hHook, int code, IntPtr wParam, IntPtr lParam);
    [StructLayout(LayoutKind.Sequential)]
    public struct LowLevelKeyboardInputEvent
    {
        
        
        
        public int VirtualCode;
        
        
        
        
        public Keys Key { get { return (Keys)VirtualCode; } }
        
        
        
        public int HardwareScanCode;
        
        
        
        public int Flags;
        
        
        
        public int TimeStamp;
        
        
        
        public IntPtr AdditionalInformation;
    }
    public const int WH_KEYBOARD_LL = 13;
    
    public enum KeyboardState
    {
        KeyDown = 0x0100,
        KeyUp = 0x0101,
        SysKeyDown = 0x0104,
        SysKeyUp = 0x0105
    }
    
    public static Keys[] RegisteredKeys;
    const int KfAltdown = 0x2000;
    public const int LlkhfAltdown = (KfAltdown >> 8);
    public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
    {
        bool fEatKeyStroke = false;
        var wparamTyped = wParam.ToInt32();
        if (Enum.IsDefined(typeof(KeyboardState), wparamTyped))
        {
            object o = Marshal.PtrToStructure(lParam, typeof(LowLevelKeyboardInputEvent));
            LowLevelKeyboardInputEvent p = (LowLevelKeyboardInputEvent)o;
            var eventArguments = new GlobalKeyboardHookEventArgs(p, (KeyboardState)wparamTyped);
            
            
            
            var key = (Keys)p.VirtualCode;
            if (RegisteredKeys == null || RegisteredKeys.Contains(key))
            {
                EventHandler<GlobalKeyboardHookEventArgs> handler = KeyboardPressed;
                handler?.Invoke(this, eventArguments);
                fEatKeyStroke = eventArguments.Handled;
            }
        }
        return fEatKeyStroke ? (IntPtr)1 : CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam);
    }
}
使用法の 違いはここで見ることができます
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private GlobalKeyboardHook _globalKeyboardHook;
    private void buttonHook_Click(object sender, EventArgs e)
    {
        
        _globalKeyboardHook = new GlobalKeyboardHook(new Keys[] { Keys.A, Keys.B });
        
        _globalKeyboardHook = new GlobalKeyboardHook();
        _globalKeyboardHook.KeyboardPressed += OnKeyPressed;
    }
    private void OnKeyPressed(object sender, GlobalKeyboardHookEventArgs e)
    {
        
        
        if (e.KeyboardState == GlobalKeyboardHook.KeyboardState.KeyDown)
        {
            
            Keys loggedKey = e.KeyboardData.Key;
            int loggedVkCode = e.KeyboardData.VirtualCode;
        }
    }
}
SiarheiKuchukの投稿に感謝します。使用法を単純化したとしても、この初期コードは私にとって非常に役に立ちました。