本篇目录 1. 桌面GUI开发分类概述
1.1 Windows
1.2 Mac
1.3 Linux
1.4 跨平台--基于原生或自有引擎(传统 C++)
1.5 跨平台--基于Web技术(以浏览器为核心)
1.6 其它语言各自的GUI开发库
1.7 大一统界面开发方案(含桌面端和移动端)
2. Windows API、MFC、WTL
3. WinForm、WPF
4. MFC 、Winform 和 WPF 比较
5. 界面库(非DirectUI思想)
6. DirectUI思想理念
7. DirectUI界面库
8. 跨平台--基于原生或自有引擎(传统 C++)
8.1 Qt
8.2 ImGUI
8.3 wxWidgets
8.4 FLTK
8.5 GTK
9. 跨平台--基于Web技术(以浏览器为核心)
9.1 CEF
9.2 XUL
9.3 NW.js
9.4 Electron
9.5 QQ NT新构架
9.6 WebView2
9.7 TAURI
9.8 webview
10. 大一统界面开发方案(含桌面端和移动端)
10.1 MAUI
10.2 Flutter
10.3 Compose Multiplatform
11. 总结
12. 思考问题
1. 桌面GUI开发分类概述
1.1 Windows 官方
1.1 Windows API C++
C#
1.2 MFC
1.4 WTL
1.3 WinForm(.net)
1.5 WPF
第三方 界面库(非DirectUI思想) 界面库(DirectUI思想) Ultimate Toolbox LibUIDK
CButtonST
Duilib SKIN++
SOUI 炫彩界面库
DuiEngine 迅雷Bolt界面引擎
1.2 Mac Objective-C(或现在的Swift)在Xcode上开发原生应用【Cocoa】,非常方便的调用操作系统底层API,劣势也一样,不跨平台、自定义控件比较复杂,可用资源太少
1.3 Linux GTK,虽然它是一个跨平台桌面软件,但它似乎只在Linux操作系统领域流行
1.4 跨平台--基于原生或自有引擎(传统 C++)
4.1 Qt 自有引擎,各平台界面风格统一
4.2 ImGUI 主要用于游戏,支持多种绘制引擎
4.3 wxWidgets 没有自绘引擎,而是对不同平台下的界面API做了整合和封装
4.4 FLTK (Fast Light Toolkit) 自绘引擎用的是OpenGL
4.4 GTK 自绘引擎(Cairo),也提供了大量系统相关的API
1.5 跨平台--基于Web技术(以浏览器为核心)
5.1 CEF (Chromium嵌入式框架) Chromium Embedded Framework 只封装Chromium
5.2 Electron 封装了 Chromium和Node.js 生态好 多进程 进程间通讯
5.3 NW.js (Node-Webkit) 封装了 Chromium和Node.js 生态变差,不涉及进程通讯
5.4 XUL (User Interface Language) 为 Gecko浏览器引擎构建的私有 UI 语言,为mozilla公司开发,代表产品Thunderbird、Firefox
下面三个是以系统内置浏览器为核心的开发框架,它们会根据不同的操作系统调用系统内置的浏览器动态链接库,对于一个小型的应用程序来说,安装包的体积可以做到小于 10M。开发代码会涉及到浏览器兼容问题。
5.5 WebView2 微软 Edge 浏览器团队推出的跨平台 GUI 引擎,它是闭源的,目前只支持 Windows 操作系统,所以仅使用 Edge 浏览器内核
下面两个框架则更灵活,在 Mac 操作系统上会使用 Cocoa / WebKit 浏览器核心,在 Linux 操作系统上会使用 gtk-webkit2 ,在 Windows 10 上会使用 Edge
5.6 TAURI 基于 rust 语言
1.6 其它语言各自的GUI开发库 Flash Adobe AIR Flex程序
Java swing JFace
Delphi 基于框架(VCL)的,可拖曳、可视化的开发环境
Python Dear PyGui (DPG) 、PyQt
PowerBuilder
......
1.7 大一统界面开发方案(含桌面端和移动端) 7.1 MAUI(.NET Multi-Platform App UI )在一个框架中生成本机、跨平台桌面和移动应用。微软的跨平台GUI框架,不仅仅支持桌面端,还支持移动端,但官方并不支持Linux的桌面端。
7.2 Flutter 是Google开源的UI工具包,使用Dart编程语言。帮助开发者通过一套代码库高效构建多平台精美应用,支持移动、Web、桌面和嵌入式平台。Flutter 开源、免费,拥有宽松的开源协议,适合商业项目。
7.3 Compose Multiplatform 依赖 JVM,是用 Kotlin 编写逻辑的界面和逻辑的,有消息说将来可能会推出 Kotlin/native*,这样就可以不用依赖 JVM 了,但是这可能还比较遥远的事情。
2. Windows API、MFC、WTL Windows API(应用程序编程接口)是一个底层的编程接口,允许开发人员编写 Windows 应用程序。它包含了操作系统提供的大量的功能和操作,如文件系统、网络、窗口管理、用户界面等。
MFC(Microsoft Foundation Classes)是一个封装了 Windows API 的 C++ 类库,它简化了 Windows 应用程序的开发,提供了更高层次的抽象。使用 MFC 可以更方便地创建用户界面、处理事件和控制程序流程等。
WTL(Windows Template Library)是 MFC 的轻量级替代品,它也是一个 C++ 类库,但相对于 MFC 更加精简,主要用于开发较小的 Windows 应用程序。WTL 的设计思想是基于模板的类库,它充分利用了 C++ 的模板机制,提供了一些高效的组件和控件。
MFC 和 WTL 都是基于 Windows API 开发的 C++ 库,它们之间的联系在于都提供了更高层次的抽象来简化 Windows 应用程序的开发。它们的主要区别在于 MFC 提供了更完整的功能,而 WTL 更加精简。开发人员可以根据自己的需要选择适合自己的库来进行开发。
2.1 API
Win32 API提供了基本的窗口和消息处理机制,开发者需要手动处理所有用户输入和输出的细节。这个时期的开发难度较大,但应用程序可以具有较高的性能。
您就需要对 Windows 的窗口、对话框、消息产生、派发与处理机制进行了解,同时也是我们普通程序开发者应该学习和模仿的典范。它本质上就是一个消息队列, Windows 消息队列的实现可以
参考开源版本的”Windows”—— ReactOS。
用户操作-> 产生消息->发送系统->系统判断来源->发给相应的窗口过程或者其他Callback函数->消息处理->等待下一条消息的产生。
以上为消息循环整个过程,下边为伪代码。
2.2 MFC
微软基础类库(Microsoft Foundation Classes,简称MFC)是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类,使得开发者可以更轻松地创建GUI应用程序。MFC提供了一组类来处理窗口和消息处理,简化了开发过程。
2.3 WTL
WTL 是 Windows Template Library 的缩写,由微软的ATL(Active Template Library) 小组开发,主要是基于 ATL 对Win32API 的封装。从 2.0 后,功能逐步完善,成为了一个完整的支持窗口的框架(windows framework),提供了一些额外的GUI控件和工具,使得开发者可以更容易地创建Windows应用程序。WTL的设计目标是提供一种轻量级、高效的GUI开发框架,可以快速构建出高性能、稳定的Windows应用程序。WTL主要适用于开发Windows桌面应用程序。
WTL 功能不如MFC完善,但是比 MFC 更小巧,不依赖 MFC 的DLL。
https://sourceforge.net/projects/wtl/
3. WinForm、WPF
3.1 WinForm Winform是.Net开发平台中对Windows Form的简称,基于.Net Framework平台 的客户端开发技术,一般使用c#编程。
WinForm开发使用Visual Studio集成开发环境(IDE)进行,开发者可以使用Visual Studio自带的可视化设计工具来设计和开发GUI界面,并使用C#语言编写事件处理程序和业务逻辑代码。
3.2 WPF WPF —用于构建 Windows 桌面应用程序的 UI 框架
WPF (Windows Presentation Foundation) 是微软推出的用于构建桌面客户端应用程序的 UI 框架,具有应用程序模型、控件、图形、布局、数据绑定和安全性等功能,属于 .NET Framework 3.0 的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。WPF 的核心是一个利用现代图形硬件的渲染引擎。
WPF(Windows Presentation Foundation)是微软公司推出的一种GUI框架,用于创建Windows桌面应用程序。WPF采用基于XAML(可扩展应用程序标记语言)的声明式编程方式,使得开发者可以轻松地创建富有交互性、高度定制化的应用程序界面。WPF使用C#语言进行开发,同时提供了强大的数据绑定、模板、动画和图形渲染等功能,可以帮助开发者快速构建出高质量的Windows应用程序。WPF还支持使用MVVM(Model-View-ViewModel)模式进行开发,使得应用程序的业务逻辑和界面逻辑可以更好地分离。WPF开发需要一定的学习成本,但它提供了强大的工具和功能,可以为开发者提供更好的开发体验和更好的用户体验。
它允许设计人员和程序员分开工作,因为 XAML 用于设计,而 C# 用于编程。
4. MFC 、Winform 和 WPF 比较 开发效率上,MFC < WPF < WinForm
开发成本,MFC > WPF > WinForm
界面执行效率上,MFC == WPF > WinForm
开发灵活性上:WPF > MFC > WinForm
美观上:WPF > WinForm > MFC
内存使用上:WPF > WinForm > MFC
使用范围:WPF > MFC == WinForm
详情参考:
https://blog.csdn.net/sinat_40003796/article/details/125767203
MFC生成本机代码,自然是很快,可是消息循环减缓了界面显示速度。
WinForm封装了win32的api,多次进行P/invoke操作(大部分使用p/invoke操作封装),速度慢。
WPF是一种新的模型,不再使用win32模型,自己新建模型,使用dx作为新的显示技术,直接访问驱动程序,加快了运行速度,可是,这种模型,需要支持dx9的显卡,硬件要求高
P/Invoke又名平台调用,是.NET CLR提供的,为了使开发者从托管代码(如题主的C#)调用动态连接库中的非托管代码(通常是C)而提供的一种服务。
类似的功能,JAVA中叫JNI,Python中叫Ctypes。因为不同语言,不同开发环境的数据类型、结构都是不同的,
当你使用P/Invoke调用dll的时候,平台会自动给你加载这个dll,并且在托管代码和非托管代码的边界自动完成数据类型转换。
使用P/Invoke的话,一般分为3步:声明,调用,异常处理。
举例,在user32.dll里有一个如下签名的函数:
BOOL SetCursorPos(int X,int Y)
我们在C#中声明
[DllImportAttribute("user32.dll", EntryPoint = "SetCursorPos")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool SetCursorPos(int x, int y);
然后调用
static void Main(string[] args)
{
SetCursorPos(250, 250);
} 复制代码
5. 界面库(非DirectUI思想) 5.1 LibUIDK--mfc skin ui,not directui
https://github.com/iUIShop/LibUIDK
简单来说,LibUIDK是用来开发QQ、360安全卫士那样的漂亮软件界面的。 LibUIDK原来是商业界面库,2019年9月8号开源。是专业开发Windows平台下图形用户界面的开发包,该开发包基于Microsoft的MFC库。使用此开发工具包可轻易把美工制作的精美界面用Visual C++实现,由于LibUIDK采用所见即所得的方式创建产品界面,所以极大的提高了产品的开发速度,并大大增强图形用户界面(GUI)的亲和力。LibUIDK还可以使您的软件轻松具有当今流行的换肤功能,以提高产品的竞争力。 在很多公司或个人研发换肤产品的时候,我们就推出了第一款界面开发工具。与换肤工具不同的是,界面工具贯穿整个项目开发周期,整个项目的界面,都可由LibUIDK完成。LibUIDK提供了比换肤工具彻底的多的界面自由定制功能。
5.2 Ultimate Toolbox-- MFC开源界面库 https://www.codeproject.com/Articles/20182/The-Ultimate-Toolbox-Home-Page
5.3 CButtonST--MFC Flat buttons
https://www.codeproject.com/Articles/57/CButtonST-v3-9-MFC-Flat-buttons
6. DirectUI思想理念 传统Win32界面编程来讲,微软提供一整套界面标准,比如窗口、按钮、滚动条、列表等。对于每一个窗口(控件也是一个窗口),其能响应的消息和行为都有规范(通过API提供给开发者)。微软这套界面标准是为通用场景下提出的解决方案,能够满足绝大部分需求,但业务场景的多样性,使得开发者们并不满足于这套界面标准。
将所有的界面控件都绘制在一个窗口上,这些控件的逻辑和绘制方式都必须自己进行编写和封装,而不是使用Windows的原生控件,所以这些控件都是无句柄的(Windowsless)。
DirectUI是一套开发理念,其主要的思想就是主窗口有句柄HWND,但是子控件Button List 等等都是无窗口句柄的,使用spy++无法抓取控件的HWND。DirectUI界面库取名自微软的一个窗口类名“DirectUIHWND”,意为Paint on parent dc directly。即子窗口不以窗口句柄的形式创建,只是逻辑上的窗口,绘制在父窗口之上。DirectUI界面库使用XML来描述界面风格,界面布局,可以很方便的构建高效,绚丽的,非常易于扩展的界面。从而很好的将界面和逻辑分离,同时易于实现各种超炫的界面效果如换色,换肤,透明等。DirectUI技术说白了就是XML配置文件+图片+JavaScript控制界面。这点与网页css+图片+JavaScript十分相似,就是如开发网页一般开发桌面程序界面,这个开发效率当然大大的提高。
而DirectUI被广为国人所知,还得感谢腾讯公司。QQ2009的界面就是使用DirectUI技术开发的。
总而言之,比较有名的开源免费Directui库有duilib/SOUI/REDM/DuiVision/Bolt(迅雷UI)等等。互联网大厂BAT/网易等的客户端ui就是使用duilib开发的。
相较于传统Win32界面,DirectUI技术有以下优势:
界面逻辑完全分离:界面布局(XML描述),将逻辑与界面解耦,符合界面设计原则。
防止软件被破解:由于DirectUI是建立在Win32界面标准之上,其DUI窗口(子控件也是一个DUI窗口)的消息转发和消息处理因框架设计的不同而异,这些内部逻辑对外不透明,很难破解。也是很多大厂不想开源其界面框架的原因之一吧。
运行效率更高:这个取决于DirectUI框架的实现。由于是在框架内部进行消息转发和处理,并不需要经过系统,理论上效率会更高。
更容易实现绚丽效果和换肤功能:DirectUI框架提供标准控件的同时也提供良好的扩展性。业务层在框架基本上可以很容易定制自己的控件。
其实duilib主打的界面制作方式是XML + UI引擎 + win32框架,其实和浏览器HTML + CSS + 渲染引擎的方式非常类似,可以将其理解为一个非常mini的浏览器。
DirectUI需要解决的问题DirectUI实际是在Windows的原生窗口基础上,更细粒度地进行窗口控制,它需要建立一套自己DirectUI标准,主要需要解决以下问题:
窗口子类化,截获窗口消息;
封装自己的控件,并将控件绘制到窗口上;
封装窗口消息,并分发到自己的控件上,让自己的控件根据消息进行相应绘制;
根据不同行为发送自己定义消息给窗口,以便客户程序处理;
界面与逻辑分离,一般使用XML来描述窗口上控件布局;
7. DirectUI界面库 7.1 Duilib Duilib 是 Windows 系统下的开源的 DirectUI 界面库(遵循 BSD 协议),完全免费,可用于商业软件开发。Duilib 可以简单方便地实现大多数界面需求,包括换肤、换色、透明等功能,支持多种图片格式,使用 XML 可以方便地定制窗口,能较好地做到 UI 和逻辑相分离,尽量减少在代码里创建 UI 控件。目前,Duilib 已经在国内有较为广泛的使用。
https://github.com/duilib/duilib
使用XML控制窗口布局描述,程序逻辑用C++实现,简单看下duilib的UI架构图
再次强调下win32/MFC的界面 和duilib 界面的区别:
(1)MFC中将按钮、菜单、标题栏等等都当作不同的东西(例如标题栏只能放在最上面,按钮不能直接拖到标题栏等等);
duilib中将所有的东西都同等对待,所以处理起来非常方便(别说把按钮放到标题栏上,就算把标题栏放在按钮上都没问题)。
(2)MFC中所有的窗口和控件都是继承于CWnd(win32继承于HWND)。
duilib中所有的控件都继承于CControlUI,所有的窗口都继承于CWindowWnd(内部包装了HWND)。
所以如果用MFC做一个界面,那么上面就是很多个CWnd,用Spy++可以看到不同的窗口句柄。
如果用duilib做一个界面,那么上面就是很多个CControlUI,但是用Spy++只能看到一个窗口句柄。
这是因为duilib整个窗口只有一个HWND,其他的CControlUI虽然是控件,但是其实都是自己绘制出来的,并不是真正的HWND,所以你可以把这些控件理解为自绘,整个duilib的界面绘制,就是在自绘一个HWND。
Duilib实现效果图
7.2 SOUI SOUI是目前为数不多的轻量级可快速开发window桌面程序开源DirectUI库.其前身为Duiengine,更早期则是源自于金山卫士开源版本UI库Bkwin.经过作者多次开发维护升级后得此库.SOUI其寓意为"瘦UI" "UI,just so so!"
SOUI官方博客 启程软件 - 博客园
7.3 DuiEngine DuiEngine -- ★金山卫士★
金山卫士开源项目带的ui界面库
金山卫士开源计划 {v11.08.8.0}
开源卫士社区
7.4 SKin++ http://bolt.xunlei.com/index.html
Bolt 界面引擎是迅雷公司从 2009 年开始开发的第四代界面库。迅雷 7 是首个采用该引擎成功开发的产品,目前迅雷旗下大部分客户端产品都基于该引擎开发,并稳定运行于超过 3.5 亿台 PC 上。
使用Bolt界面引擎,你需要首先掌握一门简单高效的脚本语言:lua,并学会使用XML。开发完整的产品,还需要掌握使用C/C++给lua环境扩展功能的方法。Bolt界面引擎是为了能高效开发一流的,需要长期维护与改进的工业级产品而设计,并不是一种(也不希望)能快速上手,然后随便拖拖控件完成一些玩具产品的快速RAD开发框架。目前,“Bolt”只专注于交互开发,光掌握它并不能让你完成一个完整的应用产品。因为我们希望Bolt能成为您完成伟大产品过程中的一件称手兵器,而不是让工程师最后变成了技术的追随者。
7.7 DirectUI扩展 微软自己的产品Visual Studio 和Office 也都是用Windowless 渲染的技术
这种技术渲染效率高,占用系统资源少。DirectUI 是在 Windows 2000 和 Windows XP 之间开发的,作为一个实验性的可视化框架。DirectUI 早于 Avalon(又名 WinFX 后来又叫做 WPF),可以看到 DirectUI 和 Avalon 之间有许多相似之处。写 DirectUI 的开发者在 Avalon 团队成立时都加入了,所以精神上的联系并不意外。
也可以将 DirectUI 视为 Avalon 的更简单且功能更弱的先驱。
由于 DirectUI 是实验性的,围绕它的许多过程都没有正式化。特别是,DirectUI相当自由地分叉,没有统一的版本。
Windows XP DirectUI:Windows XP 在三个地方使用了相对较早的 DirectUI 版本:资源管理器任务窗格、欢迎屏幕和添加或删除程序控制面板。
MSN Explorer:在 Windows XP 之前,代码分叉并复制到了 MSN 团队,他们使用它运行并生成了 MSN Explorer。
Messenger:Messenger 团队从 MSN Explorer 团队获得了 DirectUI 的副本,并进行了大量更改,尤其是在可访问性方面。
Office NetUI:与此同时,DirectUI 的一个分支版本也交给了 Office 团队,他们将其用作他们称为 NetUI 的框架的基础。
Office FlexUI:Office 人员进一步开发了 NetUI,并制作了 FlexUI。
Windows Vista DirectUI:Windows Vista DirectUI 从 Windows XP DirectUI 开始,并合并到 Messenger DirectUI 的选定部分中。
Windows 7 Ribbon:Windows 7 功能区基于 Office 功能区,因此是 Office NetUI/FlexUI 的一个分支。Windows LiveDUI:Live 团队开发了他们自己的 DirectUI 分叉版本,并从 Wave 4 开始发布。
现在的Office 应该是FlexUI,Visual Studio 也是类似的技术。这一点很好检验,你用SPYXX 工具去测试一下这两款产品,整个界面只有一个Windows 句柄HWND。如果是MFC 界面库或者.NET WinForm 又或者是DELPHI写成的,那么每个控件都是一个窗体,都有一个句柄。
这东西原理上就是轮子哥写的GacUI,他就在Office team。
7.8 DirectUI扩展--GacUI GacLib (GacUI) 是支持显卡加速的 C++ Windows GUI 库。这个库具有类似 WPF 的高级排版和控件模板功能,并且可以被 C++ 方便的使用。当选择 Direct2D 作为渲染器的时候,一个空白的 GacLib 程序静态链接 crt 只需要 700k 可执行文件大小和 6M 内存。GacLib 的控件不需要消耗 Windows 的 HWND 资源,这使得控件本身占用的资源减少,性能提高,并且不会影响到其他程序的正常运转。
专访轮子哥:我在微软「造轮子」,一不小心成了知乎大V
https://blog.51cto.com/csnd/5710894
GacLib的意义分成三层:对轮子哥自己的意义:一个持续了三年并将不知道持续多久的大型cpp轮子,差不多算得上钢铁之星了,坚持做这件事下来,无论是对设计、代码的品味还是对轮子的掌控能力都大大提高了,这是很宝贵的财富,而且做起来还很有趣。对用户的意义:无需多言 对我们这种看客的意义:知道有这么一个大牛。
8. 跨平台--基于原生或自有引擎(传统 C++)->Qt
8.1 Qt
相对于Duilib只是一个 Windows 下的纯 UI 框架,那么Qt就是一个平台,它不仅仅有 UI 能力部分,还包括跨平台的基础组件(如类似标准库的各种容器、线程管理、内存管理等),只要你遵守使用规则,让你一套代码可以在多个平台下跑,与 Duilib 一个级别的是 Qt Widgets 和 Qt Quick,这是两种不同的 UI 解决方案。
Qt几乎是C++领域最流行的跨平台桌面端软件开发框架了,这个框架是两个挪威人在1995年创建的,发展至今可以说历史相当悠久,稳定性也很有保障。
很多大公司都在用它做界面比如金山的WPS。
它内置了自绘引擎,也就是说界面上的一个按钮,一个文本框,都是Qt的引擎自己画的,这保证了基于Qt开发的软件界面在不同操作系统上看起来是一模一样的。
它提供了大量的与界面无关但与软件开发息息相关的API,比如、网络、文件系统、剪切板等,而且让这些API在不同的操作系统下都有效,这极大的节省了开发人员的时间。
Qt商业授权不太友好,开发商业应用一定要谨慎,否则可能为此付出了高额的版权费。个人开发者可以免费使用。
Qt的免费版本不允许静态链接,会有版权上的限制,但开发者还是可以通过一些特殊的编译方法静态连接Qt的库的。
除了使用C++开发Qt应用外,开发者还可以使用其他语言开发Qt应用,最流行的就是使用Python基于PyQt做Qt应用了,但PyQt仍然有版权的问题。
QT程序有三种不同的窗体类型,包括QWidget,QGraphics,QQuick,他们的渲染机制也不相同。
QWidget是最常用的UI界面类,其实现方式是对各平台对应控件的封装,通过平台自身的绘制工具绘制界面,可以直接使用OpenGL。
QGraphics是QT为了提升大量简单组件的渲染性能而创造的模块,不一定需要使用OpenGL。
QQuick是QML(一种声明式的界面编程语言)应用程序使用的QT库,从Qt Quick 2.x 起统一使用OpenGL ES 2.0 或者 OpenGL 2.0来渲染界面。渲染方式更倾向于优先使用显卡,通过硬件来加速,所以现在使用QML需要良好的显卡支持。
8.1.1 Qt Widgets Qt Widgets 和 Qt Quick 的优点显而易见,跨平台、有专业团队维护、细节功能实现完善、高性能渲染引擎。
Qt Widgets,这是 Qt 传统的 UI 解决方案,更贴近桌面系统的 UI 框架,如果你想做出理想效果,需要掌握 QSS(类似 CSS)。
Qt Widgets也支持界面描述语言(XML描述界面),可以通过设计器拖拽空间设计界面,编译期界面描述语言被转义成C++代码。
8.1.2 Qt Quick而 Qt Quick 则为了适配现有的移动端场景(当然也可以开发桌面应用),你需要掌握 QML 语法、JavaScript 语法。
Qt 想用 QML/Qt Quick 一统天下(桌面 + 移动端)。梦想还是要有的,万一实现了呢?
Qt Quick 是 QML 类型和功能的标准库。包括视觉类型、交互式类型、动画、模型和视图、粒子效果和着色效果,可以使用单个 import 语句访问所有功能。
Qt Quick 全称:Qt User Interface Creation Kit,主要包含以下特征:
一个为创建更好界面的高级 UI 技术
无需掌握 C++ 技术,JavaScript 知识会有不少帮助
针对界面设计人员和开发者
使设计师和开发人员“说同样的语言”
双方可以同时参与迭代开发
无需单独的 Flash 或 PPT UI 原型
QML 是一种用户界面规范和编程语言。它允许开发人员和设计师创建高性能、流畅的动画和视觉吸引人的应用程序。QML 提供了一种高度可读、声明性、类似 JSON 的语法,支持与动态属性绑定相结合的命令式 JavaScript 表达式。
QML 全称:Qt Meta Language 或 Qt Modelling Language
8.2 ImGUI(即时渲染)ImGUI又称为Dear ImGui,它是与平台无关的C++轻量级跨平台图形界面库,没有任何第三方依赖,可以将ImGUI的源码直接加到项目中使用,也可以编译成dll, ImGUI使用DX或者OpenGL进行界面渲染,对于画面质量要求较高,例如客户端游戏,4k/8k视频播放时,用ImGUI是很好的选择,当然,你得非常熟悉DirectX或者OpenGL,不然就是宝剑在手,屠龙无力。相对于Qt、MFC、DuiLib、SOUI等,ImGUI的拓展性更好,也更轻量级,当然对于开发者的要求也更高.
此GUI框架的实现原理和开发方式可谓独树一帜,它在一个无限循环里不断的重绘整个界面,别的GUI框架都是哪里更新了重绘哪里,它是无论有没有更新,一股脑全部重绘,而且一直在重绘,这样做对于一些不支持GPU的客户端来说CPU消耗会略高一些,不过总起来说还算好。
它对游戏开发者很友好,很多游戏都集成它来做用户交互(游戏内的一些设置界面、聊天界面之类的)
它支持很多种绘制引擎比如OpenGL,Directx,Vulkan等
打包后体积很小,也就几百K的样子
ImGUI主要用于游戏行业,所有的控件都需要手绘实现,当然性能也是满满的,毕竟是直接用dx/opengl来实现。
渲染器:DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU。
平台:GLFW, SDL2, Win32, Glut, OSX, Android。
框架:Emscripten, Allegro5, Marmalade。
语言:C, c#和:Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift…
框架:AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x,勤奋引擎,Flexium, GML/Game Maker studi2, GLEQ, Godot, GTK3+OpenGL3, Irrlicht引擎,LÖVE+LUA, Magnum, Monogame, NanoRT, cine, niine Game Lib,任天堂3DS & Switch (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D,SDL_Renderer, sml, Sokol, Unity,虚幻引擎4,vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets。 复制代码
ImGUI仓库:https://github.com/ocornut/imgui
8.3 wxWidgets
http://www.wxwidgets.org/
wxWidgets是1992年英国的一个大学教授开创的跨平台GUI软件,也非常成熟稳定,商业授权非常友好。
它没有自绘引擎,而是对不同平台下的界面API做了整合和封装,这样开发者在Windows下开发的软件看起来就是Windows窗口风格、Linux开发的软件看起来就是Linux窗口风格,这对于某些软件来说,正是他们想要的,但要想搞一些花哨的特效就没那么容易了。它同样也提供了大量的系统相关的API供开发者使用。
它是C++开发的,所以对C++开发者非常友好,
除此之外它还支持静态连接,也就是说开发个应用不用分发给用户一大堆dll。
除了开发的界面比较死板外,没啥大的问题。
8.4 FLTKFLTK全称:Fast Light Toolkit
FLTK是1998年创建的跨平台开源GUI框架,历史悠久,商业授权友好,而且C++之父也用它,它非常轻量级,支持静态连接,一个简单的应用编译后只有500K左右,非常赞。
它有自己的自绘引擎,用的是OpenGL,
但它的重绘机制是按区域重绘的,如果组件A所在的区域上存在组件B,那么A组件重绘时,会把B组件的给重绘掉,开发者必须自己写代码处理这种情况。
想象一下,如果你想实现一个A组件fade out的同时B组件fade in的效果,就会非常麻烦。
FLTK提供的一些组件样式都比较刻板,绘图API也比较少,你想实现一个漂亮一点的圆角按钮(它内置圆角按钮的圆角大小是不能改的),必须自己画,而且还得借助一些非常奇葩的手段才行,它是C++开发的,但API不够现代。
8.5 GTKhttps://www.gtk.org/
GTK是1997年创建的,也非常成熟稳定,它是C语言开发的,有很多语言的绑定,比如官方支持的JavaScript、Rust等,当然用C++语言操作GTK也很方便。
它也有自绘引擎(Cairo),也提供了大量系统相关的API,商业授权也非常友好,基于GTK开发商业软件不用担心收到律师函的问题,虽然它是一个跨平台桌面软件,但它似乎只在Linux操作系统领域流行,有非常多的Linux桌面软件都是基于GTK开发的。
这也直接导致GTK的维护者很重视Linux领域的发展,而忽视Windows和Mac领域。
这个框架提供的很多API,只在Linux下有,Windows和Mac下没有。这样的API数量众多。
甚至在Windows下编译一下GTK的源码都要比Linux下难很多。
而且GTK的渲染引擎在Windows下性能表现也不如在Linux下好。
GTK在Windows上也没办法静态连接,倒不是因为版权的问题,而是它依赖了MSYS2的一些库,这个库用于在Windows上模拟Linux环境,这也是为什么GTK在Windows上表现不佳的原因之一。
另外,由于GTK是C语言开发的,所以开发风格也很C语言化,这对于部分开发者来说可能觉得繁琐。
9. 跨平台--基于Web技术(以浏览器为核心) 9.1 CEF
https://bitbucket.org/chromiumembedded/cef/src/master/
CEF 是 Chromium Embedded Framework 的简写,顾名思义,这是一个把 Chromium 嵌入其他应用的框架。这个开源项目是 Marshall Greenblatt 在 2008 年创立的,由 C/C++ 编写而成,它通过提供稳定的 API 来避免开发者被 Blink、V8、Chromium 等复杂的代码逻辑所困扰。CEF 非常注重开发者的使用体验,很多功能都有默认实现方式,遵从约定优于配置的原则,开发者可以很轻松地驾驭 CEF 框架。
CEF 是一个商业授权非常友好的开源项目,它采用的是 BSD 授权协议,这也是那么多大厂都选择 CEF 作为桌面端开发框架的原因。据 CEF 官网数据,CEF 框架装机量已经超过了 1 亿,这个数据量还是挺惊人的。
目前市场上很多知名应用都使用 CEF 框架构建 GUI 界面,比如网易云音乐、微信 PC 端、QQ 桌面端、MATLAB、 FoxMail、OBS Studio 等。
由于它几乎封了一个完整的Chromium,它支持所有的HTML\CSS\JS特性,它几乎不提供任何与操作系统相关的API,创建个托盘图标、读写个文件啥的,都要开发者自己完成,它是C/C++开发完成的,对C++用户非常友好,它有go\python\java等语言的绑定,但都是社区提供的。
与Electron一样,它也是分主进程和渲染进程的,所以开发者要非常娴熟的运用跨进程通信的技术,
虽然CEF提供了跨进程相关的API,但复杂度还是有点高的,使用的时候要认真细心。
CEF还提供的如下特性:自定义插件、自定义协议、自定义JavaScript对象和扩展;可控制的resource loading, navigation, context menus等等。
谁在用CEF
各种浏览器
早期的双核浏览器(IE + Webkit),有些使用了CEF来作为Webkit内核浏览器控件。
对于浏览器来说,直接在Chromium上面扩展,其实才是王道,大家现在都这么做了(各种极速浏览器)。
Evernote Client (on Windows)
印象笔记允许用户将网页粘贴到笔记中,还提供了插件用来将网页保存为笔记。
GitHub Client (on Windows)
GitHub也打包了libcef.dll,从表现上面看,用来展示项目的ReadMe页面的,肯定是CEF,其他地方的UI,可能部分也是用页面来实现的。
QQ
QQ很早之前就通过内嵌IE来实现一些功能和界面。QQ引入了CEF,对一些之前用IE的地方进行了替换,这样就可以使用一些基于Webkit的新特性,同时也获得了速度、稳定性、兼容性方面的优势。
Adobe Edge Animate & Adobe Edge Reflow
Adobe推出了一整套制作现代网页的工具,取名Edge。
Adobe Edge Animate,做动画用的,Edge Reflow则是Design the responsive web. 有人翻译为响应式,其实就是自适应了。上面两款软件,都使用了CEF。
Q+
Q+在Web App的概念下,为Web页面提供了一个运行环境(简单来说就是:Client的一个框和一些可用的API),引入的Webkit内核(实际上是CEF),无需考虑IE的版本兼容问题,提高了开发效率。
9.2 XUL 混合型的Web(HTML+DOM+CSS+JavaScript)能提供的东西比传统桌面UI开发所需要的要多得多。于是XML User Interface Language(XUL)诞生了。XUL引入了一种基于XML的语言,可以用来描述一个对话框或者窗口的布局,就像HTML向浏览器描述Web页面的布局一样。
XUL 是为 Gecko 引擎构建的私有 UI 语言。它受到基于 Gecko 的 Web 浏览器开发人员的青睐。这是因为它是构建在标准技术(例如 XML、JavaScript 和 CSS)之上的。
它是为了支持Mozilla系列的应用程序(如Mozilla Firefox和Mozilla Thunderbird)而开发的使用者界面标示语言。
XUL里的元素就相当于Gtk+、Cocoa或.NET Forms等原生GUI工具包里的widget。
9.3 NW.jshttps://nwjs.io/
NW.js最早把Chromium和Node绑定到一起,用前端知识做界面,用Node技术访问操作系统,最早叫node-webkit,在2012年创建。NW.js基于MIT开源,可以无忧使用。
微信小程序开发工具好像是用NW.js开发的。作者是英特尔的员工,英特尔的一些工具也是用NW.js开发的。
除了Chromium和Node的能力外,NW.js自己也封装了一些系统级API,类似托盘图标、剪切板、系统菜单这种,但数量明显比Electron要少。
NW.js可以在多个窗口间共享同一个Node.js上下文,而且还可以通过配置让Node的上下文和Dom上下文混合,这给开发者带来了很多便利。
不像Electron要时刻想着进程间通信,哪些模块当前进程不能用这类问题。NW.js虽然起步早,但奈何没有杀手级应用,周边的生态和工具链没发展起来。
9.4 ElectronElectron是GitHub发布的跨平台桌面应用开发工具,支持 Web 技术开发桌面应用,其本身是基于 C++ 开发的,GUI 核心来自于 Chrome,而 JavaScript 引擎使用 v8。
Electron的作者曾经在NW.js团队工作过(NW.js项目贡献第二多的人就是Electron的作者),后来辗转到了github公司,于2013年在创建了Electron,也是个开源免费的产品。由于VSCode、slak等国际型产品都选择了Electron,所以从者甚众,生态和周边工具链也完善的多。
开发方式上采用多进程架构及模块归属进程,Electron每创建一个窗口都会多一个进程,这使Electron创建窗口的效率不高(秒级),NW.js有复用进程的机制,即使新窗口加载完全不同域的页面也不会创建新的进程(毫秒级)。这也是为什么很多基于Electron开发的应用都使用Dom模拟弹窗的原因。
无论是浏览器相关的API,还是系统级API,Electron提供的都比NW.js多。
9.5 Electron与nw.js区别electron和node-webkit(现在叫nw.js)的区别:
从概念上,Electron与nw.js很相似,但是他们有很重要的区别:一个主要的不同点是Electron 通过 Googles Chromium Content Module 来使用 Chromium 的功能,nw.js 则直接使用了 Chromium本身。
electron建立在 Chromium 和 NodeJS 之上的,一个负责界面,一个负责背后的逻辑
electron的特点就是可以复用前端的各种轮子。所以它开发快,招人方便。
可以方便的通过Node.JS调用系统API、可以使用SQLite做本地字典项的缓存处理,可以将复杂的计算逻辑放在客户端进行,从而减轻服务器端的压力等等。
9.6 由Electron引出QQ NT新构架实现多个系统平台之间QQ架构的统一。
QQ桌面端主要有Windows、MacOS和Linux三个版本,三个版QQ各自为政,由不同的团队开发、管理。这不仅极大地增加了QQ的整体维护成本,还限制了QQ的迭代速度。经NT技术重构后的QQ桌面端,不仅在不同系统中实现了一致体验,还更易于维护,性能也更稳定、发送更流畅。基于QQ NT架构的QQ Linux桌面端,还全面支持了龙架构(LoongArch),至此QQ原生应用终于可以同时在X86、ARM、LoongArch三大主流CPU架构上完美运行。未来,在UOS、麒麟、Loongnix等新兴操作系统上,用户也可以使用到和Windows一样的QQ。QQ NT技术的底层框架是Electron。
一提到Electron,很多人最先想到的就是“占内存”问题。
其实这个问题并不是无解,腾讯既然选择它,就一定找到了解决方案。据QQ工程师介绍,根据QQ的不同使用场景,在Electron与Native通信层面做深度定制优化,再把一些内存泄漏的场景排除,内存控制就可以做到不错的水平了。接下来的事,就是小步快跑、快速迭代,力求在最短的时间内把体验做到极致。根据此前披露的信息,新版QQ的更新周期是一到两周,或更短。
有人说,选择优势和争议都非常明显的Electron作为QQ NT技术的架构底座,是腾讯的一次豪赌,不确定性很大。但在笔者看来,这恰恰是腾讯创新精神的最好诠释。在过去相当长的一段时间里,腾讯QQ的用户体验一直是国产软件的天花板。之所以会如此,就是因为腾讯始终保持对新技术敏感,并敢于打破常规。优秀体验的背后一定是持续不断的技术创新,用户这里越是感觉平平无奇,背后的技术挑战越异常艰巨。
9.7 WebView2https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/
这是微软Edge浏览器团队推出的跨平台GUI引擎,是闭源的,目前只支持Windows,对C#和C++开发者友好,
如果使用C#开发,就得考虑把.NET运行时分发给用户,如果使用C++开发,就得自己处理系统级API的操作,webview2本身是不对系统级API做封装的。
它的优势是可以复用系统当中已存在的webview2二进制资源,如果你电脑已经存在了基于webview2开发的应用,你的安装包体积可以足够小。
它也是多进程架构,甚至比Electron还要多一个进程(为了复用二进制资源),资源占用比较多。
9.8 TAURI使用 Web 前端构建更小、更快、更安全的桌面应用程序。
Tauri 是一个框架,用于为所有主要桌面平台构建小巧、快速的二进制文件。开发人员可以集成任何可编译为 HTML、JS 和 CSS 的前端框架,以构建他们的用户界面。应用程序的后端是一个基于 Rust 的二进制文件,带有一个前端可以与之交互的 API。
Tauri 应用程序的用户界面目前在 macOS 和 Windows 上利用 tao 作为窗口处理库,在 Linux 上通过 Tauri 团队孵化和维护的 WRY 利用 WebKit、Windows 上的 WebView2 和 Linux 上的 WebKitGTK 创建一个统一的系统 webview(和其他好东西,如菜单和任务栏)接口。
https://github.com/webview/webview
这个库使用操作系统的浏览器引擎来达到减小安装包体积的问题,Mac上使用Cocoa/WebKit,Linux上使用gtk-webkit2,Windows 10上使用Edge(也就是上一个小节里提到的webview2),
它是不支持Win7的。由于不同的OS会用不同的浏览器核心,所以开发者使用它开发跨平台应用时要考虑前端代码浏览器兼容的问题。
开源且免费(MIT)有go、Rust、Python等语言的绑定,不过官方支持的是go语言,C和C++,操作浏览器的API非常少,不支持自定义scheme,更别提系统级API了。
10. 大一统界面开发方案(含桌面端和移动端)
10.1 MAUI
https://github.com/dotnet/maui
这是微软的跨平台GUI框架,不仅仅支持桌面端,还支持移动端,但官方并不支持Linux的桌面端,
.NET Multi-Platform App UI
这个框架新的很,至今还没发布稳定版。
它是.NET平台下的GUI框架,有自绘引擎,对C#开发者很友好,界面依然是用XAML描述的,可能很多人一听到XAML就直接弃坑了。
XAML表现力确实弱一些,我觉得WPF没火起来跟XAML有直接关系,也是相对来说吧(比HTML/CSS弱)。
使用这个框架开发桌面应用得封一个.NET框架给用户,当然有了.NET框架应用程序访问一般的系统级API也就不成问题了。
.NET Multi-Platform App UI (.NET MAUI) 是 Xamarin.Forms 的演进,它将功能从移动 Android 和 iOS 扩展到适用于 Windows 和 macOS 的桌面应用程序。
10.2 Flutterhttps://github.com/JetBrains/compose-multiplatform
Compose Multiplatform 依赖 JVM,是用 Kotlin 编写逻辑的界面和逻辑的,有消息说将来可能会推出 Kotlin/native*,这样就可以不用依赖 JVM 了,但是这可能还比较遥远的事情。Compose Multiplatform 的组件也是比较丰富的,大家都知道 Java 社区中有很多框架、模块等都可以使用,并且也是支持应用端的。
11. 总结 UI承载着跟用户交互的职能。从早期二进制打孔到命令行到现在的窗口可视化,其本质是降低使用计算机的门槛,提高使用计算机的效率。而从UI发展来看,DirectUI只是在有句柄的窗口上进行更细粒度的控制;再往上抽象来看,Windows系统制定窗口标准,实际上是对显存更细粒度的控制;不管是有句柄窗口还是无句柄窗口,其目的无非是提高计算机跟用户的交互能力和开发效率。
总结了三个判断桌面软件开发框架是否优秀的底层逻辑,可以帮助我们开发者认清真相,做出最优选择。
第一,是否具备独立的界面描述语言( UI DSL )。
这非常重要,是一个框架表达业务的重要能力。
类似 WPF 的 XAML、Qt ui 文件里的 XML、 HTML + CSS 都属于界面描述语言,这都属于一种通过特化的 XML 来描述界面的方式;
还有一种通过代码来描述界面的方式,flutter、qml 和 Compose Multiplatform 都以类似这样的界面描述语言来描述界面的。
但无论如何,显而易见的是,没有任何一个界面描述语言能比得上 HTML + CSS 组合。
想想看:HTML 里各种五花八门的语义化标签和 Dom 操作技巧、CSS 里的布局方式、伪元素、动画描述等,就会明白这一点。
第二,是否拥有强大的事件处理机制。
作为一个 GUI 应用,与用户的交互、与设备的交互必不可少,这就涉及到形形色色的事件,比如,与设备有关的鼠标事件、键盘事件、触屏事件、网络状态变更事件等,与界面元素状态有关的界面加载完成事件、媒体播放结束事件、元素大小改变事件等。
另外,能接收这些事件还远远不够,还得处理事件冒泡、事件捕获、事件分发,等等。
这一点上 JavaScirpt 与浏览器核心的结合来处理各种各样的事件也是表现出众。而且经历了数十年的发展,这套组合的事件系统也相当成熟稳定。
第三,是否拥有强大的异步、并行处理机制。
开发者不能在处理用户业务逻辑的时候,让界面渲染工作阻塞,
这就需要一个强大的异步、并行处理机制,如果让开发者自己去创建线程并完成这些工作,无疑是又麻烦又会增加开发者的心智负担。
JavaScirpt 虽然是单线程执行的语言,但浏览器核心是多线程的(还是多进程的),所以 JavaScript 与浏览器核心结合后,开发者既不用为开发多线程应用而苦恼,又不用为没有多线程的支持而手足无措。
从以上三方面的技术需求来看,在桌面 GUI 应用里封装一个浏览器核心还是非常有价值的,这样开发者就可以用 HTML + CSS 强大的能力来描述界面,用 JavaScript 强大的事件处理机制和异步处理机制来完成用户交互。
web相关的技术之所以胜出,并不是这些技术的设计者有多厉害,而是这20多年间,有大量的人涌入了这个领域,前赴后继的推动着它前进。其他任何一个领域都没有这么热火朝天的景象。
List of widget toolkits
12. 思考问题 开发SVG界面库可行性?
把客户端界面做的像游戏界面一样炫行不行?