01 网易 Duilib 框架概述
Duilib 是 Windows 系统下的开源的 DirectUI 界面库(遵循 BSD 协议),完全免费,可用于商业软件开发。
Duilib 可以简单方便地实现大多数界面需求,包括换肤、换色、透明等功能,支持多种图片格式,使用 XML 可以方便地定制窗口,能较好地做到 UI 和逻辑相分离,尽量减少在代码里创建 UI 控件。目前,Duilib 已经在国内有较为广泛的使用。
网易在研发网易易信 PC 版时引入 Duilib,经过多年开发和改进,由网易云信在2019年4月开源。(github 地址:https://github.com/netease-im...)
网易 Duilib 使用 C++11 重写,在其原有基础上做了较大重构,搭配谷歌的基础组件 Base 库、基于 Chromium 的 WebView 框架 CEF 以及常用的 UI 组件,形成了一套功能强大、简单易用的完整桌面 UI 开发框架。
02 网易 Duilib 整体框架
2.1 整体组件架构
组件架构图
框架中提供了多线程模型、高精度定时器、基本的 xml 解析、zip 解压等功能;封装了一层渲染接口和全局样式资源的统一管理;并且对 DPI 适配、多语言、虚拟键盘、手写板等功能增加了支持;在上层提供了丰富的控件。
2.2 线程模型和消息队列
开发框架中集成了 Chromium 中 base 库的线程模型和消息队列,base 中包含了多种消息循环、异步操作接口。
base 线程消息循环
网易 Duilib 框架中的 UI 消息循环、工作线程都完全依托 base 的线程模型。使用 base 的异步通信能力,我们可以将耗时的工作(如资源解析)放到辅助线程来减轻 UI 线程的压力。
base异步通信
同时,网易 Duilib 中的各种基础组件,都已经继承了 base 中的生命周期检测能力,每个任务在执行时都会先检查与之绑定的对象是否存活,确保多线程操作不会因野指针而导致崩溃。实际项目开发中,使用base的线程模型,我们可以非常简单做到 UI 线程、数据库线程、网络线程、其他工作线程之间的通信与交互,有效提升开发速度。
03 网易 Duilib 的功能特点
3.1 更加丰富的功能
网易 Duilib 框架提供了更加完整和丰富的功能,以满足不同真实业务场景的需求:
- 丰富的控件、简易的布局
- 灵活的控件组合、事件处理方式
- 模块化支持
- 优化渲染效率
- 异形窗体支持
- DPI 适配支持
- 多国语言支持
- 通用样式支持
- 虚表控件支持
- 虚拟键盘支持
- 实用的多线程支持
- CEF webview 支持
- 控件动画、GIF 动画支持
- 触控设备支持(Surface、Wacom)
- 抽象渲染接口(为其他渲染引擎提供支持)
3.2 灵活的布局与组合
网易 Duilib 中,增加了控件与容器的尺寸自适应功能,免去繁琐的手写尺寸。同时增强了布局能力,搭配控件的一些定位属性,可以使用少量 xml 代码来完成更加强大的布局效果。
新增的绝对布局
现在的 UI 库中,把布局、容器、控件等逻辑组件拆分开,让不同的布局可以与任意容器进行灵活的组件。并且弱化了容器与控件的区别,基础控件使用模版来编写,上层使用时可以让它继承不同的控件或模版,让控件本身也可以是容器:
typedef LabelTemplate<Control> Label;
typedef LabelTemplate<Box> LabelBox;
typedef ButtonTemplate<Control> Button;
typedef ButtonTemplate<Box> ButtonBox;
typedef CheckBoxTemplate<Control> CheckBox;
typedef CheckBoxTemplate<Box> CheckBoxBox;
基础控件继承了容器后,就可以拥有控件本身的行为+容器的组合能力。这样做的优点是如果一个基础组件在 UI 上无法满足需求,那么就让他成为容器去任意组合其他的 UI 组件,提升控件的表现能力。同时控件支持在 xml 中编写简单的事件处理逻辑,把一些功能简单的UI控制逻辑放在 xml 中。
3.3 功能强大的 web 展现组件:CEF WebView
CEF(Chromium Embedded Framework)是基于谷歌 Chromium 浏览器内核封装出的跨平台 web browser 组件。
CEF 内部有完整的一套消息循环,我们将网易 Duilib 框架中的 base 线程模型与 CEF 消息循环组合在一起。同时封装CEF的离屏渲染模式(OSR)、窗口模式为网易 Duilib 中的控件 CefControl、CefNativeControl,让 CEF 的 WebView 能力完整的嵌入到网易 Duilib 中。最后我们封装了js与native的通信能力 JsBridge。
CEF执行流程
如此,我们可以使用 CefControl、CefNativeControl 来做单纯的 web 展示控件,也可以以 WebView 为核心,网易 Duilib 为辅助,开发 web app。UI 层的展现都由 web 页面负责,底层的核心逻辑、数据库、网络等由 C++ 负责,web 与 C++ 使用 JsBridge 通信。