C# USB扫码枪winForm处理方法


网上大神的方法是无焦点接收USB扫码枪数据,我的需求是当前窗口接收就行,没有必要设置全局键盘钩子。

自己琢磨了一个类,没有API调用:

    /// <summary>
    /// 条码解析类
    /// </summary>
    public class Cl_BarCodeReader
    {
        #region 属性
        /// <summary>
        /// 发布器委托
        /// </summary>
        /// <param name="Barcode">有效码值字符串</param>
        /// <param name="cl">条码种类</param>
        public delegate void ScanerDelegate(string Barcode, Barcode_Class cl);
        /// <summary>
        /// 接收到有效条码的事件发布器
        /// </summary>
        public event ScanerDelegate ScanerReceived;
        /// <summary>
        /// 条码信息字符串
        /// </summary>
        public string BarCode { get; set; }
        /// <summary>
        /// 按键数组
        /// </summary>
        public List<Keys> MyKeys { get; set; }
        /// <summary>
        /// 初始按键时间
        /// </summary>
        public long MyTime { get; set; }
        #endregion
        #region 构造
        /// <summary>
        /// 空白构造函数
        /// </summary>
        public Cl_BarCodeReader()
        {
            BarCode = "";
            MyKeys = new List<Keys>();
            MyTime = 0;
        }#endregion
        #region 编辑
        /// <summary>
        /// 处理一个捕获的按键键值,如果扫码完毕,触发接收事件ScanerReceived
        /// 传递包含的码值字符串和条码种类枚举
        /// 编码规则:nn...ED,n是数字,末尾两个字母ED
        /// 前两位数字表示预先规定的条码的种类/来源,例如:
        /// 01 - 执行跟踪号
        /// 02 - 计划跟踪号
        /// ...
        /// </summary>
        /// <param name="key">按键键值</param>
        public void Add(Keys key)
        {
            //忽略扫码枪传来的Shift键值
            if (key == Keys.ShiftKey) return;
            var tick = DateTime.Now.Ticks;
            //初次接收
            if (MyKeys.Count == 0)
            {
                //如果不是数字,不处理
                if (!char.IsDigit(Convert.ToChar(key))) return;
                MyKeys.Add(key);
                MyTime = tick;
                return;
            }
            //计算和第一个键值的时间差
            var tsp = tick - MyTime;
            /*
            //在即时窗口输出时间差、键值,调试用
            var tk = new Task(() => Debug.WriteLine(tsp.ToString() + " " + Convert.ToChar(key) + " " + key.ToString()));
            tk.Start();
            */
            //时间差大于50毫秒时,不是扫码枪按键,重新捕获
            if (tsp > 10000 * 50)
            {
                MyKeys.Clear();
                MyTime = 0;
                Add(key);
            }
            else
            {
                //检查第二位是否为数字,此处需根据条码的编码规则修改
                if (MyKeys.Count == 1)
                {
                    if (!char.IsDigit(Convert.ToChar(key)))
                    {
                        MyKeys.Clear();
                        MyTime = 0;
                        return;
                    }
                }
                MyKeys.Add(key);
                //当存储的键值超过4个时,检查是否结束
                if (MyKeys.Count > 4)
                {
                    //末两位是ED
                    if (MyKeys[MyKeys.Count - 2] == Keys.E && MyKeys[MyKeys.Count - 1] == Keys.D)
                    {
                        BarCode = "";
                        for (int i = 0; i < MyKeys.Count; i++)
                        {
                            BarCode += Convert.ToChar(MyKeys[i]);
                        }
                        MyKeys.Clear();
                        MyTime = 0;
                        var cd = Code();
                        //触发事件
                        if (!string.IsNullOrEmpty(cd))
                            ScanerReceived(cd, BarCodeClass());
                    }
                }
            }
        }
        #endregion
        #region 判断
        /// <summary>
        /// 判断当前的条码字符串是否有效
        /// </summary>
        /// <returns></returns>
        public bool IsEffect()
        {
            return IsEffect(BarCode);
        }
        /// <summary>
        /// 判断指定的条码字符串是否是有效条码
        /// </summary>
        /// <param name="barcode"></param>
        /// <returns></returns>
        public static bool IsEffect(string barcode)
        {
//长度检查
if (barcode.Length < 5) return false;
//前两位数字检查
if (!char.IsDigit(barcode, 0) || !char.IsDigit(barcode, 1)) return false;
//末两位是否是ED
if (barcode.Substring(barcode.Length - 2, 2) != "ED") return false;
//条码种类检查
if (BarCodeClass(barcode.Substring(0, 2)) == Barcode_Class.Unkown) return false; return true; } #endregion #region 信息 /// <summary> /// 返回当前条码字符串中的信息部分 /// 无效返回空字符串 /// </summary> /// <returns></returns> public string Code() { return Code(BarCode); } /// <summary> /// 返回条码字符串中的信息部分 /// </summary> /// <param name="barcode"></param> /// <returns></returns> public static string Code(string barcode) { if (IsEffect(barcode)) {
//去除前两位和末两位
return barcode.Substring(2, barcode.Length - 4); } else return ""; } /// <summary> /// 返回当前条码种类枚举 /// </summary> /// <returns></returns> public Barcode_Class BarCodeClass() { if (BarCode.Length > 4) return BarCodeClass(BarCode.Substring(0, 2)); else return Barcode_Class.Unkown; } /// <summary> /// 返回当前条码种类名称 /// </summary> /// <returns></returns> public string BarCodeClassName() { var bclass = BarCodeClass();
//GetEnumDescription是一个利用反射获取枚举自定义特性的方法,具体实现可以百度
return Cl_General.GetEnumDescription(bclass); } /// <summary> /// 依据条码前缀,返回条码种类枚举 /// </summary> /// <param name="codepre"></param> public static Barcode_Class BarCodeClass(string codepre) { switch (codepre) { case "01": return Barcode_Class.CarryTrackCode; case "02": return Barcode_Class.PlanTrackCode; default: return Barcode_Class.Unkown; } } /// <summary> /// 依据条码前缀,返回条码种类名称 /// </summary> /// <param name="codepre"></param> /// <returns></returns> public static string BarCodeClassName(string codepre) { var bclass = BarCodeClass(codepre);
//GetEnumDescription是一个利用反射获取枚举自定义特性的方法,具体实现可以百度
return Cl_General.GetEnumDescription(bclass); } #endregion } /// <summary> /// 条码种类枚举 /// </summary> public enum Barcode_Class { [Description("未知")] /// <summary> /// 未知 /// </summary> Unkown, [Description("执行跟踪号")] /// <summary> /// 执行跟踪号 /// </summary> CarryTrackCode, [Description("计划跟踪号")] /// <summary> /// 计划跟踪号 /// </summary> PlanTrackCode }

