2018-05-05 01:44:58

Hello everyone,
In this post i am sharing my personal global keyboard hook.

What is a global keyboard hook?
A global keyboard hook enables you to capture any key press.
No matter if your application is in the front or back.
Thus the meaning global.

I have simplified the class for easy usage.
And made the code as short as possible.
Thus i do not use exception handling and so on.

Right so how to use this code?
There are 3 options you can use.

1: KeyBoardHook.HandleCallBack = YourVoidName;
This is the void where you can interact with the key presses.
The void should use  key press event keys.
The namespace for keys is in System.Windows.Forms.

For example,
internal  void YourVoidName(Keys PressedKey)
{
//Do whatever you want with the keys send.
}

2: KeyBoardHook.Start();
This will start the hook.

3: KeyBoardHook.Stop();
This will disable the keyboard hook.

So with the above simple functions you can use a global keyboard hook in your application.
Below is the class for keyboard hook.
Enjoy.

#region Imports
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
#endregion
class KeyBoardHook
{
    #region DLLImports
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, KeyBoardProcess lpfn, IntPtr hMod, uint dwThreadId);
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    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);
    #endregion
    #region Delegates
    private delegate IntPtr KeyBoardProcess(int nCode, IntPtr wParam, IntPtr lParam);
    internal delegate    void  MainCallBack(System.Windows.Forms.Keys e);   
    #endregion
        #region Fields
    private static KeyBoardProcess KeyBoardCallBack = HookCallback;
    internal static MainCallBack CallBackHandler = null;
    private static IntPtr KeyBoardHookID = IntPtr.Zero;
    private const int WinHookL = 13;
    private const int WinHookKeyDown = 0x0100;
                #endregion
    #region Start Hook
    internal static void Start()
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
            KeyBoardHookID = SetWindowsHookEx(WinHookL, KeyBoardCallBack, GetModuleHandle(curModule.ModuleName), 0);
        }
    #endregion
    #region Stop Hook
    internal static void Stop()
    {
        UnhookWindowsHookEx(KeyBoardHookID);
    }
    #endregion
    #region CallBack
    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && wParam == (IntPtr)WinHookKeyDown)
        CallBackHandler((System.Windows.Forms.Keys)Marshal.ReadInt32(lParam));
        return CallNextHookEx(KeyBoardHookID, nCode, wParam, lParam);
    }
    #endregion
}

Put your coding where your mouth is.

2018-05-05 15:04:39

This is cool, but it has the potential for issues with screen readers, I don't know exactly how this would behave, but the concept is a bit worrisome. Let's say that when this is active, even if your app is minimized, its still taking input, this might mean that you cant stop it if the app goes into a freeze or hang and doesn't respond, it might even make you not be able to shut down your computer or something, so while one app hanging wouldn't normally be a big deal, if the person who uses this class writes one that occasionally has a problem, I wonder what would happen. At the worst case scenario, they'd have to force shut down which is something I try to avoid doing. I will fight with a locked system for a long time just to avoid that possibility, and most of the time I come out on top, especially as windows gets better about dealing with that type of thing. also, might it stop your screen reader from accepting commands because this program intercepts them first, if so, that's very bad. It means that even if something does come up, we're essentially locked out of our system. Asking this because that code is a bit beyond my abilities of C# at the moment.

Facts with Tom MacDonald, Adam Calhoun, and Dax
End racism
End division
Become united

2018-05-05 22:35:09 (edited by Ethin 2018-05-05 22:35:32)

I also suspect that AV programs will search for code that does what this does and prevent it from running. This "global key hook" is exactly how key loggers work, and could be used, very easily, with or without knowing, for malicious purposes.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github