事件起因:

  搜狗拼音有几个称号(光速超人:要求最快打字速度 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、选择速度开始自动打字  

      c# 搜狗拼音输入法,刷输入速度和累计输入-冯金伟博客园c# 搜狗拼音输入法,刷输入速度和累计输入-冯金伟博客园

源码下载地址:

  http://pan.baidu.com/s/1i3Ek4b7 百度云盘