- A+
所属分类:.NET技术
项目背景:
项目技术方案定的是前后端分离,采用framework4.0+vue+elementUI 客户端需要加壳(使用CEF+ChromiumWebBrowser),避免客户端多样,导致环境不支持;
并且客户端需要调用微软硬件(键盘、语音)接口进行业务操作;
所遇到的场景:
- 语音
客户端(前端)需要触发调用;操作系统语音外设播报语音;
- 键盘
客户端(前端)需要监听键盘输入按键,并在回车的时候,回调前端js并将键盘输入的字符传给前端方法执行vue实例下指定方法;
代码实现
- 语音实现
后台代码:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Configuration; 5 using System.Data; 6 using System.Drawing; 7 using System.Linq; 8 using System.Net; 9 using System.Text; 10 using System.Threading.Tasks; 11 using System.Windows.Forms; 12 using CardReader; 13 using CefSharp; 14 using CefSharp.WinForms; 15 using FormDLL; 16 using Newtonsoft.Json; 17 using RestSharp; 18 namespace CefSharpOfQueue { 19 public partial class FormMain: Form { 20 public ChromiumWebBrowser chromeBrowser; 21 private Type voiceType; 22 private CardReader.CardReader cardReader; 23 private dynamic spVoice; 24 private string token; 25 public Control activeUserControl; 26 private Panel panelContent; 27 public FormMain() { 28 //初始化语音设备 29 this.voiceType = Type.GetTypeFromProgID("SAPI.SpVoice"); 30 this.spVoice = Activator.CreateInstance(this.voiceType); 31 //初始化winform控件 32 InitializeComponent(); 33 this.FormBorderStyle = FormBorderStyle.None; 34 //winform全屏 35 this.WindowState = FormWindowState.Maximized; 36 //初始化chromium 37 InitializeChromium(); 38 // 注册一个formMainProcess;用于前端调用后台 39 chromeBrowser.RegisterJsObject("formMainProcess", new FormMainProcess(chromeBrowser, this)); 40 } 41 //放在初始化winform控件InitializeComponent 方法中 42 private void FormMain_Load(object sender, EventArgs e) { 43 //this.activeUserControl = this.AddControl(new ScanCard(this)); 44 this.cardReader = new CardReader.CardReader(2); 45 this.cardReader.CardRead += delegate(string cardCode) { 46 if(!string.IsNullOrWhiteSpace(cardCode)) { 47 //将获取到的cardCode回传给前端全局变量 48 try { 49 chromeBrowser.GetBrowser().MainFrame.ExecuteJavaScriptAsync("Vue.prototype.$store.state.isShow=true;Vue.prototype.$store.state.queryCode='" + cardCode + "'"); 50 } catch { 51 //或者写日志 52 throw new Exception("error"); 53 } 54 } 55 }; 56 } 57 public void SpeakTxt(string msg) { 58 this.spVoice.speak(msg, 1); 59 } 60 public void InitializeChromium() { 61 // 获取配置文件里的前端服务地址 62 string url = ConfigurationManager.AppSettings["ServiceAddress"]; 63 //创建chrome对象 64 chromeBrowser = new ChromiumWebBrowser(url); 65 // 将chrome对象添加进winform控制器 66 this.Controls.Add(chromeBrowser); 67 chromeBrowser.Dock = DockStyle.Fill; 68 // Allow the use of local resources in the browser 69 BrowserSettings browserSettings = new BrowserSettings(); 70 browserSettings.FileAccessFromFileUrls = CefState.Enabled; 71 browserSettings.UniversalAccessFromFileUrls = CefState.Enabled; 72 browserSettings.WebSecurity = CefState.Enabled; 73 // browserSettings.LegacyJavascriptBindingEnabled = true; 74 chromeBrowser.BrowserSettings = browserSettings; 75 // 网页开始加载时的处理 76 chromeBrowser.FrameLoadStart += (sender, e) => { 77 string script = @"const loading = this.$loading({ 78 lock: true, 79 text: 'Loading', 80 spinner: 'el-icon-loading', 81 background: 'rgba(0, 0, 0, 0.7)' 82 }); 83 setTimeout(() => { 84 loading.close(); 85 }, 2000); 86 "; 87 e.Frame.ExecuteJavaScriptAsync(script); 88 }; 89 // 网页加载完毕时的处理 90 chromeBrowser.FrameLoadEnd += (sender, e) => { 91 string script = "alert('加载完毕!');"; 92 e.Frame.ExecuteJavaScriptAsync(script); 93 }; 94 } 95 } 96 internal class FormMainProcess { 97 private FormMain _instanceMainForm = null; 98 private ChromiumWebBrowser _instanceBrowser = null; 99 public FormMainProcess(ChromiumWebBrowser originalBrowser, FormMain mainForm) { 100 _instanceBrowser = originalBrowser; 101 _instanceMainForm = mainForm; 102 } 103 /// <summary> 104 /// 播放语音 105 /// </summary> 106 /// <param name="message"></param> 107 public void speakMsg(string message) { 108 this._instanceMainForm.Invoke(new Action(delegate { 109 this._instanceMainForm.SpeakTxt(message); 110 })); 111 } 112 } 113 }
前端代码:可在vue界面中script中任意一个方法中 使用后端注册了的formMainProcess 对象,调用对应方法。如下:
1 <template> 2 ... 3 </template> 4 <script> 5 ... 6 methods: { 7 testf(){ 8 //呼叫,播报信息 9 formMainProcess.speakMsg( 10 '测试语音ABCD' 11 ); 12 } 13 } 14 </script>