转载 https://www.cnblogs.com/zhaoyuncai/p/7684958.html
稍微有些改动 这里只添加 按键按下
一.为什么需要全局键盘监听?
在某些情况下应用程序需要实现快捷键执行特定功能,例如大家熟知的QQ截图功能Ctrl+Alt+A快捷键,只要QQ程序在运行(无论是拥有焦点还是处于后台运行状态),都可以按下快捷键使用此功能…
这个时候在程序中添加键盘监听肯定不能满足需求了,当用户焦点不在App上时(如最小化,或者用户在处理其它事物等等)键盘监听就失效了
二.怎样才能实现全局键盘监听?
这里需要用到Windows API,源码如下:(可以作为一个工具类[KeyboardHook.cs]收藏起来)
1 using System; 2 using System.Text; 3 using System.Runtime.InteropServices; 4 using System.Reflection; 5 using System.Windows.Forms; 6 7 namespace BAMdp.MouseKeyboardLibrary 8 { 9 public abstract class GlobalHook 10 { 11 #region Windows API Code 12 13 [StructLayout(LayoutKind.Sequential)] 14 protected class POINT 15 { 16 public int x; 17 public int y; 18 } 19 20 [StructLayout(LayoutKind.Sequential)] 21 protected class MouseHookStruct 22 { 23 public POINT pt; 24 public int hwnd; 25 public int wHitTestCode; 26 public int dwExtraInfo; 27 } 28 29 [StructLayout(LayoutKind.Sequential)] 30 protected class MouseLLHookStruct 31 { 32 public POINT pt; 33 public int mouseData; 34 public int flags; 35 public int time; 36 public int dwExtraInfo; 37 } 38 39 [StructLayout(LayoutKind.Sequential)] 40 protected class KeyboardHookStruct 41 { 42 public int vkCode; 43 public int scanCode; 44 public int flags; 45 public int time; 46 public int dwExtraInfo; 47 } 48 49 [DllImport("user32.dll", CharSet = CharSet.Auto, 50 CallingConvention = CallingConvention.StdCall, SetLastError = true)] 51 protected static extern int SetWindowsHookEx( 52 int idHook, 53 HookProc lpfn, 54 IntPtr hMod, 55 int dwThreadId); 56 57 [DllImport("user32.dll", CharSet = CharSet.Auto, 58 CallingConvention = CallingConvention.StdCall, SetLastError = true)] 59 protected static extern int UnhookWindowsHookEx(int idHook); 60 61 62 [DllImport("user32.dll", CharSet = CharSet.Auto, 63 CallingConvention = CallingConvention.StdCall)] 64 protected static extern int CallNextHookEx( 65 int idHook, 66 int nCode, 67 int wParam, 68 IntPtr lParam); 69 70 [DllImport("user32")] 71 protected static extern int ToAscii( 72 int uVirtKey, 73 int uScanCode, 74 byte[] lpbKeyState, 75 byte[] lpwTransKey, 76 int fuState); 77 78 [DllImport("user32")] 79 protected static extern int GetKeyboardState(byte[] pbKeyState); 80 81 [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 82 protected static extern short GetKeyState(int vKey); 83 84 [DllImport("kernel32.dll")] 85 private static extern IntPtr GetModuleHandle(string name); 86 87 protected delegate int HookProc(int nCode, int wParam, IntPtr lParam); 88 89 protected const int WH_MOUSE_LL = 14; 90 protected const int WH_KEYBOARD_LL = 13; 91 92 protected const int WH_MOUSE = 7; 93 protected const int WH_KEYBOARD = 2; 94 protected const int WM_MOUSEMOVE = 0x200; 95 protected const int WM_LBUTTONDOWN = 0x201; 96 protected const int WM_RBUTTONDOWN = 0x204; 97 protected const int WM_MBUTTONDOWN = 0x207; 98 protected const int WM_LBUTTONUP = 0x202; 99 protected const int WM_RBUTTONUP = 0x205; 100 protected const int WM_MBUTTONUP = 0x208; 101 protected const int WM_LBUTTONDBLCLK = 0x203; 102 protected const int WM_RBUTTONDBLCLK = 0x206; 103 protected const int WM_MBUTTONDBLCLK = 0x209; 104 protected const int WM_MOUSEWHEEL = 0x020A; 105 protected const int WM_KEYDOWN = 0x100; 106 protected const int WM_KEYUP = 0x101; 107 protected const int WM_SYSKEYDOWN = 0x104; 108 protected const int WM_SYSKEYUP = 0x105; 109 110 protected const byte VK_SHIFT = 0x10; 111 protected const byte VK_CAPITAL = 0x14; 112 protected const byte VK_NUMLOCK = 0x90; 113 114 protected const byte VK_LSHIFT = 0xA0; 115 protected const byte VK_RSHIFT = 0xA1; 116 protected const byte VK_LCONTROL = 0xA2; 117 protected const byte VK_RCONTROL = 0x3; 118 protected const byte VK_LALT = 0xA4; 119 protected const byte VK_RALT = 0xA5; 120 121 protected const byte LLKHF_ALTDOWN = 0x20; 122 123 #endregion 124 125 #region Private Variables 126 127 protected int _hookType; 128 protected int _handleToHook; 129 protected bool _isStarted; 130 protected HookProc _hookCallback; 131 132 #endregion 133 134 #region Properties 135 136 public bool IsStarted 137 { 138 get 139 { 140 return _isStarted; 141 } 142 } 143 144 #endregion 145 146 #region Constructor 147 148 public GlobalHook() 149 { 150 151 Application.ApplicationExit += new EventHandler(Application_ApplicationExit); 152 153 } 154 155 #endregion 156 157 #region Methods 158 159 public void Start() 160 { 161 162 if (!_isStarted && 163 _hookType != 0) 164 { 165 166 // Make sure we keep a reference to this delegate! 167 // If not, GC randomly collects it, and a NullReference exception is thrown 168 _hookCallback = new HookProc(HookCallbackProcedure); 169 170 _handleToHook = SetWindowsHookEx( 171 _hookType, 172 _hookCallback, 173 GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 174 0); 175 //GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName 176 //GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName) 177 // Were we able to sucessfully start hook? 178 if (_handleToHook != 0) 179 { 180 _isStarted = true; 181 } 182 183 } 184 185 } 186 187 public void Stop() 188 { 189 190 if (_isStarted) 191 { 192 193 UnhookWindowsHookEx(_handleToHook); 194 195 _isStarted = false; 196 197 } 198 199 } 200 201 protected virtual int HookCallbackProcedure(int nCode, Int32 wParam, IntPtr lParam) 202 { 203 204 // This method must be overriden by each extending hook 205 return 0; 206 207 } 208 209 protected void Application_ApplicationExit(object sender, EventArgs e) 210 { 211 212 if (_isStarted) 213 { 214 Stop(); 215 } 216 217 } 218 219 #endregion 220 } 221 }