(中行雷威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属性代码
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版谷歌浏览器上测试时偶尔会出现摄像头快速闪断现象)。