天天看点

(39)uniGUI for Delphi 扫描二维码

(同一个世界,同一个梦想,交流学习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给我(群主)留言。资料简介:

(39)uniGUI for Delphi 扫描二维码

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。

(39)uniGUI for Delphi 扫描二维码
控件名称 属性 取值 说明
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版谷歌浏览器上测试时偶尔会出现摄像头快速闪断现象)。

(39)uniGUI for Delphi 扫描二维码
(39)uniGUI for Delphi 扫描二维码
(39)uniGUI for Delphi 扫描二维码