C# 虚拟键盘按键(二)【keybd_event】

1. 简述

在触屏及一些其他条件下,我们需要使用虚拟键盘,而不是真正去敲击键盘来实现按键功能,这时我们就考虑到模拟键盘的使用。上一篇我们讲了SendKeys的模拟键盘用法(C# 虚拟键盘按键(一)【SendKeys】),下面我们来简单谈一下Window API的keybd_event的用法,它的参数含义我在代码注释中已经写清楚了。下面代码需要引用System.Runtime.InteropServices。

2. 代码

    public class VKCODE
    {
        public readonly byte VK_LBUTTON = 0x01;//鼠标左键
        public readonly byte VK_RBUTTON = 0x02;//鼠标右键
        public readonly byte VK_CANCEL = 0x03;//控制中断处理
        public readonly byte VK_MBUTTON = 0x04;//鼠标中键
        public readonly byte VK_XBUTTON1 = 0x05;//X1 鼠标按钮
        public readonly byte VK_XBUTTON2 = 0x06;//X2 鼠标按钮
        //public readonly byte VK_ = 0x07;//保留
        public readonly byte VK_BACK = 0x08;//BACKSPACE 键
        public readonly byte VK_TAB = 0x09;//Tab 键
        //public readonly byte VK_ = 0x0A;//预留
        //public readonly byte VK_ = 0x0B;//预留
        public readonly byte VK_CLEAR = 0x0C;//CLEAR 键
        public readonly byte VK_RETURN = 0x0D;//Enter 键
        //public readonly byte VK_ = 0x0E;//未分配
        //public readonly byte VK_ = 0x0F;//未分配
        public readonly byte VK_SHIFT = 0x10;//SHIFT 键
        public readonly byte VK_CONTROL = 0x11;//CTRL 键
        public readonly byte VK_MENU = 0x12;//Alt 键
        public readonly byte VK_PAUSE = 0x13;//PAUSE 键
        public readonly byte VK_CAPITAL = 0x14;//CAPS LOCK 键
        public readonly byte VK_KANA = 0x15;//IME Kana 模式
        public readonly byte VK_HANGUL = 0x15;//IME Hanguel 模式
        public readonly byte VK_IME_ON = 0x16;//IME 打开
        public readonly byte VK_JUNJA = 0x17;//IME Junja 模式
        public readonly byte VK_FINAL = 0x18;//IME 最终模式
        public readonly byte VK_HANJA = 0x19;//IME Hanja 模式
        public readonly byte VK_KANJI = 0x19;//IME Kanji 模式
        public readonly byte VK_IME_OFF = 0x1A;//IME 关闭
        public readonly byte VK_ESCAPE = 0x1B;//ESC 键
        public readonly byte VK_CONVERT = 0x1C;//IME 转换
        public readonly byte VK_NONCONVERT = 0x1D;//IME 不转换
        public readonly byte VK_ACCEPT = 0x1E;//IME 接受
        public readonly byte VK_MODECHANGE = 0x1F;//IME 模式更改请求
        public readonly byte VK_SPACE = 0x20;//空格键
        public readonly byte VK_PRIOR = 0x21;//PAGE UP 键
        public readonly byte VK_NEXT = 0x22;//PAGE DOWN 键
        public readonly byte VK_END = 0x23;//END 键
        public readonly byte VK_HOME = 0x24;//HOME 键
        public readonly byte VK_LEFT = 0x25;//LEFT ARROW 键
        public readonly byte VK_UP = 0x26;//UP ARROW 键
        public readonly byte VK_RIGHT = 0x27;//RIGHT ARROW 键
        public readonly byte VK_DOWN = 0x28;//DOWN ARROW 键
        public readonly byte VK_SELECT = 0x29;//SELECT 键
        public readonly byte VK_PRINT = 0x2A;//PRINT 键
        public readonly byte VK_EXECUTE = 0x2B;//EXECUTE 键
        public readonly byte VK_SNAPSHOT = 0x2C;//PRINT SCREEN 键
        public readonly byte VK_INSERT = 0x2D;//INS 键
        public readonly byte VK_DELETE = 0x2E;//DEL 键
        public readonly byte VK_HELP = 0x2F;//HELP 键
        public readonly byte VK_D0 = 0x30;//0 键
        public readonly byte VK_D1 = 0x31;//1 键
        public readonly byte VK_D2 = 0x32;//2 键
        public readonly byte VK_D3 = 0x33;//3 键
        public readonly byte VK_D4 = 0x34;//4 键
        public readonly byte VK_D5 = 0x35;//5 键
        public readonly byte VK_D6 = 0x36;//6 键
        public readonly byte VK_D7 = 0x37;//7 键
        public readonly byte VK_D8 = 0x38;//8 键
        public readonly byte VK_D9 = 0x39;//9 键
        //public readonly byte VK_ = 0x3A;//未定义
        //public readonly byte VK_ = 0x3B;//未定义
        //public readonly byte VK_ = 0x3C;//未定义
        //public readonly byte VK_ = 0x3D;//未定义
        //public readonly byte VK_ = 0x3E;//未定义
        //public readonly byte VK_ = 0x3F;//未定义
        //public readonly byte VK_ = 0x40;//未定义
        public readonly byte VK_A = 0x41;//A 键
        public readonly byte VK_B = 0x42;//B 键
        public readonly byte VK_C = 0x43;//C 键
        public readonly byte VK_D = 0x44;//D 键
        public readonly byte VK_E = 0x45;//E 键
        public readonly byte VK_F = 0x46;//F 键
        public readonly byte VK_G = 0x47;//G 键
        public readonly byte VK_H = 0x48;//H 键
        public readonly byte VK_I = 0x49;//I 键
        public readonly byte VK_J = 0x4A;//J 键
        public readonly byte VK_K = 0x4B;//K 键
        public readonly byte VK_L = 0x4C;//L 键
        public readonly byte VK_M = 0x4D;//M 键
        public readonly byte VK_N = 0x4E;//N 键
        public readonly byte VK_O = 0x4F;//O 键
        public readonly byte VK_P = 0x50;//P 键
        public readonly byte VK_Q = 0x51;//Q 键
        public readonly byte VK_R = 0x52;//R 键
        public readonly byte VK_S = 0x53;//S 键
        public readonly byte VK_T = 0x54;//T 键
        public readonly byte VK_U = 0x55;//U 键
        public readonly byte VK_V = 0x56;//V 键
        public readonly byte VK_W = 0x57;//W 键
        public readonly byte VK_X = 0x58;//X 键
        public readonly byte VK_Y = 0x59;//Y 键
        public readonly byte VK_Z = 0x5A;//Z 键
        public readonly byte VK_LWIN = 0x5B;//左 Windows 键
        public readonly byte VK_RWIN = 0x5C;//右侧 Windows 键
        public readonly byte VK_APPS = 0x5D;//应用程序密钥
        //public readonly byte VK_ = 0x5E;//预留
        public readonly byte VK_SLEEP = 0x5F;//计算机休眠键
        public readonly byte VK_NUMPAD0 = 0x60;//数字键盘 0 键
        public readonly byte VK_NUMPAD1 = 0x61;//数字键盘 1 键
        public readonly byte VK_NUMPAD2 = 0x62;//数字键盘 2 键
        public readonly byte VK_NUMPAD3 = 0x63;//数字键盘 3 键
        public readonly byte VK_NUMPAD4 = 0x64;//数字键盘 4 键
        public readonly byte VK_NUMPAD5 = 0x65;//数字键盘 5 键
        public readonly byte VK_NUMPAD6 = 0x66;//数字键盘 6 键
        public readonly byte VK_NUMPAD7 = 0x67;//数字键盘 7 键
        public readonly byte VK_NUMPAD8 = 0x68;//数字键盘 8 键
        public readonly byte VK_NUMPAD9 = 0x69;//数字键盘 9 键
        public readonly byte VK_MULTIPLY = 0x6A;//乘号键
        public readonly byte VK_ADD = 0x6B;//加号键
        public readonly byte VK_SEPARATOR = 0x6C;//分隔符键
        public readonly byte VK_SUBTRACT = 0x6D;//减号键
        public readonly byte VK_DECIMAL = 0x6E;//句点键
        public readonly byte VK_DIVIDE = 0x6F;//除号键
        public readonly byte VK_F1 = 0x70;//F1 键
        public readonly byte VK_F2 = 0x71;//F2 键
        public readonly byte VK_F3 = 0x72;//F3 键
        public readonly byte VK_F4 = 0x73;//F4 键
        public readonly byte VK_F5 = 0x74;//F5 键
        public readonly byte VK_F6 = 0x75;//F6 键
        public readonly byte VK_F7 = 0x76;//F7 键
        public readonly byte VK_F8 = 0x77;//F8 键
        public readonly byte VK_F9 = 0x78;//F9 键
        public readonly byte VK_F10 = 0x79;//F10 键
        public readonly byte VK_F11 = 0x7A;//F11 键
        public readonly byte VK_F12 = 0x7B;//F12 键
        public readonly byte VK_F13 = 0x7C;//F13 键
        public readonly byte VK_F14 = 0x7D;//F14 键
        public readonly byte VK_F15 = 0x7E;//F15 键
        public readonly byte VK_F16 = 0x7F;//F16 键
        public readonly byte VK_F17 = 0x80;//F17 键
        public readonly byte VK_F18 = 0x81;//F18 键
        public readonly byte VK_F19 = 0x82;//F19 键
        public readonly byte VK_F20 = 0x83;//F20 键
        public readonly byte VK_F21 = 0x84;//F21 键
        public readonly byte VK_F22 = 0x85;//F22 键
        public readonly byte VK_F23 = 0x86;//F23 键
        public readonly byte VK_F24 = 0x87;//F24 键
        //public readonly byte VK_ = 0x88;//保留
        //public readonly byte VK_ = 0x89;//保留
        //public readonly byte VK_ = 0x8A;//保留
        //public readonly byte VK_ = 0x8B;//保留
        //public readonly byte VK_ = 0x8C;//保留
        //public readonly byte VK_ = 0x8D;//保留
        //public readonly byte VK_ = 0x8E;//保留
        //public readonly byte VK_ = 0x8F;//保留
        public readonly byte VK_NUMLOCK = 0x90;//NUM LOCK 键
        public readonly byte VK_SCROLL = 0x91;//SCROLL LOCK 键
        //public readonly byte VK_ = 0x92;//OEM 特有
        //public readonly byte VK_ = 0x93;//OEM 特有
        //public readonly byte VK_ = 0x94;//OEM 特有
        //public readonly byte VK_ = 0x95;//OEM 特有
        //public readonly byte VK_ = 0x96;//OEM 特有
        //public readonly byte VK_ = 0x97;//未分配
        //public readonly byte VK_ = 0x98;//未分配
        //public readonly byte VK_ = 0x99;//未分配
        //public readonly byte VK_ = 0x9A;//未分配
        //public readonly byte VK_ = 0x9B;//未分配
        //public readonly byte VK_ = 0x9C;//未分配
        //public readonly byte VK_ = 0x9D;//未分配
        //public readonly byte VK_ = 0x9E;//未分配
        //public readonly byte VK_ = 0x9F;//未分配
        public readonly byte VK_LSHIFT = 0xA0;//左 SHIFT 键
        public readonly byte VK_RSHIFT = 0xA1;//右 SHIFT 键
        public readonly byte VK_LCONTROL = 0xA2;//左 Ctrl 键
        public readonly byte VK_RCONTROL = 0xA3;//右 Ctrl 键
        public readonly byte VK_LMENU = 0xA4;//左 ALT 键
        public readonly byte VK_RMENU = 0xA5;//右 ALT 键
        public readonly byte VK_BROWSER_BACK = 0xA6;//浏览器后退键
        public readonly byte VK_BROWSER_FORWARD = 0xA7;//浏览器前进键
        public readonly byte VK_BROWSER_REFRESH = 0xA8;//浏览器刷新键
        public readonly byte VK_BROWSER_STOP = 0xA9;//浏览器停止键
        public readonly byte VK_BROWSER_SEARCH = 0xAA;//浏览器搜索键
        public readonly byte VK_BROWSER_FAVORITES = 0xAB;//浏览器收藏键
        public readonly byte VK_BROWSER_HOME = 0xAC;//浏览器“开始”和“主页”键
        public readonly byte VK_VOLUME_MUTE = 0xAD;//静音键
        public readonly byte VK_VOLUME_DOWN = 0xAE;//音量减小键
        public readonly byte VK_VOLUME_UP = 0xAF;//音量增加键
        public readonly byte VK_MEDIA_NEXT_TRACK = 0xB0;//下一曲目键
        public readonly byte VK_MEDIA_PREV_TRACK = 0xB1;//上一曲目键
        public readonly byte VK_MEDIA_STOP = 0xB2;//停止媒体键
        public readonly byte VK_MEDIA_PLAY_PAUSE = 0xB3;//播放/暂停媒体键
        public readonly byte VK_LAUNCH_MAIL = 0xB4;//启动邮件键
        public readonly byte VK_LAUNCH_MEDIA_SELECT = 0xB5;//选择媒体键
        public readonly byte VK_LAUNCH_APP1 = 0xB6;//启动应用程序 1 键
        public readonly byte VK_LAUNCH_APP2 = 0xB7;//启动应用程序 2 键
        //public readonly byte VK_ = 0xB8;//预留
        //public readonly byte VK_ = 0xB9;//预留
        public readonly byte VK_OEM_1 = 0xBA;//用于杂项字符;它可能因键盘而异。 对于美国标准键盘,键;:
        public readonly byte VK_OEM_PLUS = 0xBB;//对于任何国家/地区,键+
        public readonly byte VK_OEM_COMMA = 0xBC;//对于任何国家/地区,键,
        public readonly byte VK_OEM_MINUS = 0xBD;//对于任何国家/地区,键-
        public readonly byte VK_OEM_PERIOD = 0xBE;//对于任何国家/地区,键.
        public readonly byte VK_OEM_2 = 0xBF;//用于杂项字符;它可能因键盘而异。 对于美国标准键盘,键/?
        public readonly byte VK_OEM_3 = 0xC0;//用于杂项字符;它可能因键盘而异。 对于美国标准键盘,键`~
        //public readonly byte VK_ = 0xC1;//保留
        //public readonly byte VK_ = 0xC2;//保留
        //public readonly byte VK_ = 0xC3;//保留
        //public readonly byte VK_ = 0xC4;//保留
        //public readonly byte VK_ = 0xC5;//保留
        //public readonly byte VK_ = 0xC6;//保留
        //public readonly byte VK_ = 0xC7;//保留
        //public readonly byte VK_ = 0xC8;//保留
        //public readonly byte VK_ = 0xC9;//保留
        //public readonly byte VK_ = 0xCA;//保留
        //public readonly byte VK_ = 0xCB;//保留
        //public readonly byte VK_ = 0xCC;//保留
        //public readonly byte VK_ = 0xCD;//保留
        //public readonly byte VK_ = 0xCE;//保留
        //public readonly byte VK_ = 0xCF;//保留
        //public readonly byte VK_ = 0xD0;//保留
        //public readonly byte VK_ = 0xD1;//保留
        //public readonly byte VK_ = 0xD2;//保留
        //public readonly byte VK_ = 0xD3;//保留
        //public readonly byte VK_ = 0xD4;//保留
        //public readonly byte VK_ = 0xD5;//保留
        //public readonly byte VK_ = 0xD6;//保留
        //public readonly byte VK_ = 0xD7;//保留
        //public readonly byte VK_ = 0xD8;//保留
        //public readonly byte VK_ = 0xD9;//保留
        //public readonly byte VK_ = 0xDA;//保留
        public readonly byte VK_OEM_4 = 0xDB;//用于杂项字符;它可能因键盘而异。 对于美国标准键盘,键[{
        public readonly byte VK_OEM_5 = 0xDC;//用于杂项字符;它可能因键盘而异。 对于美国标准键盘,键\\|
        public readonly byte VK_OEM_6 = 0xDD;//用于杂项字符;它可能因键盘而异。 对于美国标准键盘,键]}
        public readonly byte VK_OEM_7 = 0xDE;//用于杂项字符;它可能因键盘而异。 对于美国标准键盘,键'"
        public readonly byte VK_OEM_8 = 0xDF;//用于杂项字符;它可能因键盘而异。
        //public readonly byte VK_ = 0xE0;//预留
        //public readonly byte VK_ = 0xE1;//OEM 特有
        public readonly byte VK_OEM_102 = 0xE2;//美国标准键盘上的 <> 键,或非美国 102 键键盘上的 \\| 键
        //public readonly byte VK_ = 0xE3;//OEM 特有
        //public readonly byte VK_ = 0xE4;//OEM 特有
        public readonly byte VK_PROCESSKEY = 0xE5;//IME PROCESS 键
        //public readonly byte VK_ = 0xE6;//OEM 特有
        public readonly byte VK_PACKET = 0xE7;//用于将 Unicode 字符当作键击传递。 VK_PACKET 键是用于非键盘输入法的 32 位虚拟键值的低位字。 有关更多信息,请参阅 KEYBDINPUT、SendInput、WM_KEYDOWN 和 WM_KEYUP 中的注释
        //public readonly byte VK_ = 0xE8;//未分配
        //public readonly byte VK_ = 0xE9;//OEM 特有
        //public readonly byte VK_ = 0xEA;//OEM 特有
        //public readonly byte VK_ = 0xEB;//OEM 特有
        //public readonly byte VK_ = 0xEC;//OEM 特有
        //public readonly byte VK_ = 0xED;//OEM 特有
        //public readonly byte VK_ = 0xEE;//OEM 特有
        //public readonly byte VK_ = 0xEF;//OEM 特有
        //public readonly byte VK_ = 0xF0;//OEM 特有
        //public readonly byte VK_ = 0xF1;//OEM 特有
        //public readonly byte VK_ = 0xF2;//OEM 特有
        //public readonly byte VK_ = 0xF3;//OEM 特有
        //public readonly byte VK_ = 0xF4;//OEM 特有
        //public readonly byte VK_ = 0xF5;//OEM 特有
        public readonly byte VK_ATTN = 0xF6;//Attn 键
        public readonly byte VK_CRSEL = 0xF7;//CrSel 键
        public readonly byte VK_EXSEL = 0xF8;//ExSel 键
        public readonly byte VK_EREOF = 0xF9;//Erase EOF 键
        public readonly byte VK_PLAY = 0xFA;//Play 键
        public readonly byte VK_ZOOM = 0xFB;//Zoom 键
        //public readonly byte VK_NONAME = 0xFC;//预留
        public readonly byte VK_PA1 = 0xFD;//PA1 键
        public readonly byte VK_OEM_CLEAR = 0xFE;//Clear 键
        
    }

    ///按键状态
    public enum KeyStatus
    {
        Down,     //键按下
        Up,       //键释放
        ExDown,   //扩展键按下
        ExUp,     //扩展键释放
        Press     //键按下后再释放
    }
    public class VirKeyboard : VKCODE
    {
        /* 虚拟键盘输入
         * 参数一:bVk--键盘上的键的虚拟代码
         * 参数二:bScan--该键的硬件扫描码【扫描代码是系统在用户按下某个键时生成的值。
         *         它是一个值,该值标识按下的键(不考虑活动键盘布局),而不是由键表示的字符。 
         *         应用程序通常忽略扫描代码,它使用虚拟键代码来解释击键消息。】,值一般为0
         * 参数三:dwFlags--控制功能,有以下三个值
         *         KEYEVENTF_KEYDOWN = 0x0000,表示键被按下
         *         KEYEVENTF_EXTENDEDKEY = 0x0001,表示指示这个键是否是扩展键,
         *         KEYEVENTF_KEYUP = 0x0002,键被释放
         * 参数四:dwExtraInfo,与键笔划关联的附加值。值一般为0
         */
        [DllImport("USER32.DLL")]
        private static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

        //按键状态
        private readonly int KEYEVENTF_KEYDOWN = 0x0000; //键被按下
        private readonly int KEYEVENTF_EXTENDEDKEY = 0x0001; //是扩展键
        private readonly int KEYEVENTF_KEYUP = 0x0002; //键被释放
        
        
        /// <summary>
        /// 虚拟按键,按下某键后(特别是Shift),要记得释放,一般是按下和释放成对使用,或者使用Press。
        /// </summary>
        /// <param name="vkCode">VKCODE类里的定义的只读变量,即按键的虚拟代码</param>
        /// <param name="keyStatus">KeyStatus按键状态</param>
        public void VirtualKey(byte vkCode, KeyStatus keyStatus)
        {
            switch (keyStatus)
            {
                case KeyStatus.Down:
                    keybd_event(vkCode, 0, KEYEVENTF_KEYDOWN, 0);
                    break;
                case KeyStatus.Up:
                    keybd_event(vkCode, 0, KEYEVENTF_KEYUP, 0);
                    break;
                case KeyStatus.ExDown:
                    keybd_event(vkCode, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYDOWN, 0);
                    break;
                case KeyStatus.ExUp:
                    keybd_event(vkCode, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
                    break;
                case KeyStatus.Press:
                    keybd_event(vkCode, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYDOWN, 0);
                    System.Threading.Thread.Sleep(100);
                    keybd_event(vkCode, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
                    break;
            }
            
        }

    }

3. 说明

别看我们平时用鼠标键盘很简单,但是它确实是个庞大的体系,微软的帮助文档有473页之多,如下图,这些文档看起来是不是很头疼?其实我们没有必要去仔细了解它,只需要知道我们用到的部分即可,能实现功能就行。
在这里插入图片描述

键盘按键有个关键的部分就是每个按键都有一个对应的虚拟代码,我已经在代码中的VKCODE类全部列出了,大家也可以结合自己的实际情况单独拿出来使用。
枚举KeyStatus是我用来定义按键的状态的,普通可显示字符的按键用Up,Down就行,ExUp和ExDown是指有扩展键按下或释放,Press是指普通或扩展键按下后又释放的状态,为确保Window消息正确传递,我在按下后加了100毫秒的延时,再去释放该按键。
VirKeyboard类是我们真正要用到的类,我在它上继承了VKCODE类,是为了方便使用,而不必再去new一个VKCODE。例如我们虚拟输出一个大写A,可以使用以下方法:

    VirKeyboard virKey = new VirKeyboard();
    virKey.VirtualKey(virKey.VK_SHIFT, KeyStatus.Down); //模拟按下Shift键
    virKey.VirtualKey(virKey.VK_A, KeyStatus.Down);     //模拟按下a键
    virKey.VirtualKey(virKey.VK_A, KeyStatus.Up);     //模拟弹起a键
    virKey.VirtualKey(virKey.VK_SHIFT, KeyStatus.Up);   //模拟弹起Shift键

这里要注意,在按下扩展键特别是常用的Shift键后,要记得释放(弹起)该键,虽然不会有什么太大影响,但系统会认为Shift键是按下状态,再操作其他应用程序时,可能会产生影响的。
上面我们输出的大写A如果改成小写a,可以直接用Press:

    virKey.VirtualKey(virKey.VK_A, KeyStatus.Press); //按下并释放a键

不管是普通可见字符按键还是扩展按键,使用KeyStatus.ExDown和KeyStatus.ExUp都能实现,使用它俩具有通用性,而不必关心是否按了扩展键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值