C++从零编写 GUI?老司机分享多年开发心得

2024-07-29
来源:网络整理

我在知乎上回答“如何用C++从零开始写一个GUI?”这个问题,是比较粗略的讲解了我开发GUI引擎的一些经验。

移至csdn并保存

虽然上面的回答已经很全面了,但是作为开发多年界面引擎的老手,我还是想补充一些内容,并且给大家展示一下我做的引擎。

我做过三代HMI图形界面引擎,从传统的基于控件组织的GUI界面引擎,到现在主流的移动平台用的支持各种动态效果的NUI(用户)界面引擎。首先给大家展示一个使用我的NUI界面引擎开发的产品示例视频。这是一款图形化的轻量级项目管理工具。

以下地址可以下载此软件项目管理软件的版本,免费

我的图形引擎采用C++开发,跨平台,支持Mac IOS等主流系统

也就是说基于这个引擎开发的界面不仅可以运行在 上,还可以直接移植到其他平台上,而应用层UI代码保持不变。

同时也没有实现各种动态界面效果的压力(要知道使用MFC制作滑动界面对于程序员来说是一个巨大的噩梦),界面使用起来也非常简单,丝毫不比Java复杂。

小伙伴们可能会有疑问:

1. 是一样的吗?

它不一样。它是一种解释型语言。源代码一旦写出来,就可以在所有平台上使用。它依赖于每个平台的浏览器来解释它。我们使用 C++,它需要为不同的平台重新编译。

2. UI 是用 Java 写的,iOS 是用 C++ 写的。你们的 C++ 引擎能同时支持这两个平台吗?

IOS是完全兼容C++的,可以理解为C++的升级版,使用C++引擎是没有问题的。

底层来说,C++代码完全可以运行在JNI下层,只需要封装一层Java层即可。

也就是说你可以在一个平台上开发出界面,然后在其他平台上编译运行,运行效果可以一致。

3. 为什么你想开发自己的引擎?现有的引擎不是很酷很棒吗?

首先跟我们的业务有关,我们是做车载设备软件的,早期要面对各种平台,各种定制化的嵌入式系统,qnx,不可能每个系统都做一套UI。

这个系统基本没什么好的图形引擎,你说的是MFC吧?当时嵌入式设备的运行速度完全让人受不了(CPU)

唯一可靠的跨平台 GUI 引擎是 QT。但是如果用于商业用途,则需要花钱,而且价格不菲。

所以我开始编写自己的引擎,用轮子和火从头开始重建它。

我们来谈谈主题发起者提出的问题:如何使用轮子和火来构建图形界面?

“获取输入消息”和“输出到屏幕”是图形界面的“轮子”和“火种”。这两种方式都依赖于操作系统提供的接口,而不同操作系统的接口可能并不相同,即使是同一个操作系统,也有不同的实现方式。对于一个跨平台的图形界面引擎来说,这两部分的代码基本是不能跨平台的,针对不同的平台会有不同的实现,但这两部分的代码不会太多,封装好也不会影响上层的开发。

现在我们有了轮子和火,我们如何开始构建图形界面引擎?

至于图形界面引擎,超出了本文的讨论范围,可以使用第三方开源图形库,有能力也可以自己写。我前两代界面引擎使用的图形引擎都是我自己开发的。在做第三代 NUI 引擎的时候,已经有不少优秀的开源图形引擎,而且还是跨平台的,所以就用了第三方图形引擎。毕竟专业的人做专业的事,虽然自己做的事情也不错,但费时费力,而且在架构和功能完备性上还是专业图形引擎更胜一筹。

虽然界面引擎依赖于图形引擎,但通过良好的架构设计,可以弱依赖。强依赖是指用完图形引擎后不能再改,弱依赖是指不满意可以改。一般2D图形引擎都是软渲染的(不使用GPU加速,否则效果有限),针对特定平台,可以换成这样的3D引擎

既然确定了图形引擎,接下来就是真正的主角——界面引擎了。首先我们来定义一下什么是界面引擎。它并不是软件产品的最终形态,而是开发图形应用软件的中间件。一个优秀的界面引擎必须满足

1.能够实现各种界面效果和功能

2.能够轻松实现界面效果和功能

3.能够高效、轻松地实现界面效果和功能

这是最初的愿景要求。为了实现这一点,必须精心设计输入和输出架构。

控件:建立控件(现在更通俗的叫法是视图)机制,组合控件、控件组等层级机制,简单的初始化接口,支持多种风格的定义。对控件进行整体管理。

绘制:控件的绘制机制,绘制重叠的顺序

消息机制:如何有效、高效的分发OS原生的消息。当用户点击屏幕时,界面引擎需要判断点击了哪个控件,生成什么消息。

常用控件集合:在基础框架稳定之后,我们需要制作一些常用的基础控件,供应用层直接使用,比如按钮,列表,滑块,进度条等。

微信小程序开发从零学起_开发微信小程序的平台有哪些_微信开发平台小程序

