Capturing keystrokes without focus

10,767

Low-Level windows hooks is one way to do it. Here is one article and here is a little more info from MSDN.

This is a partial view of what that code can look like:

    private IntPtr LowLevelKeyboardHook(int nCode, WindowsMessages wParam, [In] KBDLLHOOKSTRUCT lParam)
    {
        bool callNext = true;

        bool isKeyDown = (wParam == WindowsMessages.KEYDOWN || wParam == WindowsMessages.SYSKEYDOWN);
        bool isKeyUp = (wParam == WindowsMessages.KEYUP || wParam == WindowsMessages.SYSKEYUP);

        if ((nCode >= 0) && (isKeyDown || isKeyUp))
        {
            // the virtual key codes and the winforms Keys have the same enumeration
            // so we can freely cast back and forth between them
            Keys key = (Keys)lParam.vkCode;

            // Do your other processing here...
        }

        // if any handler returned false, trap the message
        return (callNext) ? User32.CallNextHookEx(_mainHook, nCode, wParam, lParam) : _nullNext;
    }


    /// <summary>
    /// Registers the user's LowLevelKeyboardProc with the system in order to
    /// intercept any keyboard events before processed in the regular fashion.
    /// This can be used to log all keyboard events or ignore them.
    /// </summary>
    /// <param name="hook">Callback function to call whenever a keyboard event occurs.</param>
    /// <returns>The IntPtr assigned by the Windows's sytem that defines the callback.</returns>
    private IntPtr RegisterLowLevelHook(LowLevelKeyboardProc hook)
    {
        IntPtr handle = IntPtr.Zero;

        using (Process currentProcess = Process.GetCurrentProcess())
        using (ProcessModule currentModule = currentProcess.MainModule)
        {
            IntPtr module = Kernel32.GetModuleHandle(currentModule.ModuleName);
            handle = User32.SetWindowsHookEx(HookType.KEYBOARD_LL, hook, module, 0);
        }

        return handle;
    }

    /// <summary>
    /// Unregisters a previously registered callback from the low-level chain.
    /// </summary>
    /// <param name="hook">IntPtr previously assigned to the low-level chain.
    /// Users should have stored the value given by 
    /// <see cref="Drs.Interop.Win32.LowLevelKeyboard.RegisterLowLevelHook"/>,
    /// and use that value as the parameter into this function.</param>
    /// <returns>True if the hook was removed, false otherwise.</returns>
    private bool UnregisterLowLevelHook(IntPtr hook)
    {
        return User32.UnhookWindowsHookEx(hook);
    }

Just implement all the P/Invoke declarations needed, and it should work. I use this approach in my application and it works fine.

Share:
10,767
kresjer
Author by

kresjer

Updated on July 20, 2022

Comments

  • kresjer
    kresjer almost 2 years

    E.g. with winamp (on Windows at least), you can play a game fullscreen with winamp in the background, and use the media buttons* to control the sound. Winamp doesn't need to get focus, allowing the game to continue fullscreen.

    I'd prefer to write this in Java but that probably isn't going to work (capturing keystrokes without focus is already difficult in Java afaik), so any C# solution is also fine.

    So the basic question is: how to capture keystrokes without focus?

    *) I believe the 'back/forward/stop/mail/search/favorites/web/home' buttons are called media buttons, but a better name would be welcome :).

    • Luc
      Luc over 10 years
      I call them media buttons or media keys too, don't know any better name.
  • Uri Abramson
    Uri Abramson almost 11 years
    Those types are not recognized on my application and it doesnt compile (WindowsMessages, User32 etc...) what did you do to make it work? do you have this code online anywhere by any chance?
  • Erich Mirabal
    Erich Mirabal almost 11 years
    No, those are the declarations that you would need to declare. I don't have that code online, but you can create simple stubs using P/Invoke signatures from pinvoke.net.
  • Taha Rehman Siddiqui
    Taha Rehman Siddiqui about 6 years
    what is the _nullNext variable?