Skip to content

Instantly share code, notes, and snippets.

@AonaSuzutsuki
Last active March 5, 2022 00:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AonaSuzutsuki/0a287e1addcf7e1874c8150d1a7a8bde to your computer and use it in GitHub Desktop.
Save AonaSuzutsuki/0a287e1addcf7e1874c8150d1a7a8bde to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
namespace ConsoleApp1
{
abstract class AbstractInterceptKeyboard
{
#region Win32 Constants
protected const int WH_KEYBOARD_LL = 0x000D;
protected const int WM_KEYDOWN = 0x0100;
protected const int WM_KEYUP = 0x0101;
protected const int WM_SYSKEYDOWN = 0x0104;
protected const int WM_SYSKEYUP = 0x0105;
#endregion
#region Win32API Structures
[StructLayout(LayoutKind.Sequential)]
public class KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public KBDLLHOOKSTRUCTFlags flags;
public uint time;
public UIntPtr dwExtraInfo;
}
[Flags]
public enum KBDLLHOOKSTRUCTFlags : uint
{
KEYEVENTF_EXTENDEDKEY = 0x0001,
KEYEVENTF_KEYUP = 0x0002,
KEYEVENTF_SCANCODE = 0x0008,
KEYEVENTF_UNICODE = 0x0004,
}
#endregion
#region Win32 Methods
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc 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);
#endregion
#region Delegate
private delegate IntPtr KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
#endregion
#region Fields
private KeyboardProc proc;
private IntPtr hookId = IntPtr.Zero;
#endregion
public void Hook()
{
if (hookId == IntPtr.Zero)
{
proc = HookProcedure;
using (var curProcess = Process.GetCurrentProcess())
{
using (ProcessModule curModule = curProcess.MainModule)
{
hookId = SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
}
}
public void UnHook()
{
UnhookWindowsHookEx(hookId);
hookId = IntPtr.Zero;
}
public virtual IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam)
{
return CallNextHookEx(hookId, nCode, wParam, lParam);
}
}
class InterceptKeyboard : AbstractInterceptKeyboard
{
#region InputEvent
public class OriginalKeyEventArg : EventArgs
{
public int KeyCode { get; }
public OriginalKeyEventArg(int keyCode)
{
KeyCode = keyCode;
}
}
public delegate void KeyEventHandler(object sender, OriginalKeyEventArg e);
public event KeyEventHandler KeyDownEvent;
public event KeyEventHandler KeyUpEvent;
protected void OnKeyDownEvent(int keyCode)
{
KeyDownEvent?.Invoke(this, new OriginalKeyEventArg(keyCode));
}
protected void OnKeyUpEvent(int keyCode)
{
KeyUpEvent?.Invoke(this, new OriginalKeyEventArg(keyCode));
}
#endregion
public override IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_SYSKEYDOWN))
{
var kb = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
var vkCode = (int)kb.vkCode;
OnKeyDownEvent(vkCode);
}
else if (nCode >= 0 && (wParam == (IntPtr)WM_KEYUP || wParam == (IntPtr)WM_SYSKEYUP))
{
var kb = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
var vkCode = (int)kb.vkCode;
OnKeyUpEvent(vkCode);
}
return base.HookProcedure(nCode, wParam, lParam);
}
}
class Program
{
[STAThread]
static void Main(string[] args)
{
var interceptKeyboard = new InterceptKeyboard();
interceptKeyboard.KeyDownEvent += InterceptKeyboard_KeyDownEvent;
interceptKeyboard.KeyUpEvent += InterceptKeyboard_KeyUpEvent;
interceptKeyboard.Hook();
var application = new Application();
application.Run(new Window()
{
Width = 300,
Height = 300,
});
interceptKeyboard.UnHook();
}
private static void InterceptKeyboard_KeyUpEvent(object sender, InterceptKeyboard.OriginalKeyEventArg e)
{
Console.WriteLine("Keyup KeyCode {0}", e.KeyCode);
}
private static void InterceptKeyboard_KeyDownEvent(object sender, InterceptKeyboard.OriginalKeyEventArg e)
{
Console.WriteLine("Keydown KeyCode {0}", e.KeyCode);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment