事件起因:
搜狗拼音有几个称号(光速超人:要求最快打字速度 200字/m,一代文豪:要求累计输入字数达200000)一直没有那么快的速度,就想用.net来实现。
相关技术:
1、winform基本控件使用
2、多线程开发
3、C# Win32api函数调用
核心代码
1、在窗体中放入两个按钮 分别名称为:开始(name:btnStart) 停止(btnStop)
2、添加一个下拉框为 cbSpeend 输入速度下拉选项
3、添加文本框命名为 txtInWord
4、后台需要引用命名空间
1 using System.Runtime.InteropServices;
5、导入键盘输入方法SendInput,该方法包含了对键盘,鼠标,硬件输入的底层方法。定义代码如下
1 //导入SendInput方法 2 [DllImport("user32.dll")] 3 public static extern UInt32 SendInput(UInt32 nInputs, ref INPUT pInputs, int cbSize); 4 5 //输入结构体 6 [StructLayout(LayoutKind.Explicit)] 7 public struct INPUT 8 { 9 [FieldOffset(0)] 10 public Int32 type; 11 [FieldOffset(4)] 12 public KEYBDINPUT ki; 13 [FieldOffset(4)] 14 public MOUSEINPUT mi; 15 [FieldOffset(4)] 16 public HARDWAREINPUT hi; 17 } 18 19 //鼠标输入结构体 20 [StructLayout(LayoutKind.Sequential)] 21 public struct MOUSEINPUT 22 { 23 public Int32 dx; 24 public Int32 dy; 25 public Int32 mouseData; 26 public Int32 dwFlags; 27 public Int32 time; 28 public IntPtr dwExtraInfo; 29 } 30 31 //键盘输入结构体 32 [StructLayout(LayoutKind.Sequential)] 33 public struct KEYBDINPUT 34 { 35 public Int16 wVk; 36 public Int16 wScan; 37 public Int32 dwFlags; 38 public Int32 time; 39 public IntPtr dwExtraInfo; 40 } 41 42 //硬件输入结构体 43 [StructLayout(LayoutKind.Sequential)] 44 public struct HARDWAREINPUT 45 { 46 public Int32 uMsg; 47 public Int16 wParamL; 48 public Int16 wParamH; 49 } 50 //键盘输入 51 public const int INPUT_KEYBOARD = 1;
View Code
6、定义软件中需要使用的基本变量,包含_flag是否继续输入,_thread当前打字的线程,_spend线程暂停的时间定义代码如下
1 //定义状态 2 bool _flag = true; 3 //定义键盘输入的速度 4 private int _spend = 800; 5 //定义线程 6 private Thread _t;
7、定义一个模型 Info 用于下拉框的数据源
/// <summary> /// info下拉框数据源 /// </summary> public class Info { public string Name { get; set; } public string Id { get; set; } }
8、初始化下拉框,在构造函数中初始化
/// <summary> /// 构造函数 /// </summary> public Form1() { InitializeComponent(); btnStop.Enabled = false; //初始化下拉框 IList<Info> infoList = new List<Info>(); Info info1 = new Info() { Id = "300", Name = "快速(200字/分)" }; Info info2 = new Info() { Id = "500", Name = "中速(120字/分)" }; Info info3 = new Info() { Id = "800", Name = "慢速(75字/分)" }; infoList.Add(info1); infoList.Add(info2); infoList.Add(info3); cbSpeend.DataSource = infoList; cbSpeend.ValueMember = "Id"; cbSpeend.DisplayMember = "Name"; }
9、开始按钮单击事件,单击开始按钮后启动线程开始自动打字。同事禁用开始和下拉框
1 /// <summary> 2 /// 开始按钮单击事件 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void btnStart_Click(object sender, EventArgs e) 7 { 8 _flag = true; 9 btnStart.Enabled = false; 10 cbSpeend.Enabled = false; 11 btnStop.Enabled = true; 12 _spend = int.Parse(cbSpeend.SelectedValue.ToString()); 13 //初始化线程 14 _thread = new Thread(KeyBoardStart); 15 _thread.IsBackground = true; 16 _thread.Start(); 17 txtInWord.Focus(); 18 } 19 20 private void KeyBoardStart() 21 { 22 while (_flag) 23 { 24 try 25 { 26 //点击A键 27 INPUT inDown = new INPUT(); 28 inDown.type = INPUT_KEYBOARD; 29 inDown.ki.wVk = (int)Keys.A; 30 SendInput(1, ref inDown, Marshal.SizeOf(inDown)); 31 //点击空格键 32 inDown = new INPUT(); 33 inDown.type = INPUT_KEYBOARD; 34 inDown.ki.wVk = (int)Keys.Space; 35 SendInput(1, ref inDown, Marshal.SizeOf(inDown)); 36 //线程暂停 37 Thread.Sleep(_spend); 38 } 39 catch (Exception ex) 40 { 41 MessageBox.Show(ex.Message); 42 } 43 } 44 45 MessageBox.Show(@"打字结束"); 46 //启用按钮开始 47 SetBtnEnabled(btnStart, true); 48 //禁用停止按钮 49 SetBtnEnabled(btnStop, false); 50 //启用下拉框 51 SetComEnabled(cbSpeend, true); 52 }
View Code
10、开始打字线程中使用了委托来设置按钮和下拉框的状态,这样可以使线程安全。同事定义设置按钮状态的安全方法以及设置下拉框的安全方法。
1 /// <summary> 2 /// 定义委托 设置按钮的状态 3 /// </summary> 4 /// <param name="btn">按钮</param> 5 /// <param name="b">false:禁用;true:启用</param> 6 delegate void SetBtnEnabledDel(Button btn, bool b); 7 /// <summary> 8 /// 定义委托 设置下拉框的状态 9 /// </summary> 10 /// <param name="cb">下拉框</param> 11 /// <param name="b">false:禁用;true:启用</param> 12 delegate void SetComEnabledDel(ComboBox cb, bool b); 13 14 /// <summary> 15 /// 设置下拉框的属性 16 /// </summary> 17 /// <param name="cb"></param> 18 /// <param name="b"></param> 19 private void SetComEnabled(ComboBox cb, bool b) 20 { 21 if (cb.InvokeRequired) 22 { 23 //在使用用委托调用自己 24 SetComEnabledDel sbe = SetComEnabled; 25 Invoke(sbe, cb, b); 26 } 27 else 28 { 29 cb.Enabled = b; 30 } 31 } 32 33 /// <summary> 34 /// 设置按钮的状态 35 /// </summary> 36 /// <param name="btn"></param> 37 /// <param name="b"></param> 38 private void SetBtnEnabled(Button btn, bool b) 39 { 40 if (btn.InvokeRequired) 41 { 42 //在使用用委托调用自己 43 SetBtnEnabledDel sbe = SetBtnEnabled; 44 Invoke(sbe, btn, b); 45 } 46 else 47 { 48 btn.Enabled = b; 49 } 50 }
View Code
11、定义停止按钮事件,需要将,输入状态改为false。关闭窗体的时候清理窗体的子线程。
1 /// <summary> 2 /// 停止按钮事件 3 /// </summary> 4 /// <param name="sender"></param> 5 /// <param name="e"></param> 6 private void btnStop_Click(object sender, EventArgs e) 7 { 8 _flag = false; 9 } 10 11 /// <summary> 12 /// 关闭窗体事件 13 /// </summary> 14 /// <param name="sender"></param> 15 /// <param name="e"></param> 16 private void Form1_FormClosing(object sender, FormClosingEventArgs e) 17 { 18 try 19 { 20 if (_thread != null) 21 { 22 //清除线程 23 _thread.DisableComObjectEagerCleanup(); 24 } 25 } 26 catch (Exception ex) 27 { 28 MessageBox.Show(ex.Message); 29 } 30 }
View Code
功能截图:
1、首先运行程序
2、将输入发切换到中文
3、选择速度开始自动打字
源码下载地址: