Cnoos

记录一些学习、工作、生活的内容或想法

记录一下 Foxtable WebView2 双向消息通信的阶段性改进

笔记 约 5 分钟 阅读 8

前言

之前为 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 的现代化业务界面桥接层。