Skip to content

Instantly share code, notes, and snippets.

@downloadpizza
Created April 25, 2024 16:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save downloadpizza/d082abf86d80cb71280ff37e61515793 to your computer and use it in GitHub Desktop.
Save downloadpizza/d082abf86d80cb71280ff37e61515793 to your computer and use it in GitHub Desktop.
A Global keyboard hook simplified for use outside of WinForms (still requires a Windows window of some sorts though)
using System.Runtime.InteropServices;
using SFML.Window;
namespace KH
{
/*
**IMPORTANT NOTE**
this only works if called in a thread which also receives window updates
(for example if you call SFMLs RenderWindow.DispatchEvent's function,
or in any windows forms or WPF application where you use the same thread)
*/
public partial class KeyboardHook
{
public KeyboardHook() {
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, _proc, IntPtr.Zero, 0);
}
[DllImport("user32.dll")]
static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);
[DllImport("user32.dll")]
static extern bool UnhookWindowsHookEx(IntPtr hInstance);
[DllImport("user32.dll")]
static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
const int WH_KEYBOARD_LL = 13;
const int WM_KEYDOWN = 0x100;
private LowLevelKeyboardProc _proc = hookProc;
private static IntPtr hhook = IntPtr.Zero;
public static void Unhook()
{
UnhookWindowsHookEx(hhook);
}
~KeyboardHook() {
Unhook();
}
static HashSet<Keyboard.Key> pressedKeys = new HashSet<Keyboard.Key>();
public static IntPtr hookProc(int code, IntPtr wParam, IntPtr lParam)
{
if (code >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
var kbhs = Marshal.PtrToStructure<KbHookStruct>(lParam);
Console.WriteLine(kbhs.vkCode);
}
return CallNextHookEx(hhook, code, (int)wParam, lParam);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
struct KbHookStruct {
public int vkCode;
public int scanCode;
public int flags;
public int time;
public IntPtr dwExtraInfo;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment