关于原理请参考我的另一篇文章 mouse Hook.
新建类:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace TestHook { class KeyboardHook { int hHook; public bool IsHooking = false; Win32Api.HookProc KeyboardHookDelegate; public event KeyEventHandler OnKeyDownEvent; public event KeyEventHandler OnKeyUpEvent; public event KeyPressEventHandler OnKeyPressEvent; //Store the control key is pressed, the key used to generate specific private List<Keys> preKeysList = new List<Keys>(); public KeyboardHook() { } ~KeyboardHook() { if (IsHooking) { Win32Api.UnhookWindowsHookEx(hHook); } } public void UnHook() { if (IsHooking) { if (Win32Api.UnhookWindowsHookEx(hHook)) { IsHooking = false; } } } public bool SetHook() { KeyboardHookDelegate = new Win32Api.HookProc(KeyboardHookProc); Process cProcess = Process.GetCurrentProcess(); ProcessModule cModule = cProcess.MainModule; var mh = Win32Api.GetModuleHandle(cModule.ModuleName); hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0); if (hHook == 0) return false; IsHooking = true; return true; } private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { //If the message was discarded (nCode<0) or if no event handler is not triggered event if ((nCode >= 0) && (OnKeyDownEvent != null || OnKeyUpEvent != null || OnKeyPressEvent != null)) { Win32Api.KeyboardHookStruct KeyDataFromHook = (Win32Api.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.KeyboardHookStruct)); Keys keyData = (Keys)KeyDataFromHook.vkCode; //Control keypressed //Get key value int acctualValue = -1; byte[] keyState = new byte[256]; Win32Api.GetKeyboardState(keyState); byte[] inBuffer = new byte[2]; if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1) { acctualValue = inBuffer[0]; } if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN)) { if (IsFounctionKeys(keyData) && preKeysList.IndexOf(keyData) == -1) { preKeysList.Add(keyData); } } // WM_KEYDOWN and WM_SYSKEYDOWN message if (OnKeyDownEvent != null && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN)) { KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData)); Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags); OnKeyDownEvent(acctualValue, e); } //WM_KEYDOWN message ,lead to OnKeyPressEvent Remove this founction for now //If pressed key ,then record it if (OnKeyPressEvent != null && wParam == Win32Api.WM_KEYDOWN) { if (Win32Api.ToAscii(KeyDataFromHook.vkCode, KeyDataFromHook.scanCode, keyState, inBuffer, KeyDataFromHook.flags) == 1) { KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]); OnKeyPressEvent(this, e); } } //control keyup if ((OnKeyDownEvent != null || OnKeyPressEvent != null) && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP)) { if (IsFounctionKeys(keyData)) { for (int i = preKeysList.Count - 1; i >= 0; i--) { if (preKeysList[i] == keyData) { preKeysList.RemoveAt(i); } } } } //WM_KEYUP and WM_SYSKEYUP message,lead to OnKeyUpEvent events if (OnKeyUpEvent != null && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP)) { KeyEventArgs e = new KeyEventArgs(GetDownKeys(keyData)); OnKeyUpEvent(acctualValue, e); } } return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam); } private Boolean IsFounctionKeys(Keys key) { if (key == Keys.LControlKey || key == Keys.RControlKey || key == Keys.LMenu || key == Keys.RMenu || key == Keys.LShiftKey || key == Keys.RShiftKey /* || key == Keys.LWin ||key == Keys.RWin*/) { return true; } return false; } //According to the control key has been pressed to generate key /// <summary> /// Juage the char is sprintable /// </summary> /// <returns></returns> private bool IsSprint(char input) { if (input > 0x1f && input != 0x7f) { return true; } return false; } private Keys GetDownKeys(Keys key) { Keys rtnKey = Keys.None; foreach (Keys i in preKeysList) { if (i == Keys.LControlKey || i == Keys.RControlKey) { rtnKey = rtnKey | Keys.Control; } if (i == Keys.LMenu || i == Keys.RMenu) { rtnKey = rtnKey | Keys.Alt; } if (i == Keys.LShiftKey || i == Keys.RShiftKey) { rtnKey = rtnKey | Keys.Shift; } } return rtnKey | key; } } }建类:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace TestHook { class Win32Api { #region Normal Data Struct public const int WM_KEYDOWN = 0x100; public const int WM_KEYUP = 0x101; public const int WM_SYSKEYDOWN = 0x104; public const int WM_SYSKEYUP = 0x105; public const int WH_KEYBOARD_LL = 13; public const int WH_MOUSE_LL = 14; public const int WM_MOUSEMOVE = 0x200; public const int WM_LBUTTONDOWN = 0x201; public const int WM_RBUTTONDOWN = 0x204; public const int WM_MBUTTONDOWN = 0x207; public const int WM_LBUTTONUP = 0x202; public const int WM_RBUTTONUP = 0x205; public const int WM_MBUTTONUP = 0x208; public const int WM_LBUTTONDBLCLK = 0x203; public const int WM_RBUTTONDBLCLK = 0x206; public const int WM_MBUTTONDBLCLK = 0x209; //define keyboard meesage struct [StructLayout(LayoutKind.Sequential)] public class KeyboardHookStruct { //Represents a virtual keyboard codes between 1 and 254 public int vkCode; //Indicate a hardware scan code public int scanCode; public int flags; public int time; public int dwExtraInfo; } //Declares a Point type is marshaled [StructLayout(LayoutKind.Sequential)] public class POINT { public int x; public int y; } //Declaring a mouse hook marshaled structure types [StructLayout(LayoutKind.Sequential)] public class MouseHookStruct { public POINT pt; public int hWnd; public int wHitTestCode; public int dwExtraInfo; } #endregion #region Api public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); //install hook [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); //uninstall hook [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern bool UnhookWindowsHookEx(int idHook); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam); [DllImport("user32")] public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[] lpwTransKey, int fuState); [DllImport("user32")] public static extern int GetKeyboardState(byte[] pbKeyState); [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID); #endregion #region Copied from Prism Management Studio Common [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] public static extern IntPtr GetForegroundWindow(); #endregion #region GetMessageExtraInfo [DllImport("user32.dll", EntryPoint = "GetMessageExtraInfo", SetLastError = true)] public static extern IntPtr GetMessageExtraInfo(); #endregion #region MapVirtualKey [DllImport("user32.dll")] public static extern UInt32 MapVirtualKey(UInt32 uCode, UInt32 uMapType); #endregion } }最后在winform里面注册事件并设置钩子。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace TestHook { public partial class Form2 : Form { public Form2() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls = false;//不检查线程之间的冲突 } TestKeyBorddelegate keyBoardDelegate; KeyboardHook keyboardHook = new KeyboardHook(); private void btnStartKeyBoard_Click(object sender, EventArgs e) { keyboardHook.OnKeyDownEvent += KeyDown;//注册响应方法 if (!keyboardHook.SetHook())//设置不成功 { keyboardHook.OnKeyDownEvent -= KeyDown; } } //方法,键盘按下的方法 private void KeyDown(object sender, KeyEventArgs e) { keyBoardDelegate = (s) => { this.Text = s; }; keyBoardDelegate.BeginInvoke(e.KeyValue.ToString(),null,null);//开辟新线程否则可能造成form的卡顿。 } private void btnCancel_Click(object sender, EventArgs e) { keyboardHook.OnKeyDownEvent -= KeyDown; keyboardHook.UnHook(); } } public delegate void TestKeyBorddelegate(string s); }