文档章节

Winform开发框架之读卡器和条码扫描枪的数据接收处理

科趣网
 科趣网
发布于 2017/05/04 15:53
字数 1771
阅读 12
收藏 1

在我们开发一些项目的时候,一般需要一些外围的设备进行数据处理,如ID/IC读卡器获取卡号、激光条码扫描枪、USB摄像头、USB方式的小票据打印机(POS打印机)、USB来电录音盒、普通打印机等一系列附属设备。借助这些设备,可以使我们的业务流程更严谨,输入数据更方便,或者能够一些特殊的数据等功能。本文主要介绍其中的ID读卡器(IC读卡器)快速读取卡号,以及实用激光条码枪的条码扫描录入功能,后面的一些硬件设备的处理,后续文章在继续介绍。

1、设备介绍

前面介绍的设备,在很多场合上都可能用到,如我的会员管理系统里面,就需要用到下面的设备处理。

本文主要针对性了解ID读卡器和条码枪的设备数据处理,这两种设备虽然不同,但是它们相似的地方就是都支持在光标处录入数据的,就有点类似我们的键盘快速录入一样,当然激光条码枪也支持很多种方式的事件处理操作,这是后话。

 

2、ID读卡器数据读取界面和条码扫描枪读取界面的分析介绍

在我的会员管理系统里面,录入卡号一般是通过ID读卡器获取的,在界面上设置一个可以弹出录入的文本框,也方便手工录入卡号,如下面的界面功能所示。

当然,有时候,我们可能不需要提供手工录入,那么就不能通过光标录入方式获取扫描的内容,因为我们把输入框设置为只读的了,所以这种情况,就就应该通过事件来获取设备的输入内容。

在条码枪处理读取条形码或者二维码的时候,我们一般都是和商品相关的地方使用条形码,二维码也可以使用,条形码可能一般带有数据供阅读,二维码则没有,但是都可以通过设备读取出来到文本框里面,一般如果录入,就停放光标在文本框就可以了,如商品的信息的录入。在我们需要输入条码的地方点一下,然后操作条码枪录入条码即可,这种不需要额外的代码处理。

但是对于一些我们需要快速录入商品信息的界面,如客户消费界面,那么就需要对条码的事件进行处理了。

例如下面的界面,在消费确认前的产品录入,我们都是通过条码枪的快速扫描产品进行录入的,这时候条码枪就代替了手工的录入,我们可以每次扫描一次,就在列表里面自动增加一个对应商品的记录,非常方便的了。

 

3、通用的读卡操作和条码扫描枪操作实现

在前面小节介绍了一些利用ID读卡器录入数据和使用条码枪的场景,对于如果是在可输入文本框里面获得内容,不用任何编码,如果是在只读界面或者窗体上获得设备的数据,那么就可以通过事件进行处理了,那么读卡器和扫描枪的事件应该如何处理的呢。

我的做法,是统一在我的Winform开发框架的界面层基类模块里面,增加一些硬件相关的处理类和界面,这样在各个框架派生出来的项目就可以很方便使用了。

其中Device里面的CardReader就是IC、ID读卡器获取操作的处理,一般来说,这些卡都是以00开始的,所以我们的处理类,通过一个Time来控制连续获取数据的处理就可以了,主要就是监听KeyUp事件。

 

以CardReader为例,它的完整代码如下所示。

复制代码

