Winform開發框架之讀卡器和條碼掃描槍的數據接收處理

在咱們開發一些項目的時候,通常須要一些外圍的設備進行數據處理,如ID/IC讀卡器獲取卡號、激光條碼掃描槍、USB攝像頭、USB方式的小票據打印機(POS打印機)、USB來電錄音盒、普通打印機等一系列附屬設備。藉助這些設備,可使咱們的業務流程更嚴謹,輸入數據更方便,或者可以一些特殊的數據等功能。本文主要介紹其中的ID讀卡器(IC讀卡器)快速讀取卡號,以及實用激光條碼槍的條碼掃描錄入功能,後面的一些硬件設備的處理,後續文章在繼續介紹。安全

一、設備介紹

前面介紹的設備,在不少場合上均可能用到,如個人會員管理系統裏面,就須要用到下面的設備處理。框架

本文主要針對性瞭解ID讀卡器和條碼槍的設備數據處理,這兩種設備雖然不一樣,可是它們類似的地方就是都支持在光標處錄入數據的,就有點相似咱們的鍵盤快速錄入同樣,固然激光條碼槍也支持不少種方式的事件處理操做,這是後話。this

 

二、ID讀卡器數據讀取界面和條碼掃描槍讀取界面的分析介紹

在個人會員管理系統裏面,錄入卡號通常是經過ID讀卡器獲取的,在界面上設置一個能夠彈出錄入的文本框,也方便手工錄入卡號,以下面的界面功能所示。編碼

固然,有時候,咱們可能不須要提供手工錄入,那麼就不能經過光標錄入方式獲取掃描的內容,由於咱們把輸入框設置爲只讀的了,因此這種狀況,就就應該經過事件來獲取設備的輸入內容。spa

在條碼槍處理讀取條形碼或者二維碼的時候,咱們通常都是和商品相關的地方使用條形碼,二維碼也可使用,條形碼可能通常帶有數據供閱讀,二維碼則沒有,可是均可以經過設備讀取出來到文本框裏面,通常若是錄入,就停放光標在文本框就能夠了,如商品的信息的錄入。在咱們須要輸入條碼的地方點一下,而後操做條碼槍錄入條碼便可,這種不須要額外的代碼處理。code

可是對於一些咱們須要快速錄入商品信息的界面,如客戶消費界面,那麼就須要對條碼的事件進行處理了。orm

例以下面的界面,在消費確認前的產品錄入,咱們都是經過條碼槍的快速掃描產品進行錄入的,這時候條碼槍就代替了手工的錄入,咱們能夠每次掃描一次,就在列表裏面自動增長一個對應商品的記錄,很是方便的了。blog

 

三、通用的讀卡操做和條碼掃描槍操做實現

在前面小節介紹了一些利用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;
            }
        }
    }
相關文章
相關標籤/搜索