Skip to main content

Low Level Keyboard Listener in C#

Modified version of Low Level Keyboard Listener from this article: https://www.dylansweb.com/2014/10/low-level-global-keyboard-hook-sink-in-c-net/
I added OnKeyUp listener and rename the OnKeyPressed listener into OnKeyDown
LowLevelKeyboardListener.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Input;

namespace MyNamespace
{
    public class LowLevelKeyboardListener
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_KEYUP = 0x0101;
        private const int WM_SYSKEYDOWN = 0x0104;
        private const int WM_SYSKEYUP = 0x0105;

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        public event EventHandler<KeyDownArgs> OnKeyDown;
        public event EventHandler<KeyUpArgs> OnKeyUp;

        private LowLevelKeyboardProc _proc;
        private IntPtr _hookID = IntPtr.Zero;

        public LowLevelKeyboardListener()
        {
            _proc = HookCallback;
        }

        public void HookKeyboard()
        {
            _hookID = SetHook(_proc);
        }

        public void UnHookKeyboard()
        {
            UnhookWindowsHookEx(_hookID);
        }

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

        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);

                if (OnKeyDown != null) { OnKeyDown(this, new KeyDownArgs(KeyInterop.KeyFromVirtualKey(vkCode))); }
            }

            //Could be an else if, idk never tried it, lol
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP)
            {
                int vkCode = Marshal.ReadInt32(lParam);

                if (OnKeyUp != null) { OnKeyUp(this, new KeyUpArgs(KeyInterop.KeyFromVirtualKey(vkCode))); }
            }

            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    }

    public class KeyDownArgs : EventArgs
    {
        public Key KeyDown { get; private set; }

        public KeyDownArgs(Key key)
        {
            KeyDown = key;
        }
    }

    public class KeyUpArgs : EventArgs
    {
        public Key KeyUp { get; private set; }

        public KeyUpArgs(Key key)
        {
            KeyUp = key;
        }
    }
}
Form1.cs
using System;
using System.Windows.Forms;

namespace MyNamespace
{
    public partial class Form1 : Form
    {
        private LowLevelKeyboardListener _listener;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _listener = new LowLevelKeyboardListener();
            _listener.OnKeyDown += _listener_OnKeyDown;
            _listener.OnKeyUp += _listener_OnKeyUp;

            _listener.HookKeyboard();
        }

        private void _listener_OnKeyDown(object sender, KeyDownArgs e)
        {
            Console.WriteLine("Key Down: " + e.KeyDown);
        }

        private void _listener_OnKeyUp(object sender, KeyUpArgs e)
        {
            Console.WriteLine("Key Up: " + e.KeyUp);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _listener.UnHookKeyboard();
        }
    }
}

Comments

Popular posts from this blog

AniList Custom Filter

Some custom filters for the browse anime feature. (If you want the manga version edit it yourself, I'm lazy...)

osu!play

DOWNLOAD The improved version of GH!mania.