特殊控件:一些特殊控件,例如模态对话框、弹出菜单等,其设计与常规控件不同,基本上需要全局管理。

编辑工具:是否需要图形化的界面编辑工具?对于静态界面,比如对话框、各种按钮、列表框等,一个所见即所得的编辑工具会提高界面开发的效率。笔者的第一代、第二代引擎也提供了界面编辑工具,但是第三代NUI引擎却没有,因为现在的界面动态内容太多,而且界面元素是可以移动的,所以单纯的静态界面编辑工具已经没有意义了。

作者早期界面引擎的界面编辑工具

动画支持:对于传统的GUI界面来说,以上这些都可以完成,成为界面引擎。但是在之后的软件时代,用户已经不再满足于静态的界面交互体验,各种基于使用场景的动态变化已经成为图形界面的标配,因此也需要建立对控件的动画支持。

动画支持好是需要一些技巧的,虽然可以提供定时器消息让开发者在应用层实现一些动画效果,但是调用起来不方便,交互时问题也很多,用MFC或者GTK去实现界面就知道了,所以界面引擎提供原生的动画效果也很重要。

原来MFC控件加个图片按钮那么难,但它却是很多界面开发者的启蒙老师,就是从它开始我才逐渐了解了消息循环,了解了屏幕显示的机制,虽然过程很痛苦。在之后几年的工作中,我接触了很多其他的UI引擎,对整个图形界面运行机制有了更深入的理解。机缘巧合下,我自己也鼓捣过几个界面引擎,不过主要用在公司内部产品中,也考虑过开源,让它更有价值。网站和域名我都申请过了,但现阶段还没精力去整理。

要想自己开发一个界面引擎,首先必须对一些现有的界面库有很深的理解,不但要会用,还要知道背后的实现机制和故事,否则你只是一个使用者,而不是创造者,使用者并不是一个贬义词,能把一个引擎用到极致也是一件很了不起的事情。

接触过一些图形界面库,但并不是每一个都深入用过,基本架构和原理了解一点,MFC了解多一点,QT用得比较多,前几年学过,但这几年没怎么做过IOS开发,应该发展很快。

人机界面的发展经历了三个阶段

1.命令行界面(CLI)

命令行的用户行为模式是记忆->输入,用户需要记住每一条命令,然后输入才能与机器交互,使用门槛较高,现在只有专业人士和想要展现黑客牛逼的好莱坞电影才会用到。

2. GUI图形界面

由苹果推出并开发,其用户行为模型是识别->选择。用户不再需要记忆命令,只需点击鼠标即可探索软件。此时,大多数软件都无人阅读用户手册,交互门槛降低。但对于我们这些从未接触过电脑的父母来说,还是有距离感和学习门槛的。

GUI其实就是采用了一套标准的图形界面语言(按钮、列表、文本框等),所有的应用需求都转化成这套界面语言,信息内容也要以界面语言的形式来表达。

3.NUI界面

iPad的出现,大大降低了机器交互的门槛,几乎所有人,包括老人、小孩,都会使用。因为交互语言发生了变化,不再以标准化控件来设计。这时候内容>形式,形式要基于信息内容的使用场景。满足人们对内容呈现和交互的自然期待。这样界面引擎就无法仅通过提供标准控件来满足要求。

现有的移动应用界面(例如微信)并不严格地被视为 NUI 界面。要了解真正的 NUI 界面,您应该观看此视频

/秒/

这是微软在2007年的一个概念视频,我看完这个视频之后非常震撼,之后就萌生了开发一个NUI引擎的想法,让视频中的交互成为现实(移动平台上大部分效果现在都能实现,但是性能就没有那么炫酷了)

虽然NUI引擎提供了一套标准的控件,但更重要的是满足两个要求:

1.简单易用的动态机制,用户无需考虑定时器、多线程、异步处理等,可以实现界面元素各种属性动画

2.便捷的控件扩展机制,可以更方便地定义一个新的控件,让用户可以专注于定义控件行为,而不必担心控件的消息处理和绘制处理。旧的HMI引擎每生成一个新的控件都要重新加载Draw和两个方法。新的NUI引擎采用了类似库层的封装,并引入了信号槽机制,这样就可以像搭积木一样搭建控件,而不必重写这两个方法。

现在的NUI引擎基本都实现了这两个目标,开发门槛低,开发效率和实现效果不逊于目前最强大的两大界面引擎。不过我们还是轻量级引擎,不敢说超越了他们,功能综合性肯定不如这些顶级开发者做的顶级产品。但我是跨平台的,苹果产品再强大,也只能在苹果系统上使用吧?

以下视频是对 NUI 引擎的简单解释

/秒/

下面的视频演示了这款基于NUI引擎开发的软件在PC、iPad、手机上的运行效果,可以展现NUI的跨平台能力。

/秒/

今年我也曾有过把自己在图形界面开发方面的经验整理成一本书的想法,但是感觉市面上大部分的书都是学习现有的流行界面引擎,如何制作界面引擎,感兴趣的人可能并不多,所以一直没动笔写。

分享