(中行雷威2020.05.21)
(同一個世界,同一個夢想,交流學習C++Builder and Delphi XE10,傳承c++builder and Delphi的魅力!歡迎各地朋友加入我的QQ羣484979943,進羣密碼“BCB”,同時也請將該羣號廣爲宣傳,希望能夠廣集各方高手,共同進步。如需下載開發工具及源代碼請加入我的QQ羣。)
【閱讀倡議】
1、有問題請留言;
2、沒問題請點贊;
3、看連載請加羣;
4、下源碼請加羣;
【開發工具】
1、C++Builder and Delphi 10.3.3
2、FMSoft_uniGUI_Complete_Professional_1.70.0.1531(正版)
本人主筆的國內第一本uniGUI教學案例代碼已誕生,分爲cbuilder和delphi兩個版本,買代碼送教程,需要的朋友可以加入我的QQ技術交流羣484979943給我(羣主)留言。資料簡介:
https://www.meipian.cn/20b86ayo?share_from=others&user_id=64168117&uuid=a8a75af8c0cc31e6a21b8a79a2b07398&share_depth=1&first_share_uid=64168117&utm_medium=meipian_android&share_user_mpuuid=94b70e99e8b6986c71b270a9883befb2
1.1手機掃描二維碼
UniGUI目前(截至1525版本)還沒有自己的掃碼控件,但是它最大的特點就是打通了對JavaScript的調用,可以調用第三方的js實現掃碼,本例將調用ZXing掃碼的js代碼實現移動設備掃碼,它既是一個掃碼案例,又是一個詳細闡釋uniGUI如何調用JavaScript和回調的案例。
1、佈局
新建一個項目,配置好並保存項目,然後編譯運行項目,生成輸出目錄結構,然後將本節配套代碼files目錄下的beep-digital.mp3(掃碼聲音文件)和zxing.min.js(ZXing的JavaScript文件)複製到Win32\Debug\files目錄下;因爲ZXing掃碼使用了https加密連接,需要SSL證書和SSL庫文件,將tools目錄下的cert.pem、key.pem、root.pem(SSL證書文件)、libeay32.dll、ssleay32.dll(SSL驅動文件)複製到Win32\Debug目錄下(證書文件的生成及https連接的使用方法詳見我的《UniGUI入門到精通》教程的“加密連接”章節)。
在MainmForm上添加一個UnimHTMLFrame、兩個UnimButton和一個UnimMemo。UnimHTMLFrame1用來關聯ZXing的js腳本實現攝像頭選擇和攝像頭掃碼;UnimButton一個用來啓動掃碼,命名爲btnStart,一個用來停止掃碼,命名爲btnStop;UnimMemo1用來記錄掃碼結果,命名爲mResult。
控件名稱 |
屬性 |
取值 |
說明 |
UnimHTMLFrame1 |
Align |
alTop |
|
|
AlignWithMargins |
TRUE |
保留控件四周邊界 |
btnStart(UnimButton1) |
Align |
alTop |
|
|
AlignWithMargins |
TRUE |
保留控件四周邊界 |
btnReset(UnimButton2) |
Align |
alTop |
|
|
AlignWithMargins |
TRUE |
保留控件四周邊界 |
mResult(UnimMemo1) |
Align |
alTop |
|
|
AlignWithMargins |
TRUE |
保留控件四周邊界 |
UniServerModule |
CustomFiles |
files/zxing.min.js |
調用Zxing JS代碼 |
|
FilesFolder |
files\ |
默認文件目錄 |
|
SSL->Enabled |
TRUE |
啓動SSL |
|
SSL->Password |
8077 |
HTTPS端口 |
|
SSL->CertFile |
cert.pem |
證書文件及配置 |
|
SSL->KeyFile |
key.pem |
|
|
SSL->Method |
sslvTLSv1_1 |
|
|
SSL->Mode |
sslmUnassigned |
|
|
SSL->RootCertFile |
root.pem |
|
|
SSL->Versions |
[sslvTLSv1_1] |
2、功能
系統啓動後直接調用主窗口MainmForm的OnReady事件初始化硬件設備,搜索設備共有幾個攝像頭,然後列舉出來,選擇一個後置攝像頭,點擊btnStart按鈕開始掃碼,對準條形碼或二維碼,滴的一聲將在下方的UnimMemo裏出現掃碼結果;點擊btnReset按鈕將停止掃描,可以重新選擇新的攝像頭,屏幕中如果同時出現一個條形碼和一個二維碼,將優先掃描二維碼。
3、代碼
1)UnimHTMLFrame1的HTML屬性代碼
<audio id="player" height="0px" src="files/beep-digital.mp3" style="display:none"></audio>
<div>
<video id="video" width="100%" height="100%" style="border: 1px solid gray"></video>
</div>
<div id="sourceSelectPanel" style="display:none">
<label for="sourceSelect">Change video source:</label>
<select id="sourceSelect" style="max-width:400px">
</select>
</div>
2)UniServerModule的CustomFiles屬性代碼
files/zxing.min.js
3)UnimMain.pas核心代碼
…
procedure btnInitClick(Sender: TObject);//定義攝像頭初始化函數
procedure btnStartClick(Sender: TObject);//開始掃碼事件
procedure btnResetClick(Sender: TObject);//停止掃碼事件
…
//初始化攝像頭清單, 讓MainmForm的OnReady事件直接調用btnInitClick函數
procedure TMainmForm.btnInitClick(Sender: TObject);
var
tmpStr:String;
begin
tmpStr:=UnimHTMLFrame1.JSName +'._ael=document.getElementById("player");'+ UnimHTMLFrame1.JSName +'._ael.load();'+
UnimHTMLFrame1.JSName + '.oldResultText="";'+
'let selectedDeviceId;'+
' const codeReader = new ZXing.BrowserMultiFormatReader();'+
' codeReader.getVideoInputDevices()'+
' .then((videoInputDevices) => {'+
' const sourceSelect = document.getElementById("sourceSelect");'+
' selectedDeviceId = videoInputDevices[0].deviceId;'+
' if (videoInputDevices.length >= 1) {'+
' videoInputDevices.forEach((element) => {'+
' const sourceOption = document.createElement("option");'+
' sourceOption.text = element.label;'+
' sourceOption.value = element.deviceId;'+
' sourceSelect.appendChild(sourceOption);'+
' });'+
' sourceSelect.onchange = () => {'+
' selectedDeviceId = sourceSelect.value;'+
' };'+
' const sourceSelectPanel = document.getElementById("sourceSelectPanel");'+
' sourceSelectPanel.style.display = "block";'+
' }'+
' document.getElementById("'+ btnStart.JSId +'").addEventListener("click", () => {'+
' codeReader.decodeFromVideoDevice(selectedDeviceId, "video", (result, err) => {'+
' if (result&&result.text!='+UnimHTMLFrame1.JSName+'.oldResultText) {'+
' window.ajaxRequest('+ UnimHTMLFrame1.JSName +', "getResult", ["result="+result.text]);'+
UnimHTMLFrame1.JSName + '.oldResultText=result.text;'+
' }'+
' if (err && !(err instanceof ZXing.NotFoundException)) {'+
' }'+
' });'+
' });'+
' document.getElementById("'+ btnReset.JSId +'").addEventListener("click", () => {'+
' codeReader.reset();'+
' ajaxRequest('+ UnimHTMLFrame1.JSName +', "getResult", ["result="+""]);'+
' })'+
' })'+
' .catch((err) => {'+
' alert(err)'+
' })';
UniSession.AddJS(tmpStr);
end;
//停止掃碼
procedure TMainmForm.btnResetClick(Sender: TObject);
begin
(Sender as TUnimButton).JSInterface.JSCall('element.dom.click', []);
end;
//開始掃碼
procedure TMainmForm.btnStartClick(Sender: TObject);
begin
(Sender as TUnimButton).JSInterface.JSCall('element.dom.click', []);
end;
//UnimHTMLFrame的OnAjaxEvent事件實現Ajax回調傳回掃碼結果
procedure TMainmForm.UnimHTMLFrame1AjaxEvent(Sender: TComponent;
EventName: string; Params: TUniStrings);
begin
if (EventName = 'getResult') and (Params.Values['result']<>Trim(mResult.Text)) then
begin
mResult.Lines.Add(FormatDateTime('yyyyMMdd hh:nn:ss',Now()));
mResult.Lines.Add('【'+Params.Values['result']+'】');
UnimHTMLFrame1.JSInterface.JSCall('_ael.play', []);
end;
end;
initialization
RegisterAppFormClass(TMainmForm);
end.
4、效果
設置手機,讓谷歌瀏覽器擁有攝像頭和聲音權限,打開手機的谷歌瀏覽器,輸入https://服務地址:8077,操作體驗一下吧(本案例在華爲和小米手機均調試通過,在PC版谷歌瀏覽器上測試時偶爾會出現攝像頭快速閃斷現象)。