以金山界面库(openkui)为例思考和分析界面库的设计和实现——问题
随着物质生活的丰富,人们的精神生活也越来越丰富。人们闲暇的时间也相对变多,于是很多人就开始寻找打发时间的方法。其中电视便是其中一种非常重要的消遣方式。假如我们打开电视机,看到了一个电视台正在播一部我们之前没看过的,正在一招一式进行打斗的武侠片;另一个电视台正在播一部之前也没看过的,正在重复太极推手的教学片。我想大部分人会选择那部武侠片。为什么?因为那是一个动作体系,不会让人厌烦。而那个推手教学片,可能非常高端,可能非常有内涵,但是总是让人缺乏点新鲜感。我之前更关注技术的细节,而今天开始,我将开始分析一款开源的软件界面库。这系列文章不再拘泥于一些技术细节,而从一个思路的方向去分析这个库。
我介绍这套界面库是目前开源的金山卫士开源计划中的一部分。具体的访问地址是 http://code.ijinshan.com/。其中代码的下载SVN地址是https://openkui.googlecode.com/svn/trunk。我将分析的是版本号为54的版本。(转载请指明出于breaksoftware的csdn博客)
在分析这个库之前,我们可以闭上眼睛,清空大脑,思考一下:如果自己要设计和编写一个界面库,将如何规划和设计?将会遇到什么技术问题?将如何做出一些选择?
首先,我们要做出一个抉择,我们采用窗口控件方式还是采用直接绘制的方式?我们知道windows系统又可称为“视窗系统”,正如其义,我们可以发现,windows系统就是通过一个个窗口展现给我们的。如果使用过SPY++的同学应该发现,windows系统中大部分窗口下的子控件其实也是一些小窗口,只是他们的父窗口被指向了我们看到的那个最最大的最最外层的那个窗口。
如上图中,各个用粗线框起来的部分,就是一个个窗口。这就是问题中所提到的用窗口控件方式。
还有一种方式就是直接绘制,又称为DirectUI。顾名思义,它就是直接在父窗口中绘制各个部分,而不是通过子窗口的形式将各种窗口组成成一个可以协同工作的窗口。最最常见的一个例子便是IE的最最里层那个窗口,它通过其渲染引擎将网页内容绘制在窗口上。这样做有什么好处呢?我们知道,如果我们用控件方式组织网页的话,每个控件都会保存一个句柄,如果一个稍微复杂点的网页,可能有成千上万个元素,也就意味着有成千上万个句柄。这些子窗口还要依赖消息进行窗口管理和绘制。可以想象,这将导致整个网页展现和管理变得非常复杂和庞大。它的执行效率可能连最最差版本的IE都无法比。
那我们选择DirectUI?不,如果我们选择DirectUI,那我在此写这系列文章就没有意义了。而且客户端界面,一般不会有太过于复杂的渲染问题,所以选择窗口控件方式还是可以接受的。如果对内嵌IE式的DirectUI技术赶兴趣的同学可以看两篇相关的博文《如何定制一款12306抢票浏览器——完结篇》和《内嵌IE网页窗口中消除IE默认脚本设置影响的方法》。我这儿就不再赘述。
现在我们确认了使用窗口控件的方式。那我们再抛出第二个问题:使用什么框架?
使用WTL还是MFC?
我相信做windows开发的同学,对MFC很熟悉。我刚毕业的时候,也是看了遍侯捷的《深入浅出MFC》才开始踏上windows开发之路的。但是,之后一直耳闻MFC的种种弊端,其中人们提到最多的一点就是MFC框架复杂容余,编译出来的文件相对较大。于是WTL就进入我们的视野,我曾记得有人给我推荐WTL时,说WTL是微软内部开发用的,从可靠性上来说是没有问题的。但是WTL相对于MFC则要复杂很多,因为你可以发现到处都是模板泛型技术,如果没有一定的C++功底,使用WTL就像云里雾里,非常难受。综合以上分析,我们似乎可以觉得WTL更可以适合我们的开发,因为我们要设计的是一套界面库,我们要设计自己的框架,所以越基础对我们来说是越合适的。
选择好了WTL后,我们来思考下我们这个界面库如何构成?
如何选择描述文件的格式?
自定义一种格式?个人觉得没有必要,毕竟这不是我们界面库的中心问题,我们应该选择一个稳定的,易于表达的格式。可能你会想到HTML,是的,我觉得可以。但是是否我们还可以再精简一点呢?那就是XML了,而且目前已经有开源的XML解析库。我们这样就可以不拘泥XML的细节,专心于其他业务逻辑。
但是有些东西我们还是要考虑的,就是XML内部的属性定义和组织形式。
我们先讨论下组织形式。为了在一开始表述的清晰,我并不准备以XML来讲解,因为其中我们似乎还要探讨我们自定义的XML属性名等问题。为了简化,同时为了贴近我们日常中能遇到的场景,我将使用大家比较熟悉的HTML作为例子。HTML已经为我们定义好了属性和语法,我们将主要从组织形式来思考,并且可以在已有的HTML技术中吸取其发展中产生的优化点。
我们先看一个例子
<html><head> </head><body> <img id="id1" src="http://xxxx.xxx.xx/xx.xx" height="200" width="200" atl="AAAAAA"/><img id="id2" src="http://yyyy.yyy.yy/yy.yy" height="200" width="200" atl="BBBBBB"/><img id="id3" src="http://xxxx.xxx.xx/xx.xx" height="300" width="400" atl="CCCCCC"/><img id="id4" src="http://yyyy.yyy.yy/yy.yy" height="300" width="400" atl="DDDDDD"/><body>
</html>
上面这段包含四张图片的网页,经过我们观察发现,这段代码是非常容余的,可以精简之。比如我们可以将height="200" width="200" 表示为一个class属性,height="300" width="400" 表示为一个class的属性。这样网页就修改为 <html><head> <style type="text/css">class small{heigth:200;width:200;};class big{height:300;width:400};</style></head><body> <img id="id1" src="http://xxxx.xxx.xx/xx.xx" class="small" atl="AAAAAA"/><img id="id2" src="http://yyyy.yyy.yy/yy.yy" class="small" atl="BBBBBB"/><img id="id3" src="http://xxxx.xxx.xx/xx.xx" class="big" atl="CCCCCC"/><img id="id4" src="http://yyyy.yyy.yy/yy.yy" class="big" atl="DDDDDD"/><body>
</html>
我们还可以发现有些容余,就是src和atl字段。我们有没有办法将这两个东西简化呢?我对HTML不熟悉,我知识范围内不知道该如何解决这个问题。但是记得曾经做MFC时,在资源文件RC中,有个字符串表(string table),其中保存的是多个字符串键值对。这也是种思路,当然HTML可能不支持这种形式。如此,HTML已经不能满足我们的描述了。我们回到XML来。对于以上的情况,我们可以分为3个XML文件,其中一个用于描述字符串,一个用于描述类型,一个用于描述界面。 字符串描述表
<string id=" xx">http://xxxx.xxx.xx/xx.xx<string/>
<string id= "yy">http://yyyy.yyy.yy/yy.yy<string/>
<string id= "A">AAAAAA<string/>
<string id= "B">BBBBBB<string/>
<string id= "C">CCCCCC<string/>
<string id= "D">DDDDDD<string/>
类型描述 <class name="small" height=200 width=200></class>
<class name="big" height=300 width=400></class>
界面描述 <body><img id="id1" src="xx" class="small" atl="A"/><img id="id2" src="yy" class="small" atl="B"/><img id="id3" src="xx" class="big" atl="C"/><img id="id4" src="yy" class="big" atl="D"/>
</body>
这样就清爽很多了。KUI对我之上的设计做了更细的划分,我们将在之后介绍。 如何读取保存界面元素属性?
有了界面描述文件,下一步就是读取这个文件了。我们大致想象一下这个过程,我们可能需要新建一个结构体,用于描述子控件的属性,举个简单的例子,以下是一个子控件A的描述结构体:
struct StControl{int x;int y;int width;int heght;
};
因为子控件B内部可能包含多个其他子控件A。于是这种关系可以使用如下结构体表示
struct StControlEx{StControl stParant;list<StControl> ListChildrenControl;
};
而多个子控件B可能又同时组成了另一个窗口控件C,那么就该表示为 struct StControlExEx{StControl stParant;list<StControlEx> ListChildrenControlEx;
};
那么多个子控件C可能又同时组成另一个窗口控件D,那么就该表示为 struct StControlExExEx{StControl stParant;list<StControlExEx> ListChildrenControlExEx;
};
…… 如此将子子孙孙无穷无尽矣。因为控件有多少层,我们要有多少个控件描述结构体与其对应。很明显这样的设计非常不好。那么我们将如何设计呢?对这个问题,我们将在之后对KUI源码进行分析时,给出它的解决方案。
如何通过界面元素属性设置控件?
一般来说,窗口必然会存在以下的属性:
位置:X,Y,Width,Height或者LeftTopX, LeftTopY,RightBottonX,RightBottonY
那么是否我们可以定义如下的结构体和XML
struct StWindow{int nLeftTopX;int nLeftTopY;int nRightBottomX;int nRightBottomY;
};
<window pos=''10,10,30,40' ></windows>
对应的,现在我们可以设想下我们可以定义一个基础类CBaseWindow class CBaseWindow{public:void SetCommonAttribute(const StWindow& );
}
继承于该类的类都将具有SetCommonAttribute函数以用于设置这些基础属性。 如果只有这些属性,该控件可能就是一个有底色的窗口。但是我们的控件是丰富多彩的,这意味着它们也会有丰富多彩的属性。以按钮为例,我们可能要新增文字内容属性。于是我们要扩展我们的按钮类为
class CButton: public CBaseWindow{public:void SetTextAttribute(const CString& cstrText);}
再假设我们有个特殊的按钮,那个按钮的文字颜色要是可以指定的,于是我们又要扩展个按钮类出来 class CSpecialButton: public Cbutton{public:void SetTextColor(const RGB& );}
再假设…… 可以想象,如果我们这么设计将会导致非常的繁琐。而上层的调用也将非常复杂,比如我们这个CSpecialButton类,它实例化时将执行如下
SetCommonAttribute(stwindow);
SetTextAttribute(cstrText);
SetTextColor(rgb);
这个还算好的,如果还有更多的属性,那这个调用将非常的没有复杂。怎么解决这样的问题呢?我们将分析KUI库,看看它是如何解决这个问题的。 界面描述文件的放置位置
如果以上问题解决了,我们之后将不会出现构架上的问题。因为我们已经拿到了界面描述信息了,下步就是在合适的地方,让子控件接收并设置这些属性即可。
现在我们再抛出一个问题:如果我们将我们界面描述文件作为独立的文件放在用户的电脑上,可能存在被恶意篡改的可能。还有就是,作为独立的文件,如果其中任何一个文件被破坏了(比如下载失败了),将导致整个界面出现异常。可以见得这样做存在比较大的风险。那么如何解决呢?目前市面上很多软件都将界面描述文件作为资源文件保存在PE文件中,这样PE完好,则界面完好;PE受损,可能程序就不能执行了。而且从技术角度说,修改PE文件的难度比修改XML文件门槛要高些。假如你也认为这是一个好方法,那么坏的问题就来了。一款软件的界面可能需要很多界面描述文件以及图片资源,我们总不能让使用我们界面库的同学,在编译工程时将这些资源文件一个一个加入到工程中吧!想想这个也是一个繁琐的问题。程序员最最讨厌重复无聊的工作!那怎么办呢?我们可以让他们将这些资源文件合并成一个文件,一个简单的方法就是将这些文件变成一个压缩包。然后将这个压缩包放到资源文件中。如果你认为这也是个好办法,那么坏的问题又来了。我们如何通过资源文件来使用压缩包中的文件呢?我们可以初步设想下过程:
读取指定资源,将其保存到硬盘(内存)中。
将保存到硬盘(内存)中的压缩包文件解压。
遍历读取解压包中的文件。
那KUI是不是这么做的呢?我们拭目以待。
带着以上这么多选择和问题,我们将在之后的章节中,一一介绍KUI是如何解决问题的,并从中尽量吸取其思想的精髓。
相关文章:
知识图谱,下一代数据中台的核心技术
作者 | 杨威,明略科技技术中心负责人 编辑 | 夕颜 出品 | AI科技大本营(ID:rgznai100) 本文为CSDN即将推出的《新战场:决胜中台》专刊的第 3 篇文章。 【导读】数据中台火的十分突然,似乎年前还在炒概念,年…

StoneAge Dict 技术方案的可行性[1]
上次和项目经理讨论了技术选型的事,现在简单地说一下,等下次开会再系统地讲。1. 平台环境:Java1.52. 用户接口:Web: JSP, JSFSpring2.5xDesktop: JavaFX3. 技术:dictzip(解析StarDict词库), XML因为StarDict是目前很受…

using的几种用途
using 常用来引用命名空间 1 using System; 2 using System.Data; 3 using System.Data.SqlClient; 4 using System.Collections.Generic; 5 using Model; 6 using IDAL; 7 using DBUnititly; using另一个用途是给类和命名空间指定别名 1 using spacename system.io2 3 using…

以金山界面库(openkui)为例思考和分析界面库的设计和实现——资源读取模块分析
按照软件的执行流程,我们首先遇到《以金山界面库(openkui)为例思考和分析界面库的设计和实现——问题》中提出的最后一个问题:界面描述文件的放置位置。我们曾提出一种方案:将界面描述文件打包后放在资源文件中&#x…
开发者如何赶上5G风口?
随着5G正式步入商用,5G 技术引发广泛关注。据信息通信研究院《5G经济社会影响白皮书》预测,2030年,5G将直接带动的总产出、经济增加值、就业机会分别为6.3万亿元、2.9万亿元和800万个。据BOSS直聘 《2019年5G相关人才数据观察》报告指出&…

