• c# 搜狗拼音输入法,刷输入速度和累计输入


    事件起因:

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

          

    源码下载地址:

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

  • 相关阅读:
    分布式系统唯一ID生成方案汇总
    百度开源的分布式 id 生成器
    全局唯一ID生成器
    VisualSVN Server迁移的方法
    SQL Server 函数 LEN 与 DATALENGTH的区别
    SQLServer中DataLength()和Len()两内置函数的区别
    sql server 查询ntext字段长度
    JAVA使用POI如何导出百万级别数据
    Java 使用stringTemplate导出大批量数据excel(百万级)
    Java 两个日期间的天数计算
  • 原文地址:https://www.cnblogs.com/binglab/p/4721005.html
Copyright © 2020-2023  润新知