记录一下 Foxtable WebView2 双向消息通信的阶段性改进
前言
之前为 Foxtable 接入 WebView2 ( 记录一下为 Foxtable 接入 WebView2:把传统 ERP 客户端扩展成现代 Web 工作台 ),主要解决的是一个问题:让 Foxtable 可以加载本地 HTML 页面,把一些复杂的 ERP 管理界面交给 HTML/CSS/JavaScript 来展示。
当时的通信方式更偏单向:
Foxtable -> ExecuteScript -> HTML
Foxtable 可以把订单、客户、费用、汇总等数据推送给 HTML 页面,HTML 负责渲染界面。但 HTML 页面里的用户操作,如何稳定回传给 Foxtable,还没有完全定型。
DLL 接入了 WebView2 原生消息通道
今天主要推进的就是这一部分:让 WebView2 从“Foxtable 控制 HTML”进一步变成“Foxtable 与 HTML 双向通信”,以实现html操作与Foxtable窗口的状态交互、数据交换等。
在 DLL 中接入了 WebView2 原生消息通道:
CoreWebView2.WebMessageReceived
这样 HTML 里执行:
window.chrome.webview.postMessage(message)
DLL 就可以收到消息。
为了避免消息丢失,也在 DLL 内部增加了一个消息队列。HTML 发来的消息会先进入队列,Foxtable 端再通过暴露出来的方法读取。
目前主要增加了几个方法:
GetWebMessageCount()
PopWebMessage()
PeekWebMessage()
ClearWebMessages()
其中最关键的是:
PopWebMessage()
它可以从队列里取出一条消息,并且移除这条消息。
这样整体流程就变成了:
HTML postMessage
↓
DLL 接收消息
↓
放入消息队列
↓
Foxtable VB 主动读取
HTML 侧的 fox-bridge.js 也做了兼容处理。新的 DLL 可以走 window.chrome.webview.postMessage(),同时仍然保留:
window._foxMessage = message
这样旧方式也还能用于兼容和调试。
目前 HTML 发送给 Foxtable 的消息格式统一为:
{
"action": "hello",
"data": {},
"timestamp": "...",
"page": "..."
}
Foxtable 侧只需要解析 action,再按不同动作处理即可。
当前先支持几个基础动作:
hello
select-customer
select-order
轮询消息
没有使用 Timer 去轮询消息。
虽然有了 PopWebMessage() 之后,可以用 Timer 定时读取,但对账页面不是实时系统,没有必要一直空跑。高频 Timer 反而可能带来 UI 卡顿、重复触发或假死问题。
所以现在采用的是更低频的方式:
用户点击 Foxtable 窗口时读取消息
每次读取时,会把队列里的消息弹出,只保留最后一条有效消息。旧消息、无效 action、重复消息都忽略。
这个方式更适合当前对账页面的场景。
因为用户连续点击客户或订单时,Foxtable 通常只需要知道最后一次选择,不一定要处理前面每一次点击。
这次更新之后,整体通信模型从原来的:
Foxtable -> ExecuteScript -> HTML
变成了:
Foxtable -> ExecuteScript -> HTML
HTML -> postMessage -> DLL 消息队列 -> Foxtable VB
也就是说,WebView2 控件现在真正具备了双向桥接能力。
总结
Foxtable 里的 HTML 页面就不只是展示层了,也可以作为用户交互层。Foxtable 继续负责数据查询、业务处理和本地 ERP 能力,HTML 负责界面展示和操作入口,DLL 负责两边的通信。
后续这套方式可以继续用于对账页面,也可以扩展到订单复核、客户结余、付款审核、发票预览、库存分析等页面中。
整体来看,这次更新不是界面上的变化,而是通信机制上的补齐。WebView2 从一个“嵌入式 HTML 容器”,进一步变成了 Foxtable 的现代化业务界面桥接层。