/// <summary>
    /// 读卡器封装类
    /// </summary>
    public class CardReader
    {
        private Control _hostCtrl;
        private string _cardCode;
        private Timer _timer;
        private const int CARD_CODE_LEN = 10;
        private const string CARD_CODE_START = "00";

        /// <summary>
        /// 读卡器读到一张卡的事件
        /// </summary>
        public event CardReadEventHandler CardRead;

        /// <summary>
        /// 默认读卡器(挂在主窗体上,会被主窗体初始化,在模块里用肯定是安全的)
        /// </summary>
        public static CardReader Default { get; set; }

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="hostCtrl">接受键盘事件的宿主控件</param>
        public CardReader(Control hostCtrl)
        {
            _hostCtrl = hostCtrl;
            if (_hostCtrl is Form)
            {
                (_hostCtrl as Form).KeyPreview = true;
            }
            _hostCtrl.KeyUp += new KeyEventHandler(hostCtrl_KeyUp);
            _cardCode = "";
            _timer = new Timer();
            _timer.Interval = 20;
            _timer.Tick += new EventHandler(timer_Tick);
            _timer.Start();
        }

        /// <summary>
        /// 判断是否卡号
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static bool IsCardCode(string code)
        {
            return code.Length == CARD_CODE_LEN && code.StartsWith(CARD_CODE_START);
        }

        /// <summary>
        /// 定时器到期的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_Tick(object sender, EventArgs e)
        {
            //达到一定的位数才开始判断
            if (_cardCode.Length >= CARD_CODE_LEN)
            {
                _cardCode = _cardCode.Trim((char)13);
                if (IsCardCode(_cardCode))
                {
                    _timer.Stop();
                    OnCardRead(_cardCode);
                }
            }
            _cardCode = "";
            _timer.Start();
        }

        /// <summary>
        /// 监听按键弹起的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hostCtrl_KeyUp(object sender, KeyEventArgs e)
        {
            _timer.Stop();
            _cardCode = _cardCode + (char)e.KeyValue;
            _timer.Start();
        }

        private void OnCardRead(string scanCode)
        {
            if (CardRead != null)
            {
                CardRead(scanCode);
            }
        }

    }

    /// <summary>
    /// 读卡器读到一张卡的事件处理委托
    /// </summary>
    /// <param name="cardCode"></param>
    public delegate void CardReadEventHandler(string cardCode);

复制代码

 

CardReader封装类, 它的使用操作如下所示。我们通过事件就可以获取到完整的输入内容,然后进行数据的绑定或处理即可,代码如下所示。

复制代码

public partial class FrmProcessConsumption : BaseDock
    {
        /// <summary>
        /// 会员信息
        /// </summary>
        private MemberInfo memberInfo { get; set; }

        /// <summary>
        /// 读卡器接口
        /// </summary>
        private CardReader cardReader;

        public FrmProcessConsumption()
        {
            InitializeComponent();

             ................................

            cardReader = new CardReader(this);
            cardReader.CardRead += new CardReadEventHandler(cardReader_CardRead);   
        }

        void cardReader_CardRead(string cardCode)
        {
            this.txtMember_CardNo.Text = cardCode;

            BindMemberData();
        }

复制代码

 

然后我们为了方便使用,还可以定义一个统一的处理读卡器和扫描枪的接收数据的小窗口。

这个弹出的小窗口用来处理读卡器,扫描枪等信息的录入就可以了,当然上述的如CardReader/USBScanner还是可以独立使用,如我们在一个只读控件或者窗口里面,一样可以监听到对应的设备数据读取操作,但设备有数据读取完成过后,就会触发相应的事件了。

下面代码就是上面设备信息读取的代码

复制代码

/// <summary>
    /// 读卡器、USB条码扫描器、串口条码扫描器数据读取及显示窗体
    /// </summary>
    public partial class DeviceReaderDialog : BaseForm
    {
        private CardReader _cardReader;
        private USBScanner _usbScanner;public DeviceReaderDialog(DeviceType type = DeviceType.Card)
        {
            InitializeComponent();
            //能手填
            this.Readonly = false;

            if (type == DeviceType.Card)
            {
                this._cardReader = new CardReader(this);
                this._cardReader.CardRead += new CardReadEventHandler(_cardReader_CardRead);
            }
            else if (type == DeviceType.UsbScanner)
            {
                this._usbScanner = new USBScanner(this);
                this._usbScanner.ScannerRead += new ScannerReadEventHandler(Scanner_ScannerRead);
            }
        }

        void Scanner_ScannerRead(string scanCode)
        {
            this.txtCode.Text = scanCode;
            DialogResult = DialogResult.OK;
        }

        void _cardReader_CardRead(string cardCode)
        {
            this.txtCode.Text = cardCode;
            DialogResult = DialogResult.OK;
        }

        public string Code
        {
            get { return txtCode.Text; }
        }

        public bool Readonly
        {
            get { return txtCode.Properties.ReadOnly; }
            set
            {
                txtCode.Properties.ReadOnly = value;
                this.btnOK.Enabled = !value;
                this.btnOK.Visible = !value;
            }
        }

        private void DeviceReaderDialog_Load(object sender, EventArgs e)
        {
            if (!this.Readonly)
            {
                this.KeyDown += new KeyEventHandler(DeviceReaderDialog_KeyDown);
            }
        }

        void DeviceReaderDialog_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.DialogResult = DialogResult.OK;
            }
        }
    }

