实现条码枪的无焦点扫码


    在上一家公司创业初期,我接触的第一个项目是医院的供应室消毒包管理系统,几乎一人之力用了两个多月的时间,完成了基本的开发工作。回想起来,当时有个设计印象深刻。趁着还有记忆,记录下来,供大家一时之需。

当时开发的时候,对于物资的管理,自然离不开条码枪的角色。设计的是无线条码枪,让工作人员可以自由的在作业现场走动。但是有个用户体验问题,就是一般情况下,条码枪扫描的时候,都需要将输入焦点放到文本框之中,这个限制会造成极为不好的用户体验。此外,在流程设计的时候,实际上一系列操作动作,是使用扫描不同命令条码后,实现的。比如启动某功能,扫码后,确定继续下一个动作等等,全程不用碰PC机。

当时工作现场的示意图

所以问题的核心就在于是否可以接触焦点必须放到文本框之中的限制。
此方法并不是原创,但是原始代码是对WinForm平台进行开发的,被我修改为支持WPF平台。并且原文的链接已经失效,所以这段代码还是很有价值的。


现在放出几个关键点的代码,加以说明,全部代码在最后放出链接:
1.扫描监听器BarcodeScannerListener

使用WindowInteropHelper获取传入窗体的句柄,并且绑定ThreadFilterMessage事件,达到从而可以触发ProcessRawInputMessage方法

/// <summary>
/// 将监听器附着到窗体上
/// </summary>
/// <param name="form">需要附着的窗体(WPF)</param>
public void Attach(Window form)
{
    var helper = new WindowInteropHelper(form);
    IntPtr hwnd = helper.Handle;
    form.KeyDown += (sender, args) =>
    {
        if (_ControlHandled)
        {
            args.Handled = true;
            _ControlHandled = false;
        }
    };
    DoAttach(hwnd);
}

/// <summary>
/// 监听绑定
/// </summary>
/// <param name="hwnd">设备指针</param>
private void DoAttach(IntPtr hwnd)
{

    this.keystrokeBuffer = new StringBuilder();

    this.InitializeBarcodeScannerDeviceHandles();
    this.interopHelper.HookRawInput(hwnd);
    //this.HookHandleEvents(form);

    //this.AssignHandle(ptr);

    this.filter = new BarcodeScannerKeyDownMessageFilter();
    ComponentDispatcher.ThreadFilterMessage -= ComponentDispatcher_ThreadFilterMessage;
    ComponentDispatcher.ThreadFilterMessage += ComponentDispatcher_ThreadFilterMessage;
    //Application.AddMessageFilter(this.filter);
}

ProcessRawInputMessage方法中,判断传入的字符串是否是扫码枪设置的结束字符(扫码的字符串是一个一个传入的),如果不是,就加入到Buffer中,如果是,则触发FireBarcodeScanned方法

/// <summary>
/// 处理WM_INPUT消息
/// </summary>
/// <param name="rawInputHeader">rawInputHeader的指针</param>
/// <returns>按键是否被处理</returns>
private bool ProcessRawInputMessage(IntPtr rawInputHeader)
{
    BarcodeScannerDeviceInfo deviceInfo;
    bool handled;
    bool keystroke;
    string localBuffer;
    IntPtr rawInputDeviceHandle;

    handled = false;
    keystroke = false;
    localBuffer = string.Empty;
    rawInputDeviceHandle = IntPtr.Zero;

    this.interopHelper.GetRawInputInfo(
        rawInputHeader,
        ref rawInputDeviceHandle,
        ref keystroke,
        ref localBuffer);

    if (this.devices.TryGetValue(rawInputDeviceHandle, out deviceInfo) && keystroke)
    {
        handled = true;
        // 这里判断的是Tab按键,可以更换为其他按键
        if (localBuffer.Length == 1 && (localBuffer[0] == 0x09 || localBuffer[0] == '\t'))
        {
            this.FireBarcodeScanned(deviceInfo);
        }
        else
        {
            this.keystrokeBuffer.Append(localBuffer);
        }
    }

    return handled;
}

FireBarcodeScanned方法中,则会调用界面初始化时,绑定的事件,传入扫码的字符串

/// <summary>
/// 触发扫码事件
/// </summary>
/// <param name="deviceInfo">扫码设备信息</param>
private void FireBarcodeScanned(BarcodeScannerDeviceInfo deviceInfo)
{
    string barcode;
    EventHandler handler;

    barcode = this.keystrokeBuffer.ToString();

    if (barcode.Length > 0)
    {
        handler = this.BarcodeScanned;

        this.keystrokeBuffer = new StringBuilder();

        if (handler != null)
        {
            handler(this, new BarcodeScannedEventArgs(barcode, deviceInfo));
        }
    }
}

2.页面调用

这里我使用的MVVM模式,所以在ViewModel层调用,但是只要能拿到View的对象,在那一层都没有关系

BarcodeScannerListener = new BarcodeScannerListener();
BarcodeScannerListener.Attach((Window)GetView());
BarcodeScannerListener.BarcodeScanned += OnBarcodeScanned;

在传入的事件中,获取Barcode属性即可得到扫描的值

private void OnBarcodeScanned(object sender, EventArgs e)
{
    string barcode = ((BarcodeScannedEventArgs)e).Barcode;
    DoBarcodeScanned(barcode);
}

3.配置条码枪的硬件ID

需要在windows设备管理器中,找到扫码枪的设备ID,我这没有图上网找了一个

设备ID

将这个设备ID保存在App.cofig中,可以是多个

<!--在上面先配置一下-->
<configSections>
  <section name="barcodeScanner" type="Huitai.Cssd.Common.Util.Barcode.BarcodeScannerListenerConfigurationSection, Huitai.Cssd.Common" />
</configSections>

<barcodeScanner>
  <hardwareIds>
    <add id="HID#VID_05FE&PID_1010" />
  </hardwareIds>
</barcodeScanner>

最后实现的效果还是十分不错的,只要是系统处于前台(不太确定处于后台是否好用,有点记不住了),条码枪随意扫描,一窜操作下来,根本不用动键盘或鼠标,因为所有的靠键盘鼠标触发的功能,也都是使用特定条码定义了,用户体验十分不错。可惜的是,最后这个系统因为商务原因,没有上线,虽然完成度已经很高了,但是也废弃了。

放个图纪念一下吧

最后,扫码关键源码的下载链接

链接:https://306t.com/file/18510513-458449749

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 临近年终报最后几天,年终考评牵人心绪,没必要那么紧张,工作只是谋生的手段,并不是你的价值可以全部体现,不是说评为...
    海深深阅读 355评论 0 1
  • 天哪,我要喊出来了,怎么可以这么好看!没什么胃口但是觉得应该吃饭,所以做了番茄炒蛋。一边看一边吃,科塔萨尔对细节的...
    imissgr阅读 370评论 0 0