您的位置:首页 > 编程语言 > C语言/C++

浅谈图形界面引擎开发 - 如何用 C++ 从零编写 GUI

2017-03-24 10:43 573 查看
本人在知乎上关于 如何用 C++ 从零编写 GUI? 问题的回答,算是比较粗浅的讲解了GUI引擎的一些开发心得
https://www.zhihu.com/question/24462113/answer/108810406
搬到csdn上保存一下

虽然高票答案回答的比较全面了,作为一个自主开发界面引擎多年的老司机,还是补充一下内容,同时show一下自己做得引擎和大家交流一下

本人前后做过三代HMI图形界面引擎, 从传统基于控件组织的GUI界面引擎,到现在移动平台使用的主流的支持各种动态效果的NUI(natural user interface)界面引擎。先上一个使用我的NUI界面引擎开发的产品例子视频,这是一个图形化的轻量级项目管理工具
Youku Universal Player

如下地址可以下载到这个软件的windows版本
NPlan项目管理软件 ,免费

我的图形引擎是C++语言开发,跨平台的,支持windows Linux android Mac IOS等主流系统

也就是基于本引擎开发的界面,不仅能在windows上运行,也可直接移植到其他平台,而应用层UI代码不变。

同时对于各种动态界面效果实现(要知道用Windows MFC来实现iphone创建的滑来滑去的界面,对于程序员是巨大的噩梦),也毫无压力,使用接口也很简单,不会比cocoa android java framework更复杂

知友可能有疑问:
1. 那同HTML5一样吗?

不一样,HTML5是解释型语言,写完源码各个平台就可以用,依赖各平台浏览器解释,我们用的是C++,不同平台需要重新编译。
2. android的UI是用Java写的,IOS是objectC,你这C++引擎能支持这两个平台? 吹牛吧

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

android底层还是linux,C++代码可以在JNI下层运行,只需Java层进行一个封装即可

也就是说,你可以在windows平台把界面开发好,然后到其他平台编译运行,运行效果可以做到一致
3. 为什么要自己做引擎,现有的引擎不都很酷很好吗?

首先,同我们的业务有关,我们做车载设备软件,早期要面对各种各样的平台,wince,各种定制化嵌入式linux,qnx,不可能针对每个系统做一套UI,还有像

wince这种基本就没有带什么好图形引擎的系统,你说MFC?在那时的嵌入式设备其运行速度完全不能忍(CPU 200Hz)

唯一靠谱一点的跨平台图形界面引擎就是QT,嗯,这个商用的话,要钱,也不便宜

所以我开始自己写引擎,还真的从轮子和火重新搭建

再来谈谈题主的问题,如何用轮子和火搭建图形界面?
轮子和火

首先,我们看看轮子和火是什么。所谓图形界面,就是解决两个问题,“输入”和“输出”

“输入”就是用户通过键盘,鼠标,触摸屏 定制设备按钮等各种硬件装置进行的输入操作,通过这些设备的驱动,最后被操作系统转化为各种事件消息,图形界面要响应并管理好这些消息;

“输出”就是显示,让用户看到的内容,图形界面最终要在屏幕上显示出来,需要操作系统提供这个接口,本质还是显示芯片的驱动提供这个功能。不考虑效率的话,给个画点的函数就够了。但画点肯定太慢,所以一般会是一个拷屏的上屏操作,用缓冲防止闪烁;

“获取输入消息”,“输出上屏”,这两点就是图形界面的“轮子”和“火”。两个方式都依赖操作系统提供的接口,而且不同操作系统的接口也不定相同,甚至同一操作系统也有不同的方法实现。对于跨平台图形界面引擎,这两部分的基本代码是不跨平台的,针对不同平台会有不同实现,但是这两部分代码不会很多,封装的好也不影响上层开发。

轮子和火都具备了,那么怎么着手搭建一个图形界面引擎呢。

图形引擎和基本库

首先要说明的是,虽然经常说图形界面引擎,但界面引擎和图形引擎,这是两个不同的东西,就如同MFC和GDI,android UI库和skia的关系,图形引擎任务是提供基本的绘制方法,如何画位图,缩放位图,如何画线条 多边形等矢量图形,还有很重要的,如何绘制文字,这些依赖一些基本库,除非你想自己解析jpg png等图片格式,自己读取字体对文字进行矢量渲染。好在大部分这些库都是开源并且商业友好的(免费)

还有一些支持库,比如多线程,文件IO,数学算法。因此,一个图形界面引擎,有以下基本组成部分



对于图形界面引擎,不在本文讨论范围内,可以使用第三方的开源图形库,你要有能力也可以自己写。我的前两代界面引擎使用的图形引擎,都是自己开发的。到了做第三代NUI引擎的时候,已有很多开源的优秀图形引擎,也能跨平台,所以使用的是第三方的图形引擎,毕竟专业人做专业事,我们自己做的虽然也不差,但是一是要耗费精力,二是架构及功能完整性上专业图形引擎还是更好。

界面引擎虽然依赖图形引擎,但是通过好的架构设计,是可以做到弱依赖的,强依赖是使用一个图形引擎就不能换了,弱依赖是如果用的不爽还可以换个,一般2D图形引擎都是软绘制(不使用GPU加速或是使用效果也有限),针对特定平台还可以切换到openGL这样的3D引擎
界面引擎

图形引擎确定了,接下来就是真正的主角,界面引擎了。首先定义一下界面引擎是什么,他不是软件产品的最终形态,而是给图形应用软件开发的中间件,优秀的界面引擎要满足

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

2. 能够简便的实现界面效果和功能

3. 能够高效简便的实现界面效果和功能

