C#实现虚拟键盘的实例详解
更新时间:2022年12月16日 10:00:17 作者:芝麻粒儿
这篇文章主要为大家详细介绍了如何利用C#实现虚拟键盘,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
实践过程
效果
代码
public partial class Form1 : Form { private HookEx.UserActivityHook hook;//实例化HookEx.UserActivityHook private static IDictionary<short, IList<FecitButton>> spacialVKButtonsMap;//表示键/值对应的泛型集合 private static IDictionary<short, IList<FecitButton>> combinationVKButtonsMap;//表示键/值对应的泛型集合 public Form1() { InitializeComponent(); #region 将指定的按钮值添加到键类型中 spacialVKButtonsMap = new Dictionary<short, IList<FecitButton>>(); combinationVKButtonsMap = new Dictionary<short, IList<FecitButton>>(); IList<FecitButton> buttonList = new List<FecitButton>();//实例化IList<FecitButton>(按照索引单独访问的一组对象) buttonList.Add(this.btnLCTRL);//添加左面的CTRL键 combinationVKButtonsMap.Add(KeyboardConstaint.VK_CONTROL, buttonList);//添加左面的CTRL键值 buttonList = new List<FecitButton>(); buttonList.Add(this.btnLSHFT);//添加左面的LSHFT键 buttonList.Add(this.btnRSHFT);//添加右面的LSHFT键 combinationVKButtonsMap.Add(KeyboardConstaint.VK_SHIFT, buttonList);//添加LSHFT键值 buttonList = new List<FecitButton>();//实例化IList<FecitButton> buttonList.Add(this.btnLALT);//添加左面的ALT键 combinationVKButtonsMap.Add(KeyboardConstaint.VK_MENU, buttonList);//添加左面的ALT键值 buttonList = new List<FecitButton>();//实例化IList<FecitButton> buttonList.Add(this.btnLW);//添加左面的WIN键 combinationVKButtonsMap.Add(KeyboardConstaint.VK_LWIN, buttonList);//添加左面的WIN键值 buttonList = new List<FecitButton>();//实例化IList<FecitButton> buttonList.Add(this.btnLOCK);//添加LOCK键 spacialVKButtonsMap.Add(KeyboardConstaint.VK_CAPITAL, buttonList);//添加LOCK键值 #endregion foreach (Control ctrl in this.Controls) { FecitButton button = ctrl as FecitButton; if (button == null) { continue; } #region 设置按键的消息值 short key = 0;//记录键值 bool isSpacialKey = true; //记录快捷键的键值 switch (button.Name)//获取键名称 { case "btnLCTRL"://CTRL键的左键名称 case "btnRCTRL"://CTRL键的右键名称 key = KeyboardConstaint.VK_CONTROL;//获取CTRL键的键值 break; case "btnLSHFT"://SHFT键的左键名称 case "btnRSHFT"://SHFT键的左键名称 key = KeyboardConstaint.VK_SHIFT;//获取SHFT键的键值 break; case "btnLALT"://ALT键的左键名称 case "btnRALT"://ALT键的左键名称 key = KeyboardConstaint.VK_MENU;//获取ALT键的键值 break; case "btnLW"://WIN键的左键名称 case "btnRW"://WIN键的左键名称 key = KeyboardConstaint.VK_LWIN;//获取WIN键的键值 break; case "btnESC"://ESC键的名称 key = KeyboardConstaint.VK_ESCAPE;//获取ESC键的键值 break; case "btnTAB"://TAB键的名称 key = KeyboardConstaint.VK_TAB;//获取TAB键的键值 break; case "btnF1"://F1键的名称 key = KeyboardConstaint.VK_F1;//获取F1键的键值 break; case "btnF2": key = KeyboardConstaint.VK_F2; break; case "btnF3": key = KeyboardConstaint.VK_F3; break; case "btnF4": key = KeyboardConstaint.VK_F4; break; case "btnF5": key = KeyboardConstaint.VK_F5; break; case "btnF6": key = KeyboardConstaint.VK_F6; break; case "btnF7": key = KeyboardConstaint.VK_F7; break; case "btnF8": key = KeyboardConstaint.VK_F8; break; case "btnF9": key = KeyboardConstaint.VK_F9; break; case "btnF10": key = KeyboardConstaint.VK_F10; break; case "btnF11": key = KeyboardConstaint.VK_F11; break; case "btnF12": key = KeyboardConstaint.VK_F12; break; case "btnENT": case "btnNUMENT": key = KeyboardConstaint.VK_RETURN; break; case "btnWave": key = KeyboardConstaint.VK_OEM_3; break; case "btnSem": key = KeyboardConstaint.VK_OEM_1; break; case "btnQute": key = KeyboardConstaint.VK_OEM_7; break; case "btnSpace": key = KeyboardConstaint.VK_SPACE; break; case "btnBKSP": key = KeyboardConstaint.VK_BACK; break; case "btnComma": key = KeyboardConstaint.VK_OEM_COMMA; break; case "btnFullStop": key = KeyboardConstaint.VK_OEM_PERIOD; break; case "btnLOCK": key = KeyboardConstaint.VK_CAPITAL; break; case "btnMinus": key = KeyboardConstaint.VK_OEM_MINUS; break; case "btnEqual": key = KeyboardConstaint.VK_OEM_PLUS; break; case "btnLBracket": key = KeyboardConstaint.VK_OEM_4; break; case "btnRBracket": key = KeyboardConstaint.VK_OEM_6; break; case "btnPath": key = KeyboardConstaint.VK_OEM_5; break; case "btnDivide": key = KeyboardConstaint.VK_OEM_2; break; case "btnPSC": key = KeyboardConstaint.VK_SNAPSHOT; break; case "btnINS"://Insert键的名称 key = KeyboardConstaint.VK_INSERT;//获取Insert键的键值 break; case "btnDEL"://Delete键的名称 key = KeyboardConstaint.VK_DELETE;//获取Delete键的键值 break; default: isSpacialKey = false; break; } if (!isSpacialKey) { key = (short)button.Name[3];//获取按钮的键值 } button.Tag = key;//在按钮的Tag属性中记录相应的键值 #endregion button.Click += ButtonOnClick;//重载按钮的单击事件 } this.hook = new HookEx.UserActivityHook(true, true); HookEvents(); } private void HookEvents() { this.hook.KeyDown += HookOnGlobalKeyDown;//重载hook类中的自定义事件KeyDown this.hook.KeyUp += HookOnGlobalKeyUp;//重载hook类中的自定义事件KeyUp this.hook.MouseActivity += HookOnMouseActivity;//重载hook类中的自定义事件MouseActivity } private void ButtonOnClick(object sender, EventArgs e)//按键的单击事件 { FecitButton btnKey = sender as FecitButton;//获取当前按键的信息 if (btnKey == null)//如果按键为空值 return; SendKeyCommand(btnKey);//发送按键的信息 } /// <summary> /// 接收并发送按键信息 /// </summary> /// <param keyButton="FecitButton">按键信息</param> private void SendKeyCommand(FecitButton keyButton) { short key = Convert.ToInt16(keyButton.Tag.ToString());//获取当前键的键值 if (combinationVKButtonsMap.ContainsKey(key))//如果键值在键值列表中 { if (keyButton.Checked)//如果按钮处于按下状态 { SendKeyUp(key);//对按钮进行抬起操作 } else { SendKeyDown(key);//对按钮进行按下操作 } } else { //执行按钮按下和抬起的操作 SendKeyDown(key); SendKeyUp(key); } } /// <summary> /// 记录键盘的按下操作的值 /// </summary> /// <param key="short">键值</param> private void SendKeyDown(short key) { Input[] input = new Input[1];//实例化Input[] input[0].type = INPUT.KEYBOARD;//记录当有键值的类型 input[0].ki.wVk = key;//记录当前键值 input[0].ki.time = NativeMethods.GetTickCount();//获取自windows启动以来经历的时间长度(毫秒) //消息的输入 if (NativeMethods.SendInput((uint)input.Length, input, Marshal.SizeOf(input[0])) < input.Length) { throw new Win32Exception(Marshal.GetLastWin32Error());//指定错误的初始化 } } /// <summary> /// 记录键盘抬起操作的值 /// </summary> /// <param key="short">键值</param> private void SendKeyUp(short key) { Input[] input = new Input[1];//实例化Input[] input[0].type = INPUT.KEYBOARD;//记录当有键值的类型 input[0].ki.wVk = key;//记录当前键值 input[0].ki.dwFlags = KeyboardConstaint.KEYEVENTF_KEYUP; input[0].ki.time = NativeMethods.GetTickCount();//获取自windows启动以来经历的时间长度(毫秒) //消息的输入 if (NativeMethods.SendInput((uint)input.Length, input, Marshal.SizeOf(input[0])) < input.Length) { throw new Win32Exception(Marshal.GetLastWin32Error());//指定错误的初始化 } } //键盘的按下事件 private void HookOnGlobalKeyDown(object sender, HookEx.KeyExEventArgs e) { SetButtonStatus(e, true); } //键盘的抬起事件 private void HookOnGlobalKeyUp(object sender, HookEx.KeyExEventArgs e) { SetButtonStatus(e, false); } /// <summary> /// 设置当前按钮的状态 /// </summary> /// <param args="KeyExEventArgs">键信息</param> /// <param isDown="bool">标识,当前键是否按下</param> private void SetButtonStatus(HookEx.KeyExEventArgs args, bool isDown) { IList<FecitButton> buttonList = FindButtonList(args);//查找当有键 if (buttonList.Count <= 0)//如果没有找到 return;//退出本次操作 short key = (short)args.KeyValue;//获取当前键的键值 if (spacialVKButtonsMap.ContainsKey(key))//如果键/值列表中有该键 { if (!isDown)//如果按钮没有被按下 { FecitButton button = spacialVKButtonsMap[key][0];//设置按钮的信息 button.Checked = !button.Checked;//设置当前按钮为按下状态 } } else { foreach (FecitButton button in buttonList)//遍历IList中的所有按钮 { if (button == null)//如果按钮为空 break;//退出循环 button.Checked = isDown;//设置按钮的状态 } } } /// <summary> /// 鼠标事件 /// </summary> /// <param sener="object">鼠标对象</param> /// <param e="MouseExEventArgs">为MouseUp、MouseDown和MouseMove事件提供数据</param> private void HookOnMouseActivity(object sener, HookEx.MouseExEventArgs e) { Point location = e.Location;//获取鼠标的位置 if (e.Button == MouseButtons.Left)//如果是鼠标左键 { Rectangle captionRect = new Rectangle(this.Location, new Size(this.Width, SystemInformation.CaptionHeight));//获取窗体的所在区域 if (captionRect.Contains(location))//如果鼠标在该窗体范围内 { //设置窗体的扩展样式 NativeMethods.SetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE, (int)NativeMethods.GetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE) & (~KeyboardConstaint.WS_DISABLED)); //将消息发送给指定窗体 NativeMethods.SendMessage(this.Handle, KeyboardConstaint.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero); } else { //设置窗体的扩展样式 NativeMethods.SetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE, (int)NativeMethods.GetWindowLong(this.Handle, KeyboardConstaint.GWL_EXSTYLE) | KeyboardConstaint.WS_DISABLED); } } } /// <summary> /// 在键列表中查找键值 /// </summary> /// <param args="KeyExEventArgs">键信息</param> private IList<FecitButton> FindButtonList(HookEx.KeyExEventArgs args) { short key = (short)args.KeyValue;//获取键值 if (key == KeyboardConstaint.VK_LCONTROL || key == KeyboardConstaint.VK_RCONTROL)//如果是CTRL键 { key = KeyboardConstaint.VK_CONTROL;//记录CTRL键值 } else if (key == KeyboardConstaint.VK_LSHIFT || key == KeyboardConstaint.VK_RSHIFT)//如果是SHIFT键 { key = KeyboardConstaint.VK_SHIFT;//记录SHIFT键值 } else if (key == KeyboardConstaint.VK_LMENU || key == KeyboardConstaint.VK_RMENU)//如果是ALT键 { key = KeyboardConstaint.VK_MENU;//记录ALT键值 } else if (key == KeyboardConstaint.VK_RWIN)//如果是WIN键 { key = KeyboardConstaint.VK_LWIN;//记录WIN键值 } if (combinationVKButtonsMap.ContainsKey(key))//如果在IDictionary的集合中 { return combinationVKButtonsMap[key];//返回当前键的键值 } IList<FecitButton> buttonList = new List<FecitButton>();//实例化IList<FecitButton> foreach (Control ctrl in this.Controls)//遍历当前窗体中的所有控件 { FecitButton button = ctrl as FecitButton;//如果当前控件是FecitButton按钮 if (button == null)//如果当前按钮为空 continue;//重新循环 short theKey = Convert.ToInt16(button.Tag.ToString());//获取当前按钮的键值 if (theKey == key)//如果与当前操作的按钮相同 { buttonList.Add(button);//添加当前操作的按键信息 break; } } return buttonList; } }
public partial class FecitButton : Button { public FecitButton() { InitializeComponent(); base.Font = new Font("宋体", 9.75F, FontStyle.Bold); base.Width = 26; base.Height = 25; } private Color Color_Brush = Color.MediumPurple; private Color Color_Pen = Color.Indigo; public static bool MouseE = false; private bool TChecked = false; [Browsable(true), Category("按钮操作"), Description("设置按钮是否被按下,如按下,则为true")] public bool Checked { get { return TChecked; } set { TChecked = value; Invalidate(); } } protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { Color tem_colorb = Color_Brush; Color tem_colorp = Color_Pen; if (Checked) { Color_Brush = Color.Pink; Color_Pen = Color.PaleVioletRed; } else { Color_Brush = tem_colorb; Color_Pen = tem_colorp; } SolidBrush tem_Brush = new SolidBrush(Color_Brush); Pen tem_Pen = new Pen(new SolidBrush(Color_Pen), 2); e.Graphics.FillRectangle(tem_Brush, 0, 0, this.Width, this.Height); e.Graphics.DrawRectangle(tem_Pen, 1, 1, this.Width - 2, this.Height - 2); ProtractText(e.Graphics); } /// <summary> /// 鼠标移入控件的可见区域时触发 /// </summary> protected override void OnMouseEnter(EventArgs e) { Color_Brush = Color.LightSteelBlue; Color_Pen = Color.LightSlateGray; Invalidate(); base.OnMouseEnter(e); } /// <summary> /// 鼠标移出控件的可见区域时触发 /// </summary> protected override void OnMouseLeave(EventArgs e) { Color_Brush = Color.MediumPurple; Color_Pen = Color.Indigo; Invalidate(); base.OnMouseLeave(e); } private void ProtractText(Graphics g) { Graphics TitG = this.CreateGraphics();//创建Graphics类对象 string TitS = base.Text;//获取图表标题的名称 SizeF TitSize = TitG.MeasureString(TitS, this.Font);//将绘制的字符串进行格式化 float TitWidth = TitSize.Width;//获取字符串的宽度 float TitHeight = TitSize.Height;//获取字符串的高度 float TitX = 0;//标题的横向坐标 float TitY = 0;//标题的纵向坐标 if (this.Height > TitHeight) TitY = (this.Height - TitHeight) / 2F; else TitY = 1; if (this.Width > TitWidth) TitX = (this.Width - TitWidth) / 2F; else TitX = 2; Rectangle rect = new Rectangle((int)Math.Floor(TitX), (int)Math.Floor(TitY), (int)Math.Ceiling(TitWidth), (int)Math.Ceiling(TitHeight)); g.DrawString(TitS, base.Font,new SolidBrush(base.ForeColor), new PointF(TitX, TitY)); } }
internal static class KeyboardConstaint { internal static readonly short VK_F1 = 0x70; internal static readonly short VK_F2 = 0x71; internal static readonly short VK_F3 = 0x72; internal static readonly short VK_F4 = 0x73; internal static readonly short VK_F5 = 0x74; internal static readonly short VK_F6 = 0x75; internal static readonly short VK_F7 = 0x76; internal static readonly short VK_F8 = 0x77; internal static readonly short VK_F9 = 0x78; internal static readonly short VK_F10 = 0x79; internal static readonly short VK_F11 = 0x7A; internal static readonly short VK_F12 = 0x7B; internal static readonly short VK_LEFT = 0x25; internal static readonly short VK_UP = 0x26; internal static readonly short VK_RIGHT = 0x27; internal static readonly short VK_DOWN = 0x28; internal static readonly short VK_NONE = 0x00; internal static readonly short VK_ESCAPE = 0x1B; internal static readonly short VK_EXECUTE = 0x2B; internal static readonly short VK_CANCEL = 0x03; internal static readonly short VK_RETURN = 0x0D; internal static readonly short VK_ACCEPT = 0x1E; internal static readonly short VK_BACK = 0x08; internal static readonly short VK_TAB = 0x09; internal static readonly short VK_DELETE = 0x2E; internal static readonly short VK_CAPITAL = 0x14; internal static readonly short VK_NUMLOCK = 0x90; internal static readonly short VK_SPACE = 0x20; internal static readonly short VK_DECIMAL = 0x6E; internal static readonly short VK_SUBTRACT = 0x6D; internal static readonly short VK_ADD = 0x6B; internal static readonly short VK_DIVIDE = 0x6F; internal static readonly short VK_MULTIPLY = 0x6A; internal static readonly short VK_INSERT = 0x2D; internal static readonly short VK_OEM_1 = 0xBA; // ';:' for US internal static readonly short VK_OEM_PLUS = 0xBB; // '+' any country internal static readonly short VK_OEM_MINUS = 0xBD; // '-' any country internal static readonly short VK_OEM_2 = 0xBF; // '/?' for US internal static readonly short VK_OEM_3 = 0xC0; // '`~' for US internal static readonly short VK_OEM_4 = 0xDB; // '[{' for US internal static readonly short VK_OEM_5 = 0xDC; // '\|' for US internal static readonly short VK_OEM_6 = 0xDD; // ']}' for US internal static readonly short VK_OEM_7 = 0xDE; // ''"' for US internal static readonly short VK_OEM_PERIOD = 0xBE; // '.>' any country internal static readonly short VK_OEM_COMMA = 0xBC; // ',<' any country internal static readonly short VK_SHIFT = 0x10; internal static readonly short VK_CONTROL = 0x11; internal static readonly short VK_MENU = 0x12; internal static readonly short VK_LWIN = 0x5B; internal static readonly short VK_RWIN = 0x5C; internal static readonly short VK_APPS = 0x5D; internal static readonly short VK_LSHIFT = 0xA0; internal static readonly short VK_RSHIFT = 0xA1; internal static readonly short VK_LCONTROL = 0xA2; internal static readonly short VK_RCONTROL = 0xA3; internal static readonly short VK_LMENU = 0xA4; internal static readonly short VK_RMENU = 0xA5; internal static readonly short VK_SNAPSHOT = 0x2C; internal static readonly short VK_SCROLL = 0x91; internal static readonly short VK_PAUSE = 0x13; internal static readonly short VK_HOME = 0x24; internal static readonly short VK_NEXT = 0x22; internal static readonly short VK_PRIOR = 0x21; internal static readonly short VK_END = 0x23; internal static readonly short VK_NUMPAD0 = 0x60; internal static readonly short VK_NUMPAD1 = 0x61; internal static readonly short VK_NUMPAD2 = 0x62; internal static readonly short VK_NUMPAD3 = 0x63; internal static readonly short VK_NUMPAD4 = 0x64; internal static readonly short VK_NUMPAD5 = 0x65; internal static readonly short VK_NUMPAD5NOTHING = 0x0C; internal static readonly short VK_NUMPAD6 = 0x66; internal static readonly short VK_NUMPAD7 = 0x67; internal static readonly short VK_NUMPAD8 = 0x68; internal static readonly short VK_NUMPAD9 = 0x69; internal static readonly short KEYEVENTF_EXTENDEDKEY = 0x0001; internal static readonly short KEYEVENTF_KEYUP = 0x0002; internal static readonly int GWL_EXSTYLE = -20; internal static readonly int WS_DISABLED = 0X8000000; internal static readonly int WM_SETFOCUS = 0X0007; }
[StructLayout(LayoutKind.Sequential)] internal struct MOUSEINPUT { public int dx; public int dy; public int mouseData; public int dwFlags; public int time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] internal struct KEYBDINPUT { public short wVk; public short wScan; public int dwFlags; public int time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Explicit)] internal struct Input { [FieldOffset(0)] public int type; [FieldOffset(4)] public MOUSEINPUT mi; [FieldOffset(4)] public KEYBDINPUT ki; [FieldOffset(4)] public HARDWAREINPUT hi; } [StructLayout(LayoutKind.Sequential)] internal struct HARDWAREINPUT { public int uMsg; public short wParamL; public short wParamH; } internal class INPUT { public const int MOUSE = 0; public const int KEYBOARD = 1; public const int HARDWARE = 2; } internal static class NativeMethods { [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false)] internal static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = false)] internal static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); [DllImport("User32.dll", EntryPoint = "SendInput", CharSet = CharSet.Auto)] internal static extern UInt32 SendInput(UInt32 nInputs, Input[] pInputs, Int32 cbSize); [DllImport("Kernel32.dll", EntryPoint = "GetTickCount", CharSet = CharSet.Auto)] internal static extern int GetTickCount(); [DllImport("User32.dll", EntryPoint = "GetKeyState", CharSet = CharSet.Auto)] internal static extern short GetKeyState(int nVirtKey); [DllImport("User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)] internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); }
到此这篇关于C#实现虚拟键盘的实例详解的文章就介绍到这了,更多相关C#虚拟键盘内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
详解C#中Dictionary<TKey,TValue>的存储结构
无论是实际的项目中,还是在我们学习的过程中,都会重点的应用到Dictionary<TKey, TValue>这个存储类型,所以本文就来为大家介绍一下这一存储结构的相关知识,希望对大家有所帮助2023-11-11解析Silverlight调用WCF/Rest异常的解决方法
本篇文章对Silverlight调用WCF/Rest异常的解决方法进行了详细的分析介绍,需要的朋友参考下2013-05-05
最新评论