使用C# 3.0编译器编译 Asp.Net 项目代码
只需要在 web.config 里添加这样的一段设置就OK了:<configuration><system.codedom><compilers><compiler language"c#;cs;csharp"extension".cs"type"Microsoft.CSharp.CSharpCodeProvider,System, Version2.0.0.0, Cultureneu…

java 它 引用(基本类型的包装,构造函数和析构函数c++不同)
一个:java 和c参考控制 他提到引用,我们会想到java它不喜欢c里面的指针。当然java内引用和c里面的引用是不同的。 比如: 比方C中,我对某一个函数的声明。int a(int &b),b即为引用类型,函数内b的改动能够…

使用程序解决一道逻辑推理题
今天看朋友发了一个老问题,一道很有意思的推理题:(转载请指明出于breaksoftware的csdn博客) 小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日是下列10组中的一天: 3月4…

AjaxControlToolKit之DragPanelExtender用法
1、将控件ToolkitScriptManager拖至页面中...2、定义3个Panel,用于实现窗体拖动效果,代码如下:1<body>2<form id"form1"runat"server">3<div>4<cc1:ToolkitScriptManager ID"ToolkitScriptMan…
自带数据线的迷你数显充电宝,旅途必备
还有20多天就过年了有件极其考验情商的事情也来临了就是我们这群90后过年最怕的事情——相亲但是在尴尬的场合手机可是一个缓解气氛的好东西不管是想要选择看电影,还是找附近的游玩只要有手机,就可以从容不迫的应对但是带手机最尴尬的事情莫过于结账的时…

SpringJDBC的简单应用
此处写上应用JdbcTemplate的dao操作数据库的一些代码(含基本的增删改查,注:重点是查询出多条语句的写法): package org.sakaiproject.zhaorui.dao.impl;import java.sql.ResultSet;import java.sql.SQLException;impor…

WMI技术介绍和应用——查询硬件信息
这个月实在太忙了,一直没有时间去继续写WMI的应用例子。 本来是希望将《WMI技术介绍和应用》系列博文写的像WMI百科全书般,但是貌似对这个技术感兴趣的同学并不多,所以我决定对部分知识点点到为止,有需求的同学可以查询MSDN相关类…
微软开源的自动机器学习工具上新了:NNI概览及新功能详解
作者 | 宋驰来源 | 微软研究院AI头条(ID: MSRAsia)2018年9月,微软亚洲研究院发布了第一版 NNI (Neural Network Intelligence) ,目前已在 GitHub 上获得 3.8K 星,成为最热门的自动机器学习(AutoMLÿ…

10624 - Super Number
题目链接 题意:给出n到m的范围,求出一个数在前i位数组成的数字能被i整除。假设存在输出这个数,假设不存在。输出-1. 思路:回溯,每次放第i位,然后推断是否符合题意。这题踩着时间过去的2.6s(看了…

2008找回企业久违的网速
曾几何时,单位上网访访问页面也是忽忽的,等待10秒简直是不可忍受;曾几何时,公司网络下载是嗖嗖的,转眼已是2M开外;曾几何时,办公室上网看视频是杠杠的,那流畅那画面都快赶上电视直播…

发现一个windows7(32bit或64bit)DirectUI的bug
前段时间发现一个windows7的一个bug,不是什么严重的问题,我在此记录下。(转载请指明出于breaksoftware的csdn博客) 重现步骤如下: 0 在文件夹的“更改您的视图”中选择下图中用红色叉叉标记的项 1 新建一个文件夹名为“Cs" 2…
阿里达摩院2020趋势第一弹:感知智能的“天花板”和认知智能的“野望”
作者 | Just出品 | AI科技大本营(ID:rgznai100)“感知智能与认知智能是相辅相成的关系。认知智能需要感知系统来进行信号处理和概念识别,而感知系统也需要认知系统的反馈来决定如何进行更有效的提取和识别。”1月2日,阿里巴巴达摩…

Java 对synchronized的补充Lock锁
Java并发编程:Lock 从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式来实现同步访问,那就是Lock。 也许有朋友会问,既然都可以通过synchronized来实现同步访问了,那么为什么还需要提供Lock࿱…
有奖评选 | 2020年的AI技术公开课,你想听到哪些干货?
CSDN技术公开课有奖评选开始啦~~听过课的小伙伴们,哪位讲师的分享让你获益匪浅?记得给TA投票哦!投票后获取入群方式,参与抽奖,奖品很丰厚哦~~进入付费时代,如今我们看似只要招招手,一切知识随手…
一个分析“文件夹”选择框实现方法的过程
在软件开发中,我们如果存在“导入导出”的场景时,难免会用到“文件夹”选择框。之前一直没有太关注过这个的实现过程。最近在工作中遇到了一些问题,我做了一些研究。在此记录下研究的过程。(转载请指明出于breaksoftware的csdn博客…

Openssl req命令
一、简介 req指令用来创建和处理PKCS#10格式的证书 二、语法 openssl req [-inform PEM|DER] [-outform PEM|DER] [-in filename] [-out filename] [-text] [-pubkey] [-noout] [-verify] [-modulus] [-nodes] [-subject] [-passin arg] [-passout arg] [-key filename] [-key…
使用windbg抓取崩溃文件和分析的过程
在软件编程中,崩溃的场景比较常见的。且说微软技术再牛X,也是会出现崩溃的场景。网上有一段Win98当着比尔盖茨蓝屏的视频非常有意思。 (转载请指明出于breaksoftware的csdn博客)我们身边的很多软件都引入了dump生成和收集机制。但…
TF 2.1.0-rc2发布,2020年停止支持Python 2
作者 | 神经星星来源 | HyperAI超神经(ID:HyperAI)【导读】2020 年 1 月 1 日,Python 2 停止维护,正式退休。Python 3 全面登场的时刻,TensorFlow 也在悄悄改变。近日 TensorFlow 官方 GitHub 账号中,发布了…

重新认识笔记本锂电池的保养
重新认识笔记本锂电池的保养 对于笔记本电脑来说,电池可以说是一个比较重要的部件,它的效能直接关系到笔记本电脑在缺少电源的环境中的工作能力。而电池在笔记本电脑的众组件中又算是一个不折不扣的消耗品,因此涉及到笔记本电脑电池的保养和合…

nginx转发及后端服务器获取真实client的IP
针对nginx的模块介绍可以查阅wiki:http://wiki.nginx.org/Modules常用模块:HTTP CoreProxyRewriteUpstream 原理:squid,varnish以及nginx等,在做反向代理的时候,因为要代替客户端去访问服务器,所以…

AJAX的组成应用
表示层XHTMLCSS 动态显示和数据 DOM (文档对象模型)数据交互和操作 XML,XSLT 异步数据获取 XMLHttpRequest 绑定和处理数据 JavaScript XMLhttpRequest对象属性:Number readyState 4 表示完成Function onreadystatechange 回调函数string responseText XMLDocument responseXM…
打开,保存文件框的文本溢出排查
工作中遇到的这个问题还是很有意思的。其中嵌套了很多奇葩性的问题。 (转载请指明出于breaksoftware的csdn博客)我们来看下故事的发生过程,QA同学发现我们存在如下的bug 看到如此多的串,可以认为这个是典型的溢出问题。后来我咨询…
2020年,为什么说入坑AI是最好的时机?
2019年可以说是AI全面落地和商用的一年,产业智能化成为各个行业重点关注的发展方向,交通、工业、农业、医疗等主流行业无一例外。随着人工智能技术的进一步发展和落地,深度学习、数据挖掘、自动程序设计等领域也将在更多应用场景中得到实现。…

IIS 伪静态配置(安装ISAPI_Rewrite配置)
第一:首先到官方网站下载ISAPI_Rewrite 我的机子是32位的就下32位免费版的,链接地址如下: http://www.helicontech.com/download/isapi_rewrite/ISAPI_Rewrite3_0064_Lite.msi 可以选择不同版本:http://www.helicontech.com/downl…
Github标星24k,127篇经典论文下载,这份深度学习论文阅读路线图不容错过
作者 | Floodsung翻译 | 黄海广来源 | 机器学习初学者(ID:ai-start-com)【导读】如果你是深度学习领域的新手,那么你可能会遇到的第一个问题是“我应该从哪篇论文开始阅读?”本文就是一篇深度学习论文的阅读路线图!该…