原文转自:http://www.cnblogs.com/Alberl/p/3343806.html

    上一个教程实现的标题栏代码中,并没有看到处理自适应窗口大小的代码,但是窗口大小变化后,按钮的位置会跟着变化,这是因为我们将按钮放到了HorizontalLayout、VerticalLayout,这样duilib就会帮我们自动布局按钮的位置和大小,顾名思义,HorizontalLayout就是水平布局,VerticalLayout就是垂直布局。
    最开始的教程里面,窗口大小变化时,Hello World按钮会沾满整个窗口,并且文字始终居中,这就是HorizontalLayout的效果:
        <HorizontalLayout>
<Button name="btnHello" text="Hello World"/>
</HorizontalLayout>

那么HorizontalLayout和VerticalLayout有什么区别呢? 其实这个Alberl也不怎么懂,Alberl都是直接试效果的,HorizontalLayout不行就换VerticalLayout ~O(∩_∩)O  这个还得请各位大神多多赐教,等写完这个入门教程后,Alberl会继续学习duilib,到时候再继续写教程。

    由于官方木有文档,所有的东西都靠自己去看,去Demo里调试,所以这个布局的准确文字定义我也不好说,就直接用实验的方式跟大家讲解啦~
 
    现在开始讲解上一个教程中的界面布局:
    1、首先得到一个渐变的背景窗口,将XML的内容改成下面这样
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
</VerticalLayout>
</Window>

效果如图:

    从duilib的源码里可以看到:
    (1)XML的 <VerticalLayout> 节点对应于duilib里的CVerticalLayoutUI控件
    (2)CVerticalLayoutUI控件继承于CContainerUI,而CContainerUI继承于CControlUI。
    所以其实CVerticalLayoutUI 也是一个控件啦,把它和CButtonUI同等对待,就比较好理解了。
为了进一步表现他们的类似,可以将XML里面的VerticalLayout 换成 Button、Control、Container 试试,你会发现效果是一样的哦~
 
    再次强调下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。
 
    2、加上标题栏,将XML的内容改成下面这样:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
</HorizontalLayout>
</VerticalLayout >
</Window>

效果如图:

其中height="32" 是指这个HorizontalLayout 只占用32个像素高度。
 
    3、将标题栏移到下面,将XML的内容改成下面这样:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<HorizontalLayout /> <!-- 占空位,占据上面所有的空位--> <!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
</HorizontalLayout>
</VerticalLayout >
</Window>

效果如图:

这里只加了一行代码<HorizontalLayout />,就让标题栏移到了下面,这行代码的意思是:占据空白的部分。
由于这行代码放在标题栏HorizontalLayout 的上面,所以标题栏被挤了下去,如果放到下面,是没有效果的。
 
4、将标题栏移到中间,将XML的内容改成下面这样:

<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<HorizontalLayout /> <!-- 占空位,占据上面所有的空位--> <!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
</HorizontalLayout> <HorizontalLayout /> <!-- 占空位,占据下面所有的空位-->
</VerticalLayout >
</Window>

效果如图:

    为什么标题栏就跑到中间了呢? 
    在标题栏的上面和下面都有一个占空位的<HorizontalLayout />,如果没有指定高度,那么他们会默认各占一半高度,相当于有一个默认的属性 height="***"
 
    那么我们给它指定一个高度试试,比如把上面那个<HorizontalLayout /> 改为<HorizontalLayout height="32" />,效果如图:
 
    现在应该明白<HorizontalLayout />占位的作用了吧~\(^o^)/~
    这里有一点要注意的就是:
占位的时候,
<HorizontalLayout /> 一般是指定height属性,也就是说占的位置是从上往下算的。因为水平方向的位置都会占据。

<VerticalLayout/>       一般是指定width属性,也就是说占的位置是从左往右算的。因为垂直方向的位置都会占据。
并且HorizontalLayout 和VerticalLayout一般都是交叉包含,而不是重复包含(比如<HorizontalLayout> 子节点里再包含一个<HorizontalLayout> 节点)。
    当然,上面指的是一般情况,如果对布局很熟悉了,就可以随意包含了。
    这里讲的都是把标题栏水平放置,把标题栏垂直放置相信也难不倒大家了,就请自行试验,以便熟悉这些布局。
 
    5、回到前面第2个步骤,我们来添加客户区布局。
    因为背景色已经是渐变的了,所以就不给客户区加背景了,那么客户区暂且不管。
 
    6、添加最大化、最小化、关闭按钮:
    上一个教程的最后部分已经解释了按钮的外观等属性,这里为了简明,就不加那么多属性了,先加上一个最小化按钮试试效果:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
<Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>
</HorizontalLayout>
</VerticalLayout >
</Window>

效果如图:

可以看到整个最小化按钮都被拉伸了,其中两边的矩形色块是因为图片的边框也被拉伸了。
 
我们再加上最大化按钮和关闭按钮,XML如下:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
<Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>
<Button name="maxbtn" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>
<Button name="closebtn" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>
</HorizontalLayout>
</VerticalLayout >
</Window>

效果如图:

    可以发现三个按钮被均匀拉伸了。
    但是我们显然不想让按钮被拉伸,怎么办呢?
    还记得前面说的占位布局吗?因为我们想让按钮显示到右边,所以我们要占住左边的部分。 那我们加一个占位试试。
不过,
    (1)亲们知道这个占位要加到哪一行么?
        当然是加到按钮的上面! 那我们加到按钮上面试试。
    (2)亲们知道这个占位布局用<HorizontalLayout/>还是<VerticalLayout/>么?
        其实我也不知道,那咱们就试试吧。
        先加个<HorizontalLayout/>玩玩,XML如下:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
<HorizontalLayout />
<Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>
<Button name="maxbtn" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>
<Button name="closebtn" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>
</HorizontalLayout>
</VerticalLayout >
</Window>

效果如图:

    (其实换成VerticalLayout等任何CControlUI,效果都是一样的)
    果然占到了左边的部分,但是为什么还是均分呢,怎么让它只占用左边的一大部分呢?
    这就是width的用处了, 我们给HorizontalLayout 加上一个属性 width = "600",可以看到如下效果:
    好家伙,果然有用!
    下一步我们再把width加大一点,应该就可以让按钮正常了吧?
    先别急着管大小,我们先拖动一下窗口大小,或者点击最大化按钮~
    是不是有新问题啦? 为什么按钮还是被放大了呢?
    因为我们给HorizontalLayout加上了width属性,那么在水平方向,它就失去自适应效果啦,因为宽度永远是前面指定的600.
    那怎么样才能让按钮不被放大呢?
    很显然,不应该给左边的占位布局HorizontalLayout 指定width属性,而应该给右边的按钮指定width属性。
    但是按钮有 width属性吗?
    按钮是有,但是我们应该添加一个占位布局 HorizontalLayout  来指定width属性。 XML如下:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
<HorizontalLayout />
<HorizontalLayout width = "77">
<Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>
<Button name="maxbtn" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>
<Button name="closebtn" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>
</HorizontalLayout>
</HorizontalLayout>
</VerticalLayout >
</Window>

效果如图:

    现在窗口大小怎么变,按钮都不会被拉伸啦,恭喜小伙伴们~
    可以看到那3个Button节点都被放到了HorizontalLayout 节点下,下面是时候讲一下布局了:
    其实duilib整个界面都是由各种布局组成,我们把上面的XML简化一下,就是下面这样子:
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout >
<HorizontalLayout height="32" >
<HorizontalLayout />
<HorizontalLayout width = "77" />
</HorizontalLayout>
</VerticalLayout >
</Window>

很明显,最外层是整个窗口的布局<VerticalLayout>,之后又包含了一个 <HorizontalLayout height="32" >布局(即标题栏),

再里面又包含了两个HorizontalLayout布局,所以一切框架和位置都是由布局决定。
    这里先简要介绍一下duilib的UI设计器:
    1、在duilib源码的bin目录下,【DuiDesigner.exe】就是UI设计器啦。
    2、把XML拖拽上去即可直接看到界面效果,
    我们把前面那个完整的XML拖进去,即可看到如下效果:
    红色边框围起来的就是一个个HorizontalLayout 等布局啦~
 
    7、调整按钮的位置和大小。
    虽然已经将按钮显示到最后边,但是按钮沾满了右边部分,我们现在把他们的高度调小一点:
    给Button节点都加上属性 height ="20",效果如图:
    嗯,效果看起来还行。
 
    再加上width="23"属性,效果如图:
    那怎么样让按钮不挨着顶部呢?
    前面介绍过float属性,是用于绝对定位,由于现在按钮的位置都是由布局自动调整的,所以没办法调节位置,如果不想让布局自动调整位置,就要加上float="true",这样就可以自己指定位置啦。我们给最小化按钮加上 float="true" pos="0,5,22,24" 试试,效果如图:
 
    额,最小化按钮哪里去了~~~
    虽然最小化按钮使用了绝对定位,但是其他两个按钮还是自动布局,所以需要给他们也加上,XML如下:
            <HorizontalLayout width = "77">
