場輸入難題)
做LabVIEW上位機的朋友十有八九都有過這種經(jīng)歷設備已經(jīng)拉到客戶現(xiàn)場操作面板是觸摸屏一體機界面上偏偏還有配方號、批次號、工號、IP地址這些必須手動輸入的字段。讓客戶接USB鍵盤不現(xiàn)實很多產(chǎn)線工位根本沒地方放用系統(tǒng)自帶軟鍵盤界面風格和自家程序完全不搭中文輸入還要去戳屏幕體驗一言難盡。所以我花時間整理過一套LabVIEW中英文虛擬鍵盤源程序專門解決這類場景的輸入問題。這篇把方案選型、核心實現(xiàn)、實操步驟和踩坑記錄全部攤開講一遍做上位機、做HMI的朋友可以直接拿去改。1. 為什么LabVIEW項目里非要有這塊鍵盤不可1.1 觸摸屏工控現(xiàn)場的輸入難題寫辦公軟件的團隊可能很難理解產(chǎn)線工程師為什么會對屏幕上多一個鍵盤這種事較真。但真正到現(xiàn)場調(diào)試過就知道很多自動化設備合同里明確寫著人機界面采用觸摸屏默認就是不配實體鍵盤鼠標的。設備操作員每天站在屏前手上戴著手套環(huán)境里有粉塵、油污實體鍵盤既占空間又難清潔。可MES相關需求又把手動輸入的字段堆到了界面上操作員編號、產(chǎn)品型號、生產(chǎn)批號、當前工單、設備維護密碼……這些字段用下拉框很難覆蓋必須開放自由輸入。這種情況下放任不管操作員有幾個應對辦法。第一跟現(xiàn)場工程師抱怨然后被塞一個積灰的舊鍵盤用膠布貼在屏邊上第二靠系統(tǒng)自帶軟鍵盤湊合但自帶軟鍵盤按鈕很小戴手套戳不準在英文系統(tǒng)上還輸不了中文第三干脆把設備晾在那等IT來處理。不管哪一種本質上都是在消耗現(xiàn)場信任。虛擬鍵盤這個看似不起眼的小功能恰恰是讓上位機交付后能不能直接開機干活的關鍵一環(huán)。1.2 現(xiàn)成軟鍵盤方案的三個坑有的朋友會說Windows不是自帶屏幕鍵盤嗎直接調(diào)不就行了這個方案聽起來節(jié)省成本實際用起來有三個繞不開的坑。第一個是界面風格問題系統(tǒng)軟鍵盤的外殼、配色、字體跟LabVIEW做的界面完全是兩個世界的產(chǎn)物客戶看第一眼就會覺得這不是一套系統(tǒng)專業(yè)度大打折扣。第二個坑是可控性差。系統(tǒng)軟鍵盤的布局、按鍵大小、數(shù)字鍵盤是否常駐、中文輸入法如何切換通通不受程序控制。你真想限制操作員只能輸入數(shù)字或者強制使用特定數(shù)值范圍系統(tǒng)軟鍵盤完全配合不了。第三個坑更隱蔽——許多工廠的工控機是特定定制鏡像或精簡版Windows系統(tǒng)軟鍵盤可能被策略限制部署到現(xiàn)場才發(fā)現(xiàn)在別的機器上能彈出來的鍵盤這臺機器上怎么都打不開或者中文輸入法缺失求助IT又是一輪漫長的扯皮。與其賭現(xiàn)場環(huán)境不如把鍵盤邏輯完全放進LabVIEW程序里。1.3 一套自繪虛擬鍵盤源程序的價值點我自己最初決定寫這套中英文虛擬鍵盤源程序目標其實很樸素。第一在任何現(xiàn)場都能穩(wěn)定彈出來不受系統(tǒng)版本、精簡鏡像影響。第二界面風格跟主程序完全統(tǒng)一尺寸、配色、字體都能調(diào)。第三中英文輸入都能搞定中文不能只靠調(diào)用外部輸入法。第四能和主程序業(yè)務邏輯打通比如輸完數(shù)字按回車就觸發(fā)查詢這類事件在虛擬鍵盤內(nèi)部閉環(huán)處理掉。后來在實際項目里又驗證出兩個額外收益。一是復用性鍵盤做成一個獨立子VI后多個項目之間互相拷貝只改字典和布局就能用。二是可維護性很多需求方會在驗收前幾天突然提能不能加個中文輸入如果鍵盤邏輯分散在主程序各處這種改動會非常痛苦而集中在一個源程序模塊里修改路徑很短。這也是我堅持自繪而不是臨時拼湊的核心理由。2. 方案選型自繪虛擬鍵盤的開發(fā)路線拆解2.1 三條主流實現(xiàn)路線對比動手前我其實比較過三條路線這里直接列出對比結論。實現(xiàn)路線實現(xiàn)成本中英文支持定制化能力部署與兼容性維護成本調(diào)用系統(tǒng)屏幕鍵盤極低依賴系統(tǒng)輸入法幾乎不可定制精簡鏡像可能缺組件無源程序可控第三方ActiveX軟鍵盤控件中等視控件而定有限需要注冊組件升級易出問題依賴廠商維護純LabVIEW原生控件自繪較高完全自主實現(xiàn)完全可控打包簡單運行時隨程序下發(fā)源碼在手上隨時改表格里第三條路線前期投入最大但它換來的是整個鍵盤模塊完全透明。現(xiàn)場出任何問題打開LabVIEW就能改、能查、能重現(xiàn)而不是面對一個黑盒控件干瞪眼。工控項目里最怕的就是軟件在客戶那里出問題而你無法定位原生自繪恰恰把這種風險壓到最低。2.2 為什么原生控件自繪更符合工控場景工控上位機有一個區(qū)別于普通Windows應用的特點運行環(huán)境不可控程度高。同樣是Win10有的現(xiàn)場是普通辦公版有的是各類定制精簡鏡像第三方ActiveX控件在打包后往現(xiàn)場一裝經(jīng)常出現(xiàn)注冊表項缺失、運行庫沒裝、控件未授權等一串連鎖反應。系統(tǒng)軟鍵盤更不用說連在不在都取決于鏡像策略。原生控件則沒這個問題——它只是普通LabVIEW前面板控件隨VI一起打進安裝包不需要額外注冊任何組件。另外LabVIEW原生控件的風格可以和主程序用同一套主題色、字體大小和按鈕形狀。好的HMI界面之所以讓操作員覺得高級一個重要原因是視覺語言統(tǒng)一。界面上一堆混合風格的控件跟Word里混了三種字體一個道理。原生自繪能直接把這層統(tǒng)一感做出來。2.3 整體架構與數(shù)據(jù)流設計這套虛擬鍵盤源程序的架構我拆成三層。界面層是前面板上一堆布爾按鈕負責呈現(xiàn)和接收點擊這一層只管哪些鍵被按下映射層是按鍵識別與狀態(tài)管理邏輯負責把按鈕點擊翻譯成字符或者功能命令這一層是鍵盤的靈魂所在中英文切換、Shift狀態(tài)、拼音組合都在這里完成交互層負責把結果送到目標輸入控件并處理回車通知。數(shù)據(jù)流上一次完整的按鍵操作是這樣的操作員在觸摸屏按下字母鍵該按鈕的值變更事件觸發(fā)事件結構收到控件引用和當前值映射層根據(jù)標簽文本判斷按的是哪一個鍵結合當前處于英文、拼音還是數(shù)字模式得出本次要輸出的內(nèi)容如果內(nèi)容是需要上屏的字符就直接寫入當前目標輸入控件然后把焦點切回目標控件如果是回車、退格這類功能鍵則執(zhí)行相應的通知或刪除操作。整體數(shù)據(jù)流單向、清晰出問題時順著鏈路查就行不會出現(xiàn)這個字符到底是誰寫進去的這種懸案。3. 核心實現(xiàn)細節(jié)按鍵識別、中英文切換與焦點管理3.1 用控件標簽識別按鍵避免100個事件分支很多第一次寫虛擬鍵盤的朋友第一反應是在事件結構里給每一個按鈕單獨建一個分支100個按鍵就是100個分支。這種做法不是說不行但維護起來極其痛苦想改一個字的顯示標簽要動一堆地方。我的做法是只建三五個分支用控件標簽文本識別這一招把按鍵區(qū)分開。具體來說在前面板上每個按鍵控件的標簽直接設為它代表的字符比如字母A鍵標簽就叫AShift鍵標簽就叫Shift。在事件結構中把這100個按鍵的值變更事件全部綁定到同一個事件分支事件數(shù)據(jù)里的控件引用就是被點擊的那個鍵。通過一個屬性節(jié)點讀取這個引用的標簽文本再用條件結構Case根據(jù)標簽文本決定分支邏輯。這里把處理邏輯用文字概括一下事件分支(多個按鍵值變更): 控件引用 - 屬性節(jié)點讀出標簽文本 switch(標簽文本): case A..Z: 輸出字母 case 0..9: 輸出數(shù)字 case Shift: 切換Shift狀態(tài) case Backspace: 刪除最后一個字符 case Enter: 觸發(fā)完成通知 default: 其他字符鍵同樣輸出用這種結構新增一個字符鍵只需要在前面板放一個按鈕、把標簽改成對應字符程序框圖一行不用動擴展性比逐鍵建分支好太多。關鍵是LabVIEW的控件引用機制讓這件事變得非常簡單事件結構中拿到的不是字符串而是控件對象的引用讀寫它的標簽、值、焦點等屬性都暢通無阻。3.2 中文拼音輸入與候選字機制的實現(xiàn)這套源程序里中文輸入采用拼音加候選字方案不依賴操作系統(tǒng)任何輸入法程序?;舅悸肥钱旀I盤切換到中文模式后字母鍵不再直接上屏而是先進入一個拼音緩沖區(qū)緩沖區(qū)里拼出一個完整拼音后程序到內(nèi)置字典里檢索出對應的候選漢字顯示在候選字列表控件里操作員點擊候選字這個字才寫入目標輸入控件。實現(xiàn)上字典通常用一個二維字符串數(shù)組常量來表達第一列是拼音第二列是逗號分隔的漢字候選比如zhong,中,鐘,種,眾,重這樣的結構。檢索時把拼音緩沖區(qū)內(nèi)容和字典第一列做字符串匹配命中的一行就拆成候選列表顯示。這個字典可以按項目需要增補比如某工廠經(jīng)常要輸入產(chǎn)品批次用字、人員姓名的生僻字直接往數(shù)組里加行就行不用改任何程序結構。這里有個細節(jié)值得多說一句在設計拼音檢索邏輯時最好支持完整拼音匹配而不是前綴匹配否則操作員輸入帶聲調(diào)的數(shù)字或者拼音還沒輸完就急著看候選很容易造成誤判。我在實際項目里用的策略是完整拼音才匹配加候選列表動態(tài)刷新屏幕下方還有一個拼音緩沖區(qū)顯示框讓操作員隨時知道當前拼到了哪一步。中文輸入過程的體驗順不順很大程度上看這個反饋做得到不到位。3.3 焦點控制虛擬鍵盤不搶焦點的完整做法虛擬鍵盤最容易翻車的地方是真機一碰就暴露的焦點問題。觸摸屏操作沒有鼠標光標只有一個當前活動控件的概念。正常情況下操作員先點擊文本輸入框文本框獲得鍵盤焦點此時實體鍵盤或掃碼槍輸入的字符會落在文本框里。問題來了一旦操作員接著點擊屏幕上的虛擬鍵盤按鍵這個鍵盤按鈕本身變成了活動控件鍵盤焦點從文本框跑到了虛擬鍵盤按鈕上之后再點其他虛擬鍵輸出的字符就不知道跑哪去了。解決辦法的核心是焦點強制回收。虛擬鍵盤每次處理完一個按鍵都要立刻把鍵盤焦點寫回當前目標輸入控件。在程序框圖上就是保存一份目標控件的引用處理完字符后通過屬性節(jié)點把該控件的Key Focus有的版本里叫鍵盤焦點設為True。這一步必須放在虛擬鍵盤按鈕事件分支的同一次執(zhí)行中完成不能留著下個循環(huán)再做否則操作員會肉眼可見地看到焦點閃了一下又跳走。另外還有一個經(jīng)驗鍵盤子VI最好作為普通子VI嵌入到主程序前面板中不要讓鍵盤彈成獨立頂層窗口。原因很簡單跨VI操作別的程序前面板控件的焦點在LabVIEW里有時會受到限制或需要額外引用處理而嵌入到同一前面板后所有控件引用都是同一VI下的正常關系焦點回收邏輯最穩(wěn)。3.4 回車觸發(fā)業(yè)務邏輯的實現(xiàn)方式工控界面上的輸入框經(jīng)常講究輸完按回車立即執(zhí)行下一步。比如掃碼槍掃完條碼自動回車程序馬上查詢數(shù)據(jù)庫操作員在鍵盤上輸完工單號按回車界面直接跳轉。很多人直接掛目標控件的值變更事件結果發(fā)現(xiàn)每敲一個字符界面就反應一次輸入還沒結束邏輯已經(jīng)跑了好幾遍操作體驗一塌糊涂。正確做法是這樣目標輸入控件在生產(chǎn)運行期間只做純文本接收不觸發(fā)業(yè)務邏輯虛擬鍵盤上的回車鍵被按下時不是簡單把回車字符追加進文本框而是通過用戶事件或者消息隊列向主程序發(fā)送輸入完成信號主程序收到信號后才從目標控件讀取當前值執(zhí)行查詢、校驗或跳轉。這樣設計還有一個額外好處虛擬鍵盤、實體鍵盤、掃碼槍三種輸入路徑可用同一把回車邏輯。掃碼槍以USB鍵盤模式輸出時掃完碼自動補一個回車這個回車天然觸發(fā)輸入完成信號數(shù)據(jù)和鍵盤輸入統(tǒng)一走同一條處理鏈。這套一致性在MES掃碼綁定場景下特別值錢鍵盤和掃碼槍兩條輸入鏈路不用寫兩套業(yè)務代碼。4. 實操過程完整搭出一套中英文虛擬鍵盤4.1 前面板布局與按鈕機械動作選擇動手搭之前先規(guī)劃好按鍵布局。標準QWERTY三行字母區(qū)、一個數(shù)字符號區(qū)、一排功能鍵區(qū)這是大多數(shù)操作員最熟悉的排布不要為了省空間搞另類排列。觸摸屏對按鍵尺寸有硬性要求我習慣把字母鍵做成40像素以上對應約10到12毫米物理尺寸間距至少2像素戴手套操作也不容易誤觸功能鍵可以用稍小尺寸但至少也要35像素。整體放在屏幕底部三分之一的區(qū)間避免遮擋主界面的數(shù)據(jù)展示區(qū)。每個按鍵控件的機械動作建議統(tǒng)一設為Latch類型按下觸發(fā)、讀取后自動復位。這類鎖定式機械動作的程序邏輯很簡單每次按下產(chǎn)生一次True事件結構讀取并處理完后按鈕自動復位天然避免了長按重復觸發(fā)。如果用瞬時動作操作員手指一直按著屏幕值會持續(xù)保持True不小心就觸發(fā)N次邏輯調(diào)起來很惱火。視覺上功能鍵用不同底色區(qū)分會有幫助目前我的習慣是Shift用深灰、Backspace用紅、Enter用綠、中英文切換用藍其余字母數(shù)字鍵用淺灰布局邏輯一眼掃過去就很清楚。4.2 程序框圖的關鍵邏輯與狀態(tài)管理程序框圖主體是一個While循環(huán)包著事件結構事件結構里維護幾個核心狀態(tài)當前模式英文、拼音、數(shù)字、Shift狀態(tài)、Caps狀態(tài)、拼音緩沖區(qū)字符串。這些狀態(tài)用移位寄存器保存每處理一次按鍵后更新狀態(tài)再傳給下一輪事件。字符鍵的處理邏輯分四種情況。模式是英文時把標簽文本按Shift和Caps狀態(tài)做大小寫轉換后寫入目標控件模式是數(shù)字時只允許數(shù)字鍵輸出模式是拼音時字符進入拼音緩沖區(qū)并刷新候選字列表不直接上屏拼音候選字被選定時把選中的漢字拼接進目標文本框同時清空拼音緩沖區(qū)。功能鍵處理相對獨立Backspace從目標控件文本末尾刪一個字符Enter發(fā)送用戶事件觸發(fā)輸入完成Shift和Caps只改狀態(tài)不產(chǎn)生字符輸出。這里提醒一個新手容易漏的點事件結構里的多個按鍵共享一個分支時注意事件數(shù)據(jù)里還要判斷觸發(fā)事件的是哪一個引用。尤其是在綁定動態(tài)事件時如果不加區(qū)分就拿引用去讀標簽文本后面Case結構會亂。建議在事件分支開始處就讀取引用并轉成局部變量后面各處統(tǒng)一使用同一個引用保證一致性。4.3 子VI封裝、數(shù)據(jù)交互與主程序對接鍵盤做完后以子VI形式供主程序調(diào)用。子VI對外暴露的接口我固定為三組目標控件引用輸入、當前模式輸入輸出、用戶事件輸出輸出。主程序里每個需要輸入的可編輯控件都綁定一個鼠標按下或者鍵盤焦點事件在事件處理里把該控件的引用傳給鍵盤子VI的輸入引腳。這樣操作員點哪個輸入框虛擬鍵盤就自動知道往哪個框里送字符不需要額外做選中目標的操作。數(shù)據(jù)交互方式我推薦用戶事件加隊列的組合。用戶事件用來通知輸入完成這類異步業(yè)務信號隊列用來傳遞字符串消息主程序在其他循環(huán)里消費。如果項目規(guī)模不大也可以簡化成鍵盤子VI輸出一個字符串控件主程序輪詢字符串控件取值后清空。不過輪詢方案多多少少有點浪費CPU而且處理不及時我建議能上事件就上事件。如果你用的是JKI狀態(tài)機之類的框架虛擬鍵盤的輸出消息還可以直接轉成消息幀塞進狀態(tài)機隊列里實現(xiàn)主界面邏輯和鍵盤輸入模塊的徹底解耦。我有一個項目就是這么干的鍵盤子VI完全不知道主程序在做什么它只負責把人按的鍵翻譯成消息主狀態(tài)機收到消息后再決定跳轉、校驗還是落庫維護起來非常清爽。4.4 與掃碼槍等外部鍵盤輸入的統(tǒng)一處理前面提到過很多掃碼槍工作在USB鍵盤模式相當于一個只會敲字符串的實體鍵盤插入電腦后不需要裝驅動焦點在哪個文本框條碼就進哪個框。這種設計恰恰給了我們一個啟發(fā)虛擬鍵盤本質上也是輸入設備它的輸出路徑跟掃碼槍沒有本質區(qū)別都是往當前焦點控件里塞字符。所以我在主程序中并不區(qū)分字符是從虛擬鍵盤來的還是掃碼槍來的統(tǒng)一目標控件值變更、統(tǒng)一回車觸發(fā)邏輯數(shù)據(jù)源無關性讓業(yè)務層不用寫一堆條件判斷。唯一需要留意的是掃碼槍的字符輸入速度很快一整個條碼在幾十毫秒內(nèi)全部灌進文本框如果目標控件的事件處理里做了重量級操作比如查數(shù)據(jù)庫就會把輸入卡在半路。做法是把數(shù)據(jù)接收和業(yè)務處理放在不同循環(huán)里接收循環(huán)只管把值收進來放進隊列處理循環(huán)再慢慢消費兩者速率天然解耦。虛擬鍵盤手動輸入雖然慢但在同一套架構下也享受到了這個好處。5. 常見問題與排查技巧實錄5.1 點擊按鍵后目標框的焦點被搶走這是虛擬鍵盤項目里出現(xiàn)頻率最高的問題現(xiàn)象是操作員點一下虛擬鍵盤按鈕輸入框的光標就不見了后面的字符要么沒反應要么跑進奇怪的地方。排查要點是把導致焦點變化的每一個事件都過一遍。首先確認點擊虛擬鍵后目標輸入控件是否被重新設置了焦點其次檢查目標控件的屬性里有沒有禁用或者只讀開關誤開導致它根本拿不到焦點最后檢查鍵盤按鈕的機械動作會不會造成值在多個循環(huán)間閃爍因為焦點切換跟控件狀態(tài)變化有關。如果焦點設置了但焦點還是丟多半是鍵盤子VI被當成獨立頂層窗口彈出跨VI焦點控制受限。把鍵盤改成嵌入主程序前面板后這個問題基本能解決。5.2 中文輸出亂碼與字體顯示異常中文亂碼分兩種情況處理。第一種是真正的編碼錯亂出現(xiàn)原因是LabVIEW字符串在不同機器上的本地代碼頁不一致比如程序在中文系統(tǒng)開發(fā)部署到英文系統(tǒng)后中文字符串變成問號。解決思路是在涉及文件的場景把字符串統(tǒng)一轉成UTF-8字節(jié)寫入讀取時反向轉換不要直接拿中文字符串當落庫值在純界面顯示場景則要保證目標文本框控件使用的字體支持中文常見做法是把字體設置為宋體或微軟雅黑。第二種是顯示問題字符沒亂但顯示成方框。這種不是編碼問題是字體不支持。設備部署機上如果沒有安裝對應字體界面上的中文字符就會被替代字符占位。打包時把字體一并帶上或者干脆在設計時就指定系統(tǒng)自帶且支持中文的字體能省去不少現(xiàn)場救火的時間。5.3 觸摸屏上按鍵手感差、誤觸多觸摸屏操作和鼠標點擊不一樣沒有懸停狀態(tài)也沒有精確的光標。操作員如果戴手套手指接觸面積大40像素以下的按鍵非常容易誤觸相鄰鍵。經(jīng)驗值是鍵間距至少2到4像素整鍵尺寸至少40像素如果屏是10.1寸以下的小屏寧可壓縮布局行數(shù)也不能無限縮小按鍵。另外我遇到過一種典型的誤觸按鍵值在觸摸屏的電容感應上產(chǎn)生抖動一次點擊被事件結構抓到兩次True導致一個字符輸出兩遍。排查時在事件分支的True處理里加一個簡單的時間過濾比如連續(xù)兩次按鍵間隔小于100毫秒則忽略基本能壓掉這類問題。要記得這個過濾只防抖不要擋住操作員故意快速連輸?shù)那闆r所以閾值不要設得太大。5.4 打包部署后鍵盤顯示異常開發(fā)環(huán)境里一切正常打包安裝到現(xiàn)場機器后鍵盤錯位、字體變化、界面縮放異常這類問題多半和高DPI、字體缺失有關。工控現(xiàn)場常見的觸摸屏一體機分辨率不低但縮放設置五花八門LabVIEW前面板如果沒做DPI感知設置高分屏下會模糊一片或者控件錯位。打包前建議在項目屬性里確認前面板縮放模式在目標機器上實測不同分辨率下的顯示效果優(yōu)先保證最常使用的那個分辨率表現(xiàn)良好。還有一個容易踩的坑有些工控機安裝的是LabVIEW運行引擎而不是完整開發(fā)環(huán)境如果鍵盤VI用到了某個只在開發(fā)環(huán)境默認路徑下的字體或資源打包時沒設置好運行環(huán)境里就會找不到。打包前用安裝程序向導把運行引擎一并帶上再把項目用到的字體手動添加進來能避免大部分這類問題。5.5 幾個項目用過之后的整體體會這套虛擬鍵盤源程序我在實際交付里反復用了幾輪最大的體會是虛擬鍵盤不是一個錦上添花的玩具功能而是直接影響設備能否通過驗收的基礎設施。客戶不會因為它多加分但一旦中文輸入法調(diào)不出來、焦點亂跳、回車不觸發(fā)減分是實打實的。所以建議大家在項目計劃里就把鍵盤模塊當成一等公民排期而不是最后一天臨時塞進去的東西。我還總結出一個實用習慣鍵盤子VI做成通用模板后每個新項目先復制一份再按項目需求改三樣東西——拼音字典加項目專用詞匯、功能鍵布局、配色主題。主界面業(yè)務邏輯完全不需要動。這樣一套框架沉淀下來后面再遇到客戶臨時要加中文輸入這類需求改動時間基本能控制在半天以內(nèi)現(xiàn)場應對起來會從容很多。最后再提一個細節(jié)記得在鍵盤上給輸入完成留一個顯眼的確認鍵并且讓這個鍵在觸摸屏上足夠大很多操作員輸完數(shù)據(jù)后習慣性地找綠色確認按鈕這個位置做不好前面所有輸入體驗都白搭。