我把这个类放在了我的基窗口里,继承窗口只需要override ScanerHandler来实现具体的收到条码方法,窗体Load时调用一次SetBarCodeReader即可:

public partial class fm_BaseForm : Form
    {
        protected Cl_BarCodeReader BReader = null;
        /// <summary>
        /// 窗体键抬起事件处理过程,用于截获扫码枪消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void Form_KeyUp(object sender, KeyEventArgs e)
        {
            BReader.Add(e.KeyCode);
        }
        /// <summary>
        /// 启用扫码枪监视对象
        /// </summary>
        protected virtual void SetBarCodeReader(bool setkeypre = true)
        {
            if (setkeypre)
            {
                this.KeyPreview = true;
                this.KeyUp += Form_KeyUp;
            }
            if (BReader == null)
            {
                BReader = new Cl_BarCodeReader();
                BReader.ScanerReceived += ScanerHandler;
            }
        }
        /// <summary>
        /// 停止扫码枪监视对象
        /// </summary>
        protected virtual void StopBarCodeReader(bool setkeypre = true)
        {
            if (setkeypre)
            {
                this.KeyUp -= Form_KeyUp;
                this.KeyPreview = false;
            }
            if (BReader != null)
            {
                BReader.ScanerReceived -= ScanerHandler;
                BReader = null;
            }
        }
        /// <summary>
        /// 收到有效条码时的处理过程
        /// </summary>
        /// <param name="bcode"></param>
        protected virtual void ScanerHandler(string bcode, Barcode_Class cl)
        {
            //收到有效条码时的详细过程...

        }
}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM