Winform開發框架之讀卡器和條碼掃描槍的數據接收處理
在我們開發一些項目的時候,一般需要一些外圍的設備進行數據處理,如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指環式條碼掃描槍
推薦閱讀:
TAG:條形碼 |