前言
通过 C# 或 VB.NET,你只需编写少量的代码即可实现一个按键精灵。
第一节 接口
调用系统 API 实现获取或设置指定的按键状态。
获取按键状态
调用 GetAsyncKeyState() 获取指定按键的状态,GetActiveKey() 检索指定范围内的按键状态
合成击键事件
调用 keybd_event() 可合成一次击键事件,通常两次击键事件间需要设定时间间隔
对 DirectInput 有效
调用 MapVirtualKey() 获取指定按键的硬件扫描码,传入 keybd_event() 第二个参数可以对 DirectInput 有效。
第二节 帮助类
实现一系列的静态方法,由此提供不同的模拟按键功能。
虚拟键码枚举
''' <summary> ''' 虚拟键码枚举 ''' </summary> Public Enum VirtualKeys VK_LBUTTON = 1 VK_RBUTTON = 2 VK_CANCEL = 3 VK_MBUTTON = 4 VK_XBUTTON1 = 5 VK_XBUTTON2 = 6 VK_BACK = 8 VK_TAB = 9 VK_CLEAR = 12 VK_RETURN = 13 VK_SHIFT = 16 VK_CONTROL = 17 VK_MENU = 18 VK_PAUSE = 19 VK_CAPITAL = 20 VK_KANA = 21 VK_HANGUL = 21 VK_JUNJA = 23 VK_FINAL = 24 VK_HANJA = 25 VK_KANJI = 26 VK_ESCAPE = 27 VK_CONVERT = 28 VK_NONCONVERT = 29 VK_ACCEPT = 30 VK_MODECHANGE = 31 VK_SPACE = 32 VK_PRIOR = 33 VK_NEXT = 34 VK_END = 35 VK_HOME = 36 VK_LEFT = 37 VK_UP = 38 VK_RIGHT = 39 VK_DOWN = 40 VK_SELECT = 41 VK_PRINT = 42 VK_EXECUTE = 43 VK_SNAPSHOT = 44 VK_INSERT = 45 VK_DELETE = 46 VK_HELP = 47 VK_0 = 48 VK_1 = 49 VK_2 = 50 VK_3 = 51 VK_4 = 52 VK_5 = 53 VK_6 = 54 VK_7 = 55 VK_8 = 56 VK_9 = 57 VK_A = 65 VK_B = 66 VK_C = 67 VK_D = 68 VK_E = 69 VK_F = 70 VK_G = 71 VK_H = 72 VK_I = 73 VK_J = 74 VK_K = 75 VK_L = 76 VK_M = 77 VK_N = 78 VK_O = 79 VK_P = 80 VK_Q = 81 VK_R = 82 VK_S = 83 VK_T = 84 VK_U = 85 VK_V = 86 VK_W = 87 VK_X = 88 VK_Y = 89 VK_Z = 90 VK_LWIN = 91 VK_RWIN = 92 VK_APPS = 93 VK_SLEEP = 95 VK_NUMPAD0 = 96 VK_NUMPAD1 = 97 VK_NUMPAD2 = 98 VK_NUMPAD3 = 99 VK_NUMPAD4 = 100 VK_NUMPAD5 = 101 VK_NUMPAD6 = 102 VK_NUMPAD7 = 103 VK_NUMPAD8 = 104 VK_NUMPAD9 = 105 VK_MULTIPLY = 106 VK_ADD = 107 VK_SEPARATOR = 108 VK_SUBTRACT = 109 VK_DECIMAL = 110 VK_DIVIDE = 111 VK_F1 = 112 VK_F2 = 113 VK_F3 = 114 VK_F4 = 115 VK_F5 = 116 VK_F6 = 117 VK_F7 = 118 VK_F8 = 119 VK_F9 = 120 VK_F10 = 121 VK_F11 = 122 VK_F12 = 123 VK_F13 = 124 VK_F14 = 125 VK_F15 = 126 VK_F16 = 127 VK_F17 = 128 VK_F18 = 129 VK_F19 = 130 VK_F20 = 131 VK_F21 = 132 VK_F22 = 133 VK_F23 = 134 VK_F24 = 135 VK_NUMLOCK = 144 VK_SCROLL = 145 VK_LSHIFT = 160 VK_RSHIFT = 161 VK_LCONTROL = 162 VK_RCONTROL = 163 VK_LMENU = 164 VK_RMENU = 165 VK_BROWSER_BACK = 166 VK_BROWSER_FORWARD = 167 VK_BROWSER_REFRESH = 168 VK_BROWSER_STOP = 169 VK_BROWSER_SEARCH = 170 VK_BROWSER_FAVORITES = 171 VK_BROWSER_HOME = 172 VK_VOLUME_MUTE = 173 VK_VOLUME_DOWN = 174 VK_VOLUME_UP = 175 VK_MEDIA_NEXT_TRACK = 176 VK_MEDIA_PREV_TRACK = 177 VK_MEDIA_STOP = 178 VK_MEDIA_PLAY_PAUSE = 179 VK_LAUNCH_MAIL = 180 VK_LAUNCH_MEDIA_SELECT = 181 VK_LAUNCH_APP1 = 182 VK_LAUNCH_APP2 = 183 VK_OEM_1 = 186 VK_OEM_PLUS = 187 VK_OEM_COMMA = 188 VK_OEM_MINUS = 189 VK_OEM_PERIOD = 190 VK_OEM_2 = 191 VK_OEM_3 = 192 VK_OEM_4 = 219 VK_OEM_5 = 220 VK_OEM_6 = 221 VK_OEM_7 = 222 VK_OEM_8 = 223 VK_OEM_102 = 226 VK_PACKET = 231 VK_PROCESSKEY = 229 VK_ATTN = 246 VK_CRSEL = 247 VK_EXSEL = 248 VK_EREOF = 249 VK_PLAY = 250 VK_ZOOM = 251 VK_NONAME = 252 VK_PA1 = 253 VK_OEM_CLEAR = 254 End Enum
/// <summary> /// 虚拟键码枚举 /// </summary> public enum VirtualKeys { VK_LBUTTON = 1, VK_RBUTTON = 2, VK_CANCEL = 3, VK_MBUTTON = 4, VK_XBUTTON1 = 5, VK_XBUTTON2 = 6, VK_BACK = 8, VK_TAB = 9, VK_CLEAR = 12, VK_RETURN = 13, VK_SHIFT = 16, VK_CONTROL = 17, VK_MENU = 18, VK_PAUSE = 19, VK_CAPITAL = 20, VK_KANA = 21, VK_HANGUL = 21, VK_JUNJA = 23, VK_FINAL = 24, VK_HANJA = 25, VK_KANJI = 26, VK_ESCAPE = 27, VK_CONVERT = 28, VK_NONCONVERT = 29, VK_ACCEPT = 30, VK_MODECHANGE = 31, VK_SPACE = 32, VK_PRIOR = 33, VK_NEXT = 34, VK_END = 35, VK_HOME = 36, VK_LEFT = 37, VK_UP = 38, VK_RIGHT = 39, VK_DOWN = 40, VK_SELECT = 41, VK_PRINT = 42, VK_EXECUTE = 43, VK_SNAPSHOT = 44, VK_INSERT = 45, VK_DELETE = 46, VK_HELP = 47, VK_0 = 48, VK_1 = 49, VK_2 = 50, VK_3 = 51, VK_4 = 52, VK_5 = 53, VK_6 = 54, VK_7 = 55, VK_8 = 56, VK_9 = 57, VK_A = 65, VK_B = 66, VK_C = 67, VK_D = 68, VK_E = 69, VK_F = 70, VK_G = 71, VK_H = 72, VK_I = 73, VK_J = 74, VK_K = 75, VK_L = 76, VK_M = 77, VK_N = 78, VK_O = 79, VK_P = 80, VK_Q = 81, VK_R = 82, VK_S = 83, VK_T = 84, VK_U = 85, VK_V = 86, VK_W = 87, VK_X = 88, VK_Y = 89, VK_Z = 90, VK_LWIN = 91, VK_RWIN = 92, VK_APPS = 93, VK_SLEEP = 95, VK_NUMPAD0 = 96, VK_NUMPAD1 = 97, VK_NUMPAD2 = 98, VK_NUMPAD3 = 99, VK_NUMPAD4 = 100, VK_NUMPAD5 = 101, VK_NUMPAD6 = 102, VK_NUMPAD7 = 103, VK_NUMPAD8 = 104, VK_NUMPAD9 = 105, VK_MULTIPLY = 106, VK_ADD = 107, VK_SEPARATOR = 108, VK_SUBTRACT = 109, VK_DECIMAL = 110, VK_DIVIDE = 111, VK_F1 = 112, VK_F2 = 113, VK_F3 = 114, VK_F4 = 115, VK_F5 = 116, VK_F6 = 117, VK_F7 = 118, VK_F8 = 119, VK_F9 = 120, VK_F10 = 121, VK_F11 = 122, VK_F12 = 123, VK_F13 = 124, VK_F14 = 125, VK_F15 = 126, VK_F16 = 127, VK_F17 = 128, VK_F18 = 129, VK_F19 = 130, VK_F20 = 131, VK_F21 = 132, VK_F22 = 133, VK_F23 = 134, VK_F24 = 135, VK_NUMLOCK = 144, VK_SCROLL = 145, VK_LSHIFT = 160, VK_RSHIFT = 161, VK_LCONTROL = 162, VK_RCONTROL = 163, VK_LMENU = 164, VK_RMENU = 165, VK_BROWSER_BACK = 166, VK_BROWSER_FORWARD = 167, VK_BROWSER_REFRESH = 168, VK_BROWSER_STOP = 169, VK_BROWSER_SEARCH = 170, VK_BROWSER_FAVORITES = 171, VK_BROWSER_HOME = 172, VK_VOLUME_MUTE = 173, VK_VOLUME_DOWN = 174, VK_VOLUME_UP = 175, VK_MEDIA_NEXT_TRACK = 176, VK_MEDIA_PREV_TRACK = 177, VK_MEDIA_STOP = 178, VK_MEDIA_PLAY_PAUSE = 179, VK_LAUNCH_MAIL = 180, VK_LAUNCH_MEDIA_SELECT = 181, VK_LAUNCH_APP1 = 182, VK_LAUNCH_APP2 = 183, VK_OEM_1 = 186, VK_OEM_PLUS = 187, VK_OEM_COMMA = 188, VK_OEM_MINUS = 189, VK_OEM_PERIOD = 190, VK_OEM_2 = 191, VK_OEM_3 = 192, VK_OEM_4 = 219, VK_OEM_5 = 220, VK_OEM_6 = 221, VK_OEM_7 = 222, VK_OEM_8 = 223, VK_OEM_102 = 226, VK_PACKET = 231, VK_PROCESSKEY = 229, VK_ATTN = 246, VK_CRSEL = 247, VK_EXSEL = 248, VK_EREOF = 249, VK_PLAY = 250, VK_ZOOM = 251, VK_NONAME = 252, VK_PA1 = 253, VK_OEM_CLEAR = 254 }
虚拟键盘对象,提供一系列按键命令
(在线工具转换,局部静态变量部分请参考 VB.NET 版本)
''' <summary> ''' 虚拟键盘,提供一系列按键命令 ''' </summary> Public Class VirtualKeyboard Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer) Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Integer, ByVal wMapType As Integer) As Integer Private Declare Function GetAsyncKeyState Lib "user32 " (ByVal vKey As Integer) As Integer ''' <summary> ''' 发送一组按键 ''' </summary> Public Shared Sub SendString(str As String, interval As Integer) Dim strArr() As String = Split(str, ",") For Each SubStr In strArr If SubStr.First = "#" Then System.Threading.Thread.Sleep(CInt(SubStr.Substring(1))) Else For Each SubChar As Char In SubStr VirtualKeyDown(Asc(SubChar)) System.Threading.Thread.Sleep(interval) VirtualKeyUp(Asc(SubChar)) Next End If Next End Sub ''' <summary> ''' 发送一组扩展的按键 ''' </summary> Public Shared Sub SendStringEx(str As String, interval As Integer, ParamArray extra() As VirtualKeys) For Each SubKey In extra VirtualKeyDown(SubKey) Next SendString(str, interval) For Each SubKey In extra VirtualKeyUp(SubKey) Next End Sub ''' <summary> ''' 发送单个按键 ''' </summary> Public Shared Sub SendKey(vKey As VirtualKeys, interval As Integer) VirtualKeyDown(vKey) System.Threading.Thread.Sleep(interval) VirtualKeyUp(vKey) End Sub ''' <summary> ''' 同时发送两个按键 ''' </summary> Public Shared Sub SendCouple(vKey1 As VirtualKeys, vKey2 As VirtualKeys, interval As Integer) VirtualKeyDown(vKey1) VirtualKeyDown(vKey2) System.Threading.Thread.Sleep(interval) VirtualKeyUp(vKey1) VirtualKeyUp(vKey2) End Sub ''' <summary> ''' 获取A~Z的按键状态 ''' </summary> Public Shared Function GetActiveKey() As Byte For i = 65 To 90 'A~Z的ASICC码 If CurrentKeyState(i) = True Then Return i End If Next Return 0 End Function ''' <summary> ''' 获取键盘按键状态 ''' </summary> Private Shared Function CurrentKeyState(ByVal KeyCode As Byte) As Boolean Static KeyState(255) As Boolean Dim temp As Integer = GetAsyncKeyState(KeyCode) If temp = 0 Then KeyState(KeyCode) = False Else If KeyState(KeyCode) = False Then KeyState(KeyCode) = True Return True End If KeyState(KeyCode) = True Return False End If Return False End Function ''' <summary> ''' 按下指定按键 ''' </summary> Private Shared Sub VirtualKeyDown(vKey As VirtualKeys) keybd_event(vKey, MapVirtualKey(vKey, 0), &H1 Or 0, 0) '按下 End Sub ''' <summary> ''' 松开指定按键 ''' </summary> Private Shared Sub VirtualKeyUp(vKey As VirtualKeys) keybd_event(vKey, MapVirtualKey(vKey, 0), &H1 Or &H2, 0) '弹起 End Sub End Class
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Runtime.InteropServices; /// <summary> /// 虚拟键盘,提供一系列按键命令 /// </summary> public class VirtualKeyboard { [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); [DllImport("user32", EntryPoint = "MapVirtualKeyA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int MapVirtualKey(int wCode, int wMapType); [DllImport("user32 ", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] private static extern int GetAsyncKeyState(int vKey); /// <summary> /// 发送一组按键 /// </summary> public static void SendString(string str, int interval) { string[] strArr = Strings.Split(str, ","); foreach (void SubStr_loopVariable in strArr) { SubStr = SubStr_loopVariable; if (SubStr.First == "#") { System.Threading.Thread.Sleep(Convert.ToInt32(SubStr.Substring(1))); } else { foreach (char SubChar in SubStr) { VirtualKeyDown(Strings.Asc(SubChar)); System.Threading.Thread.Sleep(interval); VirtualKeyUp(Strings.Asc(SubChar)); } } } } /// <summary> /// 发送一组扩展的按键 /// </summary> public static void SendStringEx(string str, int interval, params VirtualKeys[] extra) { foreach (void SubKey_loopVariable in extra) { SubKey = SubKey_loopVariable; VirtualKeyDown(SubKey); } SendString(str, interval); foreach (void SubKey_loopVariable in extra) { SubKey = SubKey_loopVariable; VirtualKeyUp(SubKey); } } /// <summary> /// 发送单个按键 /// </summary> public static void SendKey(VirtualKeys vKey, int interval) { VirtualKeyDown(vKey); System.Threading.Thread.Sleep(interval); VirtualKeyUp(vKey); } /// <summary> /// 同时发送两个按键 /// </summary> public static void SendCouple(VirtualKeys vKey1, VirtualKeys vKey2, int interval) { VirtualKeyDown(vKey1); VirtualKeyDown(vKey2); System.Threading.Thread.Sleep(interval); VirtualKeyUp(vKey1); VirtualKeyUp(vKey2); } /// <summary> /// 获取A~Z的按键状态 /// </summary> public static byte GetActiveKey() { //A~Z的ASICC码 for (i = 65; i <= 90; i++) { if (CurrentKeyState(i) == true) { return i; } } return 0; } static readonly Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag static_CurrentKeyState_KeyState_Init = new Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag(); /// <summary> /// 获取键盘按键状态 /// </summary> static bool[] static_CurrentKeyState_KeyState; private static bool CurrentKeyState(byte KeyCode) { lock (static_CurrentKeyState_KeyState_Init) { try { if (InitStaticVariableHelper(static_CurrentKeyState_KeyState_Init)) { static_CurrentKeyState_KeyState = new bool[256]; } } finally { static_CurrentKeyState_KeyState_Init.State = 1; } } int temp = GetAsyncKeyState(KeyCode); if (temp == 0) { static_CurrentKeyState_KeyState(KeyCode) = false; } else { if (static_CurrentKeyState_KeyState(KeyCode) == false) { static_CurrentKeyState_KeyState(KeyCode) = true; return true; } static_CurrentKeyState_KeyState(KeyCode) = true; return false; } return false; } /// <summary> /// 按下指定按键 /// </summary> private static void VirtualKeyDown(VirtualKeys vKey) { keybd_event(vKey, MapVirtualKey(vKey, 0), 0x1 | 0, 0); //按下 } /// <summary> /// 松开指定按键 /// </summary> private static void VirtualKeyUp(VirtualKeys vKey) { keybd_event(vKey, MapVirtualKey(vKey, 0), 0x1 | 0x2, 0); //弹起 } static bool InitStaticVariableHelper(Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag flag) { if (flag.State == 0) { flag.State = 2; return true; } else if (flag.State == 2) { throw new Microsoft.VisualBasic.CompilerServices.IncompleteInitialization(); } else { return false; } } }
附录
GitHub:AutoHotKey.NET (已失效)