<Button name="minbtn" height ="20" width="23" float="true" pos="0,5,22,24" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>
<Button name="maxbtn" height ="20" width="23" float="true" pos="22,5,44,24" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>
<Button name="closebtn" height ="20" width="23" float="true" pos="44,5,74,24" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>
</HorizontalLayout>

效果如图:

 
    对比一下上个教程完整的图片:
    发现我们这个这个图有点不对,三个按钮的中间的线有点粗~
    这是因为图片画的不对(这些图片是Alberl早几年画的,用于MFC,所以并没有考虑duilib),可以把最大化按钮两边的边框都去掉,这样就OK啦~
    不过呢,没必要那么做,我们恰好可以再学习一点新知识~
    我们可以看到,虽然给关闭按钮指定的宽度也是23,但是它却比其他按钮大。  这说明width属性已经失效了,这是因为我们在pos属性里面已经指定了位置大小,它会优先以pos属性为准,那么显然height属性也失效了。(感谢网友【糖加三勺】的提醒,Alberl的这个说法有误,重新试了一下,如果pos属性放在后面,就会以pos为准,height属性放在后面就会以height为准,并不是属性失效。)
    回到刚刚那个按钮图片的问题,由于每个按钮图片都画了边框,所以会有加在一起就有两个边框了,所以中间的线有点粗,那么我们现在可以将最大化、关闭按钮往左边移动一个像素。
效果如图:
    嘿嘿,好了吧~
    但是这个关闭按钮貌似有点宽~
    我们当然可以再次调整pos属性,但是这不科学~~
    还记得失效的那两个属性么?
    那是因为pos属性的后面两个值都填了非0值,所以导致那两个属性失效,下面我们把pos后面的两个值改为0试试。
可以发现那两个属性又生效啦~(感谢网友【糖加三勺】的提醒,Alberl的这个说法有误,重新试了一下,如果pos属性放在后面,就会以pos为准,height属性放在后面就会以height为准,并不是属性失效。)
    现在只要去掉width、height属性中的一个,按钮都会不见了,Alberl以为按钮的大小会调整成图片的大小呢~~~
看来只能指定宽度和高度了(为了方便后期的位置调整,建议pos属性后面两个值填0,使用width/height属性来指定按钮大小)
这几个图片的宽高分别是19 * 23、19*28,所以就手动指定了,XML如下:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">
<VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">
<!-- 标题栏区 -->
<HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">
<HorizontalLayout />
<HorizontalLayout width = "77">
<Button name="minbtn" float="true" pos="0,5,0,0" height="19" width="23" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>
<Button name="maxbtn" float="true" pos="22,5,0,0" height="19" width="23" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>
<Button name="closebtn" float="true" pos="44,5,0,0" height="19" width="28" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>
</HorizontalLayout>
</HorizontalLayout>
</VerticalLayout >
</Window>

效果如图:

    (上面的XML里,Button的父节点HorizontalLayout 换成 VerticalLayout也是一样的效果,所以有时候他们是没有什么分别的,不过个人的理解应该是要交叉使用的)
    好啦,最关键的布局部分讲完啦,另外,在duilib的官方群里,有共享一个布局案例,Alberl已整理出来【duilib入门和xml培训 布局案例.rar】,那里有9个布局案例,相信看完本教程的讲解之后,再看看那9个XML布局,应该就很熟悉布局啦,如果还有不懂的话,请留言~
    注意:一切结果以实际运行效果为准,切勿完全相信本文的言论,因为Alberl搞不好手一抖打错个字母啥的,或者复制上来的代码有误,或者本来理解就有误,很可能会误导大家。如有错误的地方,多谢指正~\(^o^)/~

duilib入门简明教程 -- 界面布局(9) (转)的更多相关文章

  1. 2013 duilib入门简明教程 -- 界面布局(9)

        上一个教程实现的标题栏代码中,并没有看到处理自适应窗口大小的代码,但是窗口大小变化后,按钮的位置会跟着变化,这是因为我们将按钮放到了HorizontalLayout.VerticalLayou ...

  2. duilib入门简明教程 -- 界面布局(9)

        上一个教程实现的标题栏代码中,并没有看到处理自适应窗口大小的代码,但是窗口大小变化后,按钮的位置会跟着变化,这是因为我们将按钮放到了HorizontalLayout.VerticalLayou ...

  3. 2013 duilib入门简明教程 -- 界面设计器 DuiDesigner (10)

        上一个教程讲解了怎么布局最大化.最小化.关闭按钮,但是如果手动去计算这三个按钮的位置和大小的话,非常的不直观,也很不方便.     所以这一章准备介绍duilib的UI设计器,由于这个设计器很 ...

  4. duilib入门简明教程 -- 界面设计器 DuiDesigner (10)

       上一个教程讲解了怎么布局最大化.最小化.关闭按钮,但是如果手动去计算这三个按钮的位置和大小的话,非常的不直观,也很不方便.     所以这一章准备介绍duilib的UI设计器,由于这个设计器很不 ...

  5. duilib入门简明教程 -- 界面设计器 DuiDesigner (10) (转)

    原文转自:http://www.cnblogs.com/Alberl/p/3343838.html     上一个教程讲解了怎么布局最大化.最小化.关闭按钮,但是如果手动去计算这三个按钮的位置和大小的 ...

  6. 2013 duilib入门简明教程 -- 总结 (20)

        duilib的入门系列就到尾声了,再次提醒下,Alberl用的duilib版本是SVN上第个版本,时间是2013.08.15~       这里给出Alberl最后汇总的一个工程,戳我下载,效 ...

  7. DUILIB入门简明教程

      电子书下载: DUILIB入门简明教程.chm 文章作者:  Alberl 电子书制作: 邓学彬 目录: 2013 duilib入门简明教程 -- 前言(1) 2013 duilib入门简明教程 ...

  8. duilib教程之duilib入门简明教程13.复杂控件介绍

    首先将本节要介绍的控件全部拖到界面上,并调整好位置,如图:  然后将Name属性改成其他名字,         不能是[控件名+UI+数字]这种,因为这是DuiDesigner默认的名字,它不会实际写 ...

  9. 2013 duilib入门简明教程 -- 自绘控件 (15)

        在[2013 duilib入门简明教程 -- 复杂控件介绍 (13)]中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如 ...

随机推荐

  1. 第八篇:ORM框架SQLAlchemy 了解知识

    一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取 ...

  2. Laravel 打印已执行的sql语句

    打开app\Providers\AppServiceProvider.PHP,在boot方法中添加如下内容 5.2以下版本 // 先引入DB use DB; // 或者直接使用 \DB:: DB::l ...

  3. 【php】如何配置自主域名腾讯企业邮箱

    腾讯企业邮配置 protocal ssl smtp port 465 host smtp.exmail.qq.com user email account passwd email passwd

  4. oracle 11gR2 for win7旗舰版64安装以及连接plsql和NaviCat(win64_11gR2_database) (2012-12-31-bd 写的日志迁移

    先到oracle官网http://www.oracle.com/technetwork/cn/database/enterprise-edition/downloads/index.html下载必要数 ...

  5. 10.VUE学习之使用lodash库减少watch对后台请求的压力

    问题描述 使用watch监听库里word的值的变化,获取新值后,用oxios发送的ajax异步请求, 此时会多次发送请求,浪费服务器资料. 解决办法 使用lodash库里的_.debounce函数延缓 ...

  6. 数据结构-二叉树(Binary Tree)

    #include <stdio.h> #include <string.h> #include <stdlib.h> #define LIST_INIT_SIZE ...

  7. 科学计算库Numpy——数组生成

    等差数组 使用np.arange()或np.linspace()生成元素是等差数列的数组. 以10为底的数组 使用np.logspace()生成元素是以10为底的数组. 数组扩展 使用np.meshg ...

  8. SQLite3 of python

    SQLite3 of python 一.SQLite3 数据库 SQLite3 可使用 sqlite3 模块与 Python 进行集成,一般 python 2.5 以上版本默认自带了sqlite3模块 ...

  9. [原创]使用python对视频/音频文件进行详细信息采集,并进行去重操作

    [原创]使用python对视频/音频文件进行详细信息采集,并进行去重操作 转载请注明出处 一.关于为什么用pymediainfo以及pymediainfo的安装 使用python对视频/音频文件进行详 ...

  10. A1095 Cars on Campus (30)(30 分)

    A1095 Cars on Campus (30)(30 分) Zhejiang University has 6 campuses and a lot of gates. From each gat ...