这是原始的愿景需求,要做到这点,要仔细设计输入和输出架构
控件:建立控件(现在更流行叫view)机制,组合控件,控件组等分层及机制,简便的初始化接口,各种式样的定义支持。控件的整体管理。
绘制:控件的渲染机制,绘制的压盖顺序
消息机制:OS的原始消息,如何进行有效和高效的分发,用户点击屏幕,界面引擎要确定是哪个控件被点击,要产生怎样的消息
常用控件集合:基本框架稳定了,就要做一些比较常用的基本控件供应用层直接使用,按钮,列表,滑动条,进度条等
特殊控件:一些比较特殊的控件,比如模式对话框,弹出菜单,和常规控件的设计会有差异,他们基本需要全局管理。
编辑工具:是否需要图形界面的编辑工具,对于静态界面,就如windows的对话框,各种按钮,列表框,有一个所见即所得的编辑工具会提高界面开发效率,笔者的第一第二代引擎也提供了界面编辑工具,但是第三代NUI引擎没有做,因为现在的界面,动态的内容太多,界面元素都是可以运动的,单纯的静态界面编辑工具意义已不大。



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

动画支持:对于传统GUI界面,以上完成就可以成为一个界面引擎了,但iphone之后的软件时代,用户已不满足静态的界面交互体验,根据使用场景进行各种动态变化已是图形界面标配,所以还需要建立控件的动画支持。

动画支持要做好需要一些功底,虽然你提供个定时器消息就能让开发人员在应用层去实现一些动画效果,但是调用不方便,交互时的问题也非常多,你试试用MFC或者GTK去实现iphone的界面就知道了。因此,界面引擎提供原生的动画效果也很重要
原始的MFC控件,加个图片按钮都要搞死人,但它是很多做界面的开发者的启蒙老师,我也是从它开始才逐步理解消息循环,上屏机制的,虽然这个过程比较痛苦。后来几年的工作,接触了很多其它的UI引擎,对整个图形界面运作机制也有了更深的了解,机缘巧合也自己折腾了几个界面引擎,不过主要都用在公司内部产品。我也考虑过把它开源,让它更有价值。网站和域名都申请了,但是现阶段还没有精力整理
要能自己开发界面引擎,首先要深入了解现有的一些界面库,不仅仅要会用,还要知道其背后的实现机制及故事,否则只是一个使用者,而不能成为创建者。使用者也不是贬义,能把一个引擎用的炉火纯青也是很牛逼的事情。



笔者接触过的一些图形界面库,不是每个都深入使用,基本架构和原理都了解一些,MFC 深入一些,Motif android QT用的也稍多,cocoa几年前研究过,这几年没怎么弄IOS开发,应该发展的很快吧
NUI引擎

最后说说自己研发的NUI图形引擎



人机界面的发展,主要经过了三个阶段
1. 命令行界面 CLI



命令行的用户行为模式,是 记忆->输入,用户要背下各个命令,单后输入同机器交互,使用门槛高,现在只有专业人士和好莱坞电影里要表现黑客们的牛逼才使用
2. GUI图形界面



苹果推出,windows发扬光大,其用户行为模式,是 识别->选择,用户不用背命令了,拿着软件就可以鼠标乱点进行探索,这个时候大部分软件的用户手册都没人看了,交互门槛降低,但是我们没接触过电脑的父辈还是会觉得有距离感,有学习门槛。

GUI实际上是使用标准的一套图形界面语言(按钮,列表,文本框等),所有的应用需求都转化为这套界面语言呈现,信息内容要依附于界面语言形式表现
3. NUI界面
iphone及ipad的出现,将机器交互门槛大大降低,基本所有人包括老人小孩都能拿着就用。因为其交互语言发生了变化,不再是用标准化控件来设计界面,这时内容>形式,形式要依附信息内容的使用场景。符合人对内容表现和交互的自然预期,这样,界面引擎仅提供标准的控件就无法满足要求。



现有手机app界面,微信等,严格来说还不算NUI界面,真正的NUI界面界面,应该看看这个视频
http://pan.baidu.com/s/1kVdH1Sb

这是微软2007年的概念视频,我也是看到这个视频后,被震撼了,才有了开发一套NUI引擎的想法,来让视频中的交互成为现实(现在移动平台大部分效果已都能做到,只是表现没那么酷)

NUI引擎,虽然会提供一套标准控件,但是更重要的,要满足两个需求
1. 方便使用的动态机制,使用者不用考虑定时器,多线程,异步处理等,能实现界面元素的各种属性动画
2. 方便的控件拓展机制,要更方便的定义一个新的控件,让使用者更专注于定义控件行为,而不用管控件的消息处理,绘制处理这两个层面的事情。之前的老HMI引擎,每次生成一个新控件,都要重载Draw和DoMessage两个方法,新的NUI引擎通过类似android库drawable层的封装,并引入信号槽机制,已可以像搭积木一样搭建控件,而不必再重写这两个方法

现在的NUI引擎基本达到这两个目标。开发门槛低,开发效率和实现的效果也不输与现在最牛的两个界面引擎,cocoa,android framework,不过我们还是一个轻量级引擎,不敢说超越,综合功能肯定也不如这些顶级开发人员做的顶级产品。但是我跨平台呀,苹果东西再牛也只有苹果系统能用不是

如下视频是NUI引擎的一个简单讲解
https://pan.baidu.com/s/1gdzWzIz

如下视频,演示了基于NUI引擎开发的Nplan这个软件,在PC,IPad,android手机上的运行效果,可以看看NUI的跨平台能力
http://pan.baidu.com/s/1kU5l3Pt
今年也冒出将自己对图形界面的一些开发心得整理成书的想法,但是觉得市面上大部分都是学习现有流行界面引擎的书,讲如何做界面引擎,可能感兴趣的人不多,一直没动笔
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息