(中行雷威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給我(羣主)留言。資料簡介:
1.1 掃碼二維碼
UniGUI目前(截至1525版本)還沒有自己的掃碼控件,但是它最大的特點就是打通了對JavaScript的調用,可以調用第三方的js實現掃碼,本例將調用ZXing掃碼的js代碼實現移動設備掃碼,它既是一個掃碼案例,又是一個詳細闡釋uniGUI如何調用JavaScript和回調的案例。
- 佈局
新建一個項目,配置好並保存項目,然後編譯運行項目,生成輸出目錄結構,然後將本節配套代碼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] |
- 功能
系統啓動後直接調用主窗口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>
- UniServerModule的CustomFiles屬性代碼
files/zxing.min.js
3)UnimMain.cpp核心代碼
void __fastcall TMainmForm::UnimFormReady(TObject *Sender)
{
//初始化攝像頭
String tmpStr;
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);
}
void __fastcall TMainmForm::btnStartClick(TObject *Sender)
{//啓動掃碼
btnStart->JSInterface->JSCall("element.dom.click","[]");
}
//---------------------------------------------------------------------------
void __fastcall TMainmForm::btnResetClick(TObject *Sender)
{//停止掃碼
btnReset->JSInterface->JSCall("element.dom.click", "[]");
}
//---------------------------------------------------------------------------
void __fastcall TMainmForm::UnimHTMLFrame1AjaxEvent(TComponent *Sender, UnicodeString EventName,
TUniStrings *Params)
{//Ajax回調獲取掃碼結果
if (EventName == "getResult" )
{
mResult->Lines->Add(Now());
mResult->Lines->Add("【"+Params->Values["result"]+"】");//顯示掃碼結果
UnimHTMLFrame1->JSInterface->JSCall("_ael.play", "[]");//滴滴一聲
}
}
4、效果
設置手機,讓谷歌瀏覽器擁有攝像頭和聲音權限,打開手機的谷歌瀏覽器,輸入https://服務地址:8077,操作體驗一下吧(本案例在華爲和小米手機均調試通過,在PC版谷歌瀏覽器上測試時偶爾會出現攝像頭快速閃斷現象)。