在我们开发一些项目的时候,一般需要一些外围的设备进行数据处理,如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 = ;
private const string CARD_CODE_START = ""; /// <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 = ;
_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));
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;
}
}
}

Winform开发框架之读卡器和条码扫描枪的数据接收处理的更多相关文章

  1. Winform开发框架之权限管理系统改进的经验总结(4)-一行代码实现表操作日志记录

    在前面介绍了几篇关于我的权限系统改进的一些经验总结,本篇继续这一系列主体,介绍如何一行代码实现重要表的操作日志记录.我们知道,在很多业务系统里面,数据是很敏感的,特别对于一些增加.修改.删除等关键的操 ...

  2. Winform开发框架的重要特性总结

    从事Winform开发框架的研究和推广,也做了有几个年头了,从最初的项目雏形到目前各种重要特性的加入完善,是经过了很多项目的总结归纳和升华,有些则是根据客户需要或者应用前景的需要进行的完善,整个Win ...

  3. [转]Winform开发框架的重要特性总结

    本文转自:https://www.cnblogs.com/wuhuacong/p/3199829.html 从事Winform开发框架的研究和推广,也做了有几个年头了,从最初的项目雏形到目前各种重要特 ...

  4. Winform开发框架之通用数据导入导出操作的事务性操作完善

    1.通用数据导入导出操作模块回顾 在我的Winfrom开发框架里面,有一个通用的导入模块,它在默默处理这把规范的Excel数据导入到不同的对象表里面,一直用它来快速完成数据导入的工作.很早在随笔< ...

  5. 在Winform开发框架中,利用DevExpress控件实现数据的快速录入和选择

    在实际的项目开发过程中,有好的控件或者功能模块,我都是想办法尽可能集成到我的WInform开发框架中,这样后面开发项目起来,就可以节省很多研究时间,并能重复使用,非常高效方便.在我很早之前的一篇博客& ...

  6. asp.net中Winform开发框架之数据即时更新的实现

    在开篇之前,首先介绍一下Winform开发框架中的界面层的继承关系,首先我把所有窗体区分为三类,一类是普通的窗体,一类编辑窗体,还有一类是列表显示窗体.窗体的集成可以封装处理很多东西,良好的封装和继承 ...

  7. 基于Enterprise Library的Winform开发框架实现支持国产达梦数据库的扩展操作

    由于一个客户朋友的需求,需要我的Winform开发框架支持国产达梦数据库的操作,这个数据库很早就听过,但是真正一般项目用的很少,一般在一些特殊的项目可能需要用到.由于我的Winform开发框架,是基于 ...

  8. Winform开发框架中实现同时兼容多种数据库类型处理

    在很多应用系统里面,虽然一般采用一种数据库运行,但是由于各种情况的需要,可能业务系统会部署在不同类型的数据库上,如果开发的系统能够很方便支持多种数据库的切换,那可以为我们减少很多烦恼,同时提高系统的适 ...

  9. Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(2)

    本篇继续上篇<Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(1)>来对Winform开发框架之存储过程的支持进行介绍,上篇主要介绍了SQLServer和Oracle两 ...

随机推荐

  1. Angular ngClick 阻止冒泡和默认行为

    这其实是一个很简单的问题,如果你认真查看过Angular官方的API文档,本来不想记录的.但是这个问题不止一次的被人问起,所以今天在记录在这里. 在Angular中已经对一些ng事件如ngClick, ...

  2. 基础调试命令 - .dump/.dumpcap/.writemem/!runaway

    Windbg是windows平台上强大的调试器,它相对于其他常见的IDE集成的调试器有几个重要的优势, Windbg可以做内核态调试 Windbg可以脱离源代码进行调试 Windbg可以用来分析dum ...

  3. 自定义路径创建Cocos2d-x项目

    自定义路径创建Cocos2d-x项目 本文介绍windows下面如何优雅的创建Cocos2d-x项目.为何称之为优雅,是因为现在网上流传的一些创建方法有一些问题.大致内容如下: l  使用VS向导创建 ...

  4. java提高篇(一)-----理解java的三大特性之封装

    从大二接触java开始,到现在也差不多三个年头了.从最基础的HTML.CSS到最后的SSH自己都是一步一个脚印走出来的,其中开心过.失落过.寂寞过.虽然是半道出家但是经过自己的努力也算是完成了“学业” ...

  5. 深入探究js中无所不在的this

    黄金守则: this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window而当函数被作为某个对象的方法调用时, this等于那个对象. 下面是一些相关实践: --------- ...

  6. 04- Shell脚本学习--条件控制和循环语句

    条件判断:if语句 语法格式: if [ expression ] then Statement(s) to be executed if expression is true fi 注意:expre ...

  7. Java程序员的日常—— 基于类的策略模式、List<?>与List、泛型编译警告、同比和环比

    早晨起得太早,昨晚睡得太晚,一天都迷迷糊糊的.中午虽然睡了半个小时,可是依然没有缓过来.整个下午都在混沌中....不过今天下载了一款手游--<剑侠情缘>,感觉不错,喜欢这种类型的游戏. 今 ...

  8. MyBatis学习总结(五)——实现关联表查询

    一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) 1.2.创建表和数据 创建一张教师表和班级表,这里我们假设一个老师只负责教一个班,那么老师和班级之间的关系就是一种一对一的关 ...

  9. Linux设置SFTP服务用户目录权限

    我们有时会遇到这样的需求,限制一个Linux用户,让他只能在指定的目录下进行添加.修改.删除操作,并且只能使用sftp登录服务器,不能用ssh操作.这些可以通过配置sftp服务实现. 提供sftp服务 ...

  10. DateUtil

    //有些地方需要修改 import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDate ...