DirectUI界面编程(四)界面布局详解

8 篇文章 0 订阅
8 篇文章 2 订阅

Duilib的界面布局使用xml文件进行描述,在Duilib v1.1版本的xml布局文件中我们可以使用以下这些标签(后续版本标签有扩充):

这里写图片描述
这些标签总的来讲可以分为三类:

  1. 窗口类,该类别中只有一个Window标签,它表示一个Window窗口,是每个xml布局文件的根节点,也是必不可少的元素。
  2. 容器类,和该类别相关的标签有ChildLayout、Container、VerticalLayout、HorizontalLayout、TileLayout、TabLayout。该类标签主要用于控制按钮、编辑框等这些控件在窗口中如何摆放。例如VerticalLayout容器下的控件默认情况下都会按照先后顺序竖直摆放,而HorizontalLayout容器下的控件则水平摆放,需要注意的是容易中可以嵌套其他容器。
  3. 控件类,剩下的标签都属于控件类,例如Button标签表示窗口中的一个按钮、Edit标签用来表示编辑框等等。

一个最简单的xml布局文件需要哪些元素呢?实际上只需要一个Window标签和一个容器类标签就够了,容器类标签可以是ChildLayout、Container、VerticalLayout、HorizontalLayout、TileLayout、TabLayout中的任意一种,例如下面一个最简单的布局文件:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="432,320"> 
    <TabLayout name="MainLayout">

    </TabLayout>
</Window>

界面运行效果:
这里写图片描述
可以看到一个黑乎乎的窗口,客户区中什么都没有。

下面笔者向大家介绍一下HorizontalLayout和VerticalLayout容器在布局中的使用,使用这两种容器基本能完成大部分软件的界面效果。
1.HorizontalLayout,HorizontalLayout容器下的所有元素都会按照先后顺序水平排列,例如我们可以向该容器中添加几个按钮:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="432,320"> 
    <HorizontalLayout name="MainLayout">
        <Button text="Btn01" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
        <Button text="Btn02" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
        <Button text="Btn03" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
        <Button text="Btn04" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
    </HorizontalLayout>
</Window>

这里写图片描述

2.VerticalLayout容器则和HorizontalLayout相反,在VerticalLayout容器中的窗口元素都会按照顺序竖直排列,把上面布局内容进行修改:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="432,320"> 
    <VerticalLayout name="MainLayout">
        <Button text="Btn01" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
        <Button text="Btn02" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
        <Button text="Btn03" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
        <Button text="Btn04" width="100" height="30" bkcolor="#FFFF0000" borderround="2,2"/>
    </VerticalLayout>
</Window>

这里写图片描述

3.容器中可以再嵌套容器,我们可以在一个容器中嵌套任何其他容器,例如一个VerticalLayout中可以嵌套多个HorizontalLayout或VerticalLayout等等。
有了这些特性我们就可以完成大部分软件界面的布局,下面我们来完成一个简单的案例,效果如下:

这里写图片描述

这个界面很简单,我们先来分析一下它的布局:
这里写图片描述

上图很直观的反应了整个界面的布局情况,我们只需要在3.HorizontalLayout中添加一个Text控件,在4.HorizontalLayout中添加两个按钮控件并指定按钮的背景图片即可。

xml布局内容如下:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="432,320" sizebox="4,4,6,6" caption="0,0,0,30">
    <Font name="宋体" size="12"  />
    <Font name="宋体" size="26"  />
    <VerticalLayout name="MainLayout"  bkimage="bg.png">
         <HorizontalLayout height="30"> 
            <HorizontalLayout>
                <Text text="QQ旋风"  padding="30,12,0,0" textcolor="#FFFF0000" height="30" align="center"   font="0"  ></Text>
            </HorizontalLayout>
            <HorizontalLayout width="80"  >
                 <Button name="MinBtn" width="28" height="17" padding="0,2,0,0" normalimage="file='max_min.png' source='0,0,28,17' dest='0,0,28,17' "  hotimage="file='max_min_h.png' source='0,0,28,17' dest='0,0,28,17" ></Button>
                 <Button name="CloseBtn" width="28" height="17" padding="0,2,0,0" normalimage="file='max_min.png' source='28,0,56,17' dest='0,0,28,17' "  hotimage="file='max_min_h.png' source='28,0,56,17' dest='0,0,28,17'" ></Button>
            </HorizontalLayout>
         </HorizontalLayout>
         <HorizontalLayout >
         </HorizontalLayout>
    </VerticalLayout>
</Window>

除此之外我们需要去掉系统原有的标题栏,对WM_NCPAINT、WM_NCCALCSIZE、WM_NCACTIVATE三个系统消息进行屏蔽即可,在消息处理switch case语句中,增加下面代码

case WM_NCPAINT:
case WM_NCCALCSIZE:
case WM_NCACTIVATE:
return 0; 

加载界面代码和上节基本相同,完整内容如下:

#include <Windows.h>
#include "../DuiLib/StdAfx.h" 
using namespace DuiLib;

class CMyWnd : public CWindowWnd,public INotifyUI
{
public:
    CMyWnd(){}
    LPCTSTR GetWindowClassName() const
    {
        return L"MyWnd";
    }
    UINT GetClassStyle() const{
        return UI_CLASSSTYLE_FRAME|CS_DBLCLKS;
    }
    void Notify(TNotifyUI& msg)
    {
        if(msg.sType == L"click")
        {
            if(msg.pSender->GetName() == L"CloseBtn")
            {
                ::PostQuitMessage(0);

            }else if(msg.pSender->GetName() == L"MinBtn")
            {
                ::SendMessage(m_hWnd,WM_SYSCOMMAND, SC_MINIMIZE, 0);
            }
        }
    }
    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    { 
        switch(uMsg)
        {
        case WM_CREATE:
            {
                m_PaintMgr.Init(m_hWnd); 
                //从xml中加载界面
                CDialogBuilder builder;
                m_pRoot = builder.Create(L"tutorial4.xml",(UINT)0,NULL,&m_PaintMgr); 
                m_PaintMgr.AttachDialog(m_pRoot); 
                m_PaintMgr.AddNotifier(this);
            }
            break; 
        case WM_NCPAINT:
        case WM_NCCALCSIZE:
        case WM_NCACTIVATE:
            return 0; 
            break;
        case WM_DESTROY:
            ::PostQuitMessage(0);
            break; 
        case WM_KEYDOWN:
            {
                int nVirtKey = (int) wParam;
                if(VK_ESCAPE == nVirtKey)
                {
                    ::PostQuitMessage(0);
                }
            }
            break; 
        } 
        LRESULT lRes=0;
        if(m_PaintMgr.MessageHandler(uMsg,wParam,lParam,lRes)) return lRes;
        return CWindowWnd::HandleMessage(uMsg,wParam,lParam);
    } 
    ~CMyWnd(){
        delete m_pRoot;
    }
private:
    CPaintManagerUI m_PaintMgr; 
    CControlUI* m_pRoot;
};
INT WinMain(HINSTANCE hInst,HINSTANCE hPreInst,LPSTR lpCmdLine,INT Show)
{
    CPaintManagerUI::SetInstance(hInst);
    CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetResourcePath());
    //创建主窗口
    CMyWnd* pFrame = new CMyWnd();
    pFrame->Create(NULL,L"Tutorial4",UI_WNDSTYLE_FRAME,WS_EX_WINDOWEDGE);
    pFrame->CenterWindow(); 
    pFrame->ShowWindow(true);
    CPaintManagerUI::MessageLoop();

    return 0;
}

其他容器和控件的使用将在后面的博文中介绍。
博文源码:https://github.com/rongbo-j/duilib-tutorial

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[4.1.18.xxx] [!] 修复win10菜单黑底BUG [!] 修复编辑框圆角BUG [!] Ex_ObjFind 查找BUG [!] Ex_ObjGetObj GW_HWNDLAST/GW_HWNDFIRST BUG [+] 新增了控件属性相关接口 Ex_ObjInitPropList/Ex_ObjSetProp/Ex_ObjGetProp/Ex_ObjRemoveProp/Ex_ObjEnumProps [+] 新增了线性布局属性:#ELP_LINEAR_DALIGN 表示布局方向的对齐方式 [+] 新增了绝对布局接口 _layout_absolute_setedge、_layout_absolute_lock [!] _layout_settableinfo 更名为 _layout_table_setinfo [!] _layout_eableupdate 更名为 _layout_enableupdate [!] Ex_LayoutXXX 更名为 Ex_ObjLayoutXXX [!] 删除 Ex_DUIXXX(背景相关函数) 由 Ex_ObjXXX(背景相关函数) 代替 [!] 信息框常量 EMF_ 修改为 EMBF_ [!] Ex_TrackPopupMenu() 新增菜单标记参数和常量 EMNF_ [+] 增加全局常量 EXGF_MENU_ALL (渲染全部菜单) [!] Ex_ObjSetRgn 修改为 Ex_ObjSetPath [+] Ex_ObjSetRadius [+] 增加路径相关函数 _path_xxx() [!] Ex_scaleX/Y 统一为 Ex_Scale() [+] Ex_ObjScrollShow/Ex_ObjScrollEnable [+] EOS_DISABLENOSCROLL (滚动条不可用时禁止而不隐藏) [4.1.18.313] [+] 增加缓动机制,详见demo [!] 修改了Ex_ObjCallProc的参数,新增最后一个参数 [+] 新增“脚本分发信息_Ex”结构,方便控件处理自定义JS函数 [+] demo中增加了布局和程序交互的例子 [!] 修复2处内存泄漏BUG [!] 修复1处导致退出崩溃BUG [!] 修复1处导致退出CPU占用BUG [4.1.18.309] [+] 主窗口背景模糊支持 (EWS_BLUR/Ex_DUISetBlur) [!] 主窗口图标显示修复 [!] 主窗口移动CPU占用修复 [+] 组件事件冒泡支持 (Ex_ObjEnableEventBubble) [+] 组件坐标转换 (Ex_ObjPointTransform) [+] Ex_ObjSetPadding/Ex_ObjSetFont/Ex_ObjGetFont [!] 修复了通知机制的BUG [!] 修复了ExFC中关于矩形传参的BUG [4.1.18.306] [+] xml style/script/include 引用支持 [+] 模版列表支持 [!] 子窗口 继承父窗口背景信息 完善 [!] 滚动条 相关BUG [!] 修复了ExFC中控件移动的参数错误 [!] 修复了demo中重复打开窗口导致的崩溃 [+] 增加控件扩展demo(滑块条) [4.1] 综合: [+] 布局支持(xml/css) [+] 脚本支持(js) [+] 主题包(窗口/组件/菜单) [+] 多语言支持(i18n) [+] dpi 支持 [+] apng动画支持 窗口: [+] 普通/分层/异型 窗口支持 [+] d2d/gdi(+) 渲染支持 组件: [+] 异型 组件支持 [+] 组件层 模糊支持 其它: [+] 信息框/菜单 改造 [+] 界面/逻辑 分离 ========================================== Ex_DirectUI 4.1 本引擎贡献名单: 1.泆寒(YHan): 整体/基础 框架构建 2.暗の魔法使(Eternal): 整体/基础/功能 调整/完善/扩展 3.你的名字? (主题分享/组件扩展/功能扩展/教程文档) ========================================== 欢淫入裙交流: (群文件有扩展例子和其它相关资源共享) 综合交流群: ① 433859 ② 155525070 扩展开发交流群: ②129705651 官方网站: http://www.exdui.com (暂未上线)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值