實現(xiàn)條碼槍的無焦點掃碼


????在上一家公司創(chuàng)業(yè)初期积锅,我接觸的第一個項目是醫(yī)院的供應(yīng)室消毒包管理系統(tǒng),幾乎一人之力用了兩個多月的時間推溃,完成了基本的開發(fā)工作昂利。回想起來铁坎,當(dāng)時有個設(shè)計印象深刻页眯。趁著還有記憶,記錄下來厢呵,供大家一時之需窝撵。

當(dāng)時開發(fā)的時候,對于物資的管理襟铭,自然離不開條碼槍的角色碌奉。設(shè)計的是無線條碼槍短曾,讓工作人員可以自由的在作業(yè)現(xiàn)場走動。但是有個用戶體驗問題赐劣,就是一般情況下嫉拐,條碼槍掃描的時候,都需要將輸入焦點放到文本框之中魁兼,這個限制會造成極為不好的用戶體驗婉徘。此外,在流程設(shè)計的時候咐汞,實際上一系列操作動作盖呼,是使用掃描不同命令條碼后,實現(xiàn)的化撕。比如啟動某功能几晤,掃碼后,確定繼續(xù)下一個動作等等植阴,全程不用碰PC機蟹瘾。

當(dāng)時工作現(xiàn)場的示意圖

所以問題的核心就在于是否可以接觸焦點必須放到文本框之中的限制。
此方法并不是原創(chuàng)掠手,但是原始代碼是對WinForm平臺進行開發(fā)的憾朴,被我修改為支持WPF平臺。并且原文的鏈接已經(jīng)失效喷鸽,所以這段代碼還是很有價值的伊脓。


現(xiàn)在放出幾個關(guān)鍵點的代碼,加以說明魁衙,全部代碼在最后放出鏈接:
1.掃描監(jiān)聽器BarcodeScannerListener

使用WindowInteropHelper獲取傳入窗體的句柄报腔,并且綁定ThreadFilterMessage事件,達到從而可以觸發(fā)ProcessRawInputMessage方法

/// <summary>
/// 將監(jiān)聽器附著到窗體上
/// </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>
/// 監(jiān)聽綁定
/// </summary>
/// <param name="hwnd">設(shè)備指針</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方法中剖淀,判斷傳入的字符串是否是掃碼槍設(shè)置的結(jié)束字符(掃碼的字符串是一個一個傳入的)纯蛾,如果不是,就加入到Buffer中纵隔,如果是翻诉,則觸發(fā)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方法中捌刮,則會調(diào)用界面初始化時碰煌,綁定的事件,傳入掃碼的字符串

/// <summary>
/// 觸發(fā)掃碼事件
/// </summary>
/// <param name="deviceInfo">掃碼設(shè)備信息</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.頁面調(diào)用

這里我使用的MVVM模式绅作,所以在ViewModel層調(diào)用芦圾,但是只要能拿到View的對象,在那一層都沒有關(guān)系

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設(shè)備管理器中个少,找到掃碼槍的設(shè)備ID洪乍,我這沒有圖上網(wǎng)找了一個

設(shè)備ID

將這個設(shè)備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>

最后實現(xiàn)的效果還是十分不錯的壳澳,只要是系統(tǒng)處于前臺(不太確定處于后臺是否好用,有點記不住了)茫经,條碼槍隨意掃描巷波,一竄操作下來,根本不用動鍵盤或鼠標(biāo)卸伞,因為所有的靠鍵盤鼠標(biāo)觸發(fā)的功能抹镊,也都是使用特定條碼定義了,用戶體驗十分不錯瞪慧。可惜的是部念,最后這個系統(tǒng)因為商務(wù)原因弃酌,沒有上線,雖然完成度已經(jīng)很高了儡炼,但是也廢棄了妓湘。

放個圖紀念一下吧

最后,掃碼關(guān)鍵源碼的下載鏈接

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乌询,一起剝皮案震驚了整個濱河市榜贴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌妹田,老刑警劉巖唬党,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鬼佣,居然都是意外死亡驶拱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門晶衷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蓝纲,“玉大人,你說我怎么就攤上這事晌纫∷懊裕” “怎么了滨攻?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵十嘿,是天一觀的道長。 經(jīng)常有香客問我偶宫,道長哥牍,這世上最難降的妖魔是什么露懒? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任闯冷,我火速辦了婚禮,結(jié)果婚禮上懈词,老公的妹妹穿的比我還像新娘蛇耀。我一直安慰自己,他們只是感情好坎弯,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布纺涤。 她就那樣靜靜地躺著,像睡著了一般抠忘。 火紅的嫁衣襯著肌膚如雪撩炊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天崎脉,我揣著相機與錄音拧咳,去河邊找鬼。 笑死囚灼,一個胖子當(dāng)著我的面吹牛骆膝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播灶体,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼阅签,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蝎抽?” 一聲冷哼從身側(cè)響起政钟,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎樟结,沒想到半個月后养交,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡瓢宦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年层坠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刁笙。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡破花,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疲吸,到底是詐尸還是另有隱情座每,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布摘悴,位于F島的核電站峭梳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜葱椭,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一捂寿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孵运,春花似錦秦陋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旷赖,卻和暖如春顺又,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背等孵。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工稚照, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俯萌。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓果录,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绳瘟。 傳聞我的和親對象是個殘疾皇子雕憔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫姿骏、插件糖声、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,121評論 4 61
  • 臨近年終報最后幾天,年終考評牽人心緒分瘦,沒必要那么緊張蘸泻,工作只是謀生的手段,并不是你的價值可以全部體現(xiàn)嘲玫,不是說評為...
    海深深閱讀 363評論 0 1
  • 天哪去团,我要喊出來了抡诞,怎么可以這么好看!沒什么胃口但是覺得應(yīng)該吃飯土陪,所以做了番茄炒蛋昼汗。一邊看一邊吃,科塔薩爾對細節(jié)的...
    imissgr閱讀 378評論 0 0