在前面小节介绍了一些利用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(); }
然后我们为了方便使用,还可以定义一个统一的处理读卡器和扫描枪的接收数据的小窗口。