复制代码

 

推荐一款适合库存管理专用扫描枪:FS01指环式条码扫描枪

© 著作权归作者所有

共有 人打赏支持
科趣网
粉丝 1
博文 16
码字总数 11803
作品 0
深圳
网页/平面设计
私信 提问
基于MVC4+EasyUI的Web开发框架经验总结(16)--使用云打印控件C-Lodop打印页面或套打报关运单信息

在最新的MVC4+EasyUI的Web开发框架里面,我整合了关于网购运单处理的一个模块,其中整合了客户导单、运单合并、到货扫描、扣仓、出仓、查询等各个模块的操作,里面涉及到一些运单套打的操作,...

walb呀
2017/12/04
0
0
S2JH系列分享:基于JasperReport+Applet的“可编辑”(套打)打印报表功能

S2JH项目首页:http://www.oschina.net/p/s2jh,集结最新主流时尚开源技术的面向企业级Web应用的基础开发框架,提供一个J2EE相关主流开源技术架构整合及一些企业应用基础通用功能和组件的设计...

EntDIY
2014/05/21
2.5K
10
现在有安卓平台的二维码扫描器,有没有可以读取RFID标签的读卡器呀?

求助,我想设计一个安卓平台上可以读取RFID标签的读卡器,就像二维码扫描一样调用照相机,但是不知道用什么方法实现一个读取RFID标签的这样一个读卡器,因为RFID标签不是像条码那样扫描的,是...

妍妍丁
2014/09/15
376
0
这样的 freeMarker ftl 文件如何写。同一页面多次查询,多次填充数据

这种情况怎么处理? web模式的。 就像是在超市收银时,用扫描枪扫条码: (前台)扫一个条码,(后台)查询一个商品,(servlet+mysql)然后展现在页面上。 再扫描,再查询,... 这样,只有一...

chworld
2012/11/05
536
3
基于条码的库存管理系统 - barCode-storage

基于条码的库存管理系统 项目介绍 该系统采用php+Android(本项目分web、Android两个分支)共同开发完成。安卓端模拟扫描枪,web端负责显示及管理。 软件架构 安装教程 导入sql文件到数据库。...

NB-One
11/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

RestClientUtil和ConfigRestClientUtil区别说明

RestClientUtil directly executes the DSL defined in the code. ConfigRestClientUtil gets the DSL defined in the configuration file by the DSL name and executes it. RestClientUtil......

bboss
35分钟前
6
0

中国龙-扬科
昨天
1
0
Linux系统设置全局的默认网络代理

更改全局配置文件/etc/profile all_proxy="all_proxy=socks://rahowviahva.ml:80/"ftp_proxy="ftp_proxy=http://rahowviahva.ml:80/"http_proxy="http_proxy=http://rahowviahva.ml:80/"......

临江仙卜算子
昨天
5
0
java框架学习日志-6(bean作用域和自动装配)

本章补充bean的作用域和自动装配 bean作用域 之前提到可以用scope来设置单例模式 <bean id="type" class="cn.dota2.tpye.Type" scope="singleton"></bean> 除此之外还有几种用法 singleton:......

白话
昨天
8
0
在PC上测试移动端网站和模拟手机浏览器的5大方法

总结很全面,保存下来以备不时之需。原文地址:https://www.cnblogs.com/coolfeng/p/4708942.html

kitty1116
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部