前面那些教程都是为了让小伙伴们从win32、MFC过渡到duilib,让大家觉得duilib不是那么陌生,如果大家现在还对duilib非常陌生的话,那就说明前面的教程做得不好,请大家在下面留言,我会一一查看,并做出改进。    从这个教程开始就是见证奇迹的时刻啦~(^o^)/~

其实duilib主打的界面制作方式是XML + UI引擎 + win32框架,其实和浏览器HTML + CSS + 渲染引擎的方式非常类似,可以将其理解为一个非常mini的浏览器。
    而用duilib写界面时,大部分是在写XML,类似于写HTML,这点可能会让习惯MFC等windows界面的伙伴们有点不习惯,需要克服克服,相信在看完Alberl的教程之后,就会习惯啦~

前面的教程所使用的界面制作方式大家应该不算陌生,那么如果用XML来实现,会是什么样子呢?  
    其实也是很简单的,
    1、把if( uMsg == WM_CREATE ) 里面的代码改成下面这样:

  1. if( uMsg == WM_CREATE )
  2. {
  3. m_PaintManager.Init(m_hWnd);
  4. CDialogBuilder builder;
  5. CControlUI* pRoot = builder.Create(_T("duilib.xml"), (UINT)0, NULL, &m_PaintManager);   // duilib.xml需要放到exe目录下
  6. ASSERT(pRoot && "Failed to parse XML");
  7. m_PaintManager.AttachDialog(pRoot);
  8. m_PaintManager.AddNotifier(this);   // 添加控件等消息响应,这样消息就会传达到duilib的消息循环,我们可以在Notify函数里做消息处理
  9. return lRes;
  10. }

复制代码

2、设置XML的路径:    在CPaintManagerUI::SetInstance(hInstance); 下面调用SetResourcePath函数:

  1. CPaintManagerUI::SetInstance(hInstance);
  2. CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());   // 设置资源的默认路径(此处设置为和exe在同一目录)

复制代码

3、建立XML:    新建一个XML,文件名为“duilib.xml”,保存为UTF-8格式(不要使用windows自带的记事本编辑,可以使用UltraEdit、EditPlus等编辑器),内容如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Window size="800,600"> <!-- 窗口的初始尺寸 -->
  3. <HorizontalLayout bkcolor="#FF00FF00"> <!-- 整个窗口的背景 -->
  4. </HorizontalLayout>
  5. </Window>

复制代码

4、将"duilib.xml"放到exe目录下。  现在即可看到一个绿色的窗口,是不是也很简单呢。
  那么我们继续来添加Hello World按钮吧~O(∩_∩)O~
  上面的XML只是描述了窗口的大小和背景色,但是并没有添加按钮,下面我们添加一个Hello 按钮,只需在XML里面添加一行即可:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <Window size="800,600"> <!-- 窗口的初始尺寸 -->
  3. <HorizontalLayout bkcolor="#FF00FF00"> <!-- 整个窗口的背景 -->
  4. <Button name="btnHello" text="Hello World"/> <!-- 按钮的属性,如名称、文本 -->
  5. </HorizontalLayout>
  6. </Window>

复制代码

 再次运行一下exe,是不是又看到了熟悉的画面,怎么样,写XML很简单吧~O(∩_∩)O~   :

  不过大家可以发现,改成XML后,窗口启动后不居中了,怎么办呢?
在duiFrame.ShowModal上面那行加上duiFrame.CenterWindow();就可以啦
main.cpp的完整代码如下:

  1. #pragma once
  2. #include
  3. using namespace DuiLib;
  4. #ifdef _DEBUG
  5. #   ifdef _UNICODE
  6. #       pragma comment(lib, "DuiLib_ud.lib")
  7. #   else
  8. #       pragma comment(lib, "DuiLib_d.lib")
  9. #   endif
  10. #else
  11. #   ifdef _UNICODE
  12. #       pragma comment(lib, "DuiLib_u.lib")
  13. #   else
  14. #       pragma comment(lib, "DuiLib.lib")
  15. #   endif
  16. #endif
  17. class CDuiFrameWnd : public CWindowWnd, public INotifyUI
  18. {
  19. public:
  20. virtual LPCTSTR GetWindowClassName() const { return _T("DUIMainFrame"); }
  21. virtual void    Notify(TNotifyUI& msg)
  22. {
  23. if(msg.sType == _T("click"))
  24. {
  25. if(msg.pSender->GetName() == _T("btnHello"))
  26. {
  27. ::MessageBox(NULL, _T("我是按钮"), _T("点击了按钮"), NULL);
  28. }
  29. }
  30. }
  31. virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
  32. {
  33. LRESULT lRes = 0;
  34. if( uMsg == WM_CREATE )
  35. {
  36. m_PaintManager.Init(m_hWnd);
  37. CDialogBuilder builder;
  38. CControlUI* pRoot = builder.Create(_T("duilib.xml"), (UINT)0, NULL, &m_PaintManager);   // duilib.xml需要放到exe目录下
  39. ASSERT(pRoot && "Failed to parse XML");
  40. m_PaintManager.AttachDialog(pRoot);
  41. m_PaintManager.AddNotifier(this);   // 添加控件等消息响应,这样消息就会传达到duilib的消息循环,我们可以在Notify函数里做消息处理
  42. return lRes;
  43. }
  44. // 以下3个消息WM_NCACTIVATE、WM_NCCALCSIZE、WM_NCPAINT用于屏蔽系统标题栏
  45. else if( uMsg == WM_NCACTIVATE )
  46. {
  47. if( !::IsIconic(m_hWnd) )
  48. {
  49. return (wParam == 0) ? TRUE : FALSE;
  50. }
  51. }
  52. else if( uMsg == WM_NCCALCSIZE )
  53. {
  54. return 0;
  55. }
  56. else if( uMsg == WM_NCPAINT )
  57. {
  58. return 0;
  59. }
  60. if( m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes) )
  61. {
  62. return lRes;
  63. }
  64. return __super::HandleMessage(uMsg, wParam, lParam);
  65. }
  66. protected:
  67. CPaintManagerUI m_PaintManager;
  68. };
  69. int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
  70. {
  71. CPaintManagerUI::SetInstance(hInstance);
  72. CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());   // 设置资源的默认路径(此处设置为和exe在同一目录)
  73. CDuiFrameWnd duiFrame;
  74. duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
  75. duiFrame.CenterWindow();
  76. duiFrame.ShowModal();
  77. return 0;
  78. }

复制代码

注意:以上已给出完整代码,由于最前面的17行是#include等信息,基本不会变动,所以后面的教程不再列出这些代码。

duilib教程之duilib入门简明教程6.XML配置界面的更多相关文章

  1. duilib教程之duilib入门简明教程17.事件处理和消息响应

    界面的显示方面就都讲完啦,下面来介绍下控件的响应.    前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEGIN_ME ...

  2. duilib教程之duilib入门简明教程3.第一个程序 Hello World

    小伙伴们有点迫不及待了么,来看一看Hello World吧:新建一个空的win32项目,新建一个main.cpp文件,将以下代码复制进去: #include <windows.h> #in ...

  3. duilib教程之duilib入门简明教程14.部分bug 2

    上一个教程中提到了ActiveX的Bug,即如果主窗口直接用变量生成,则关闭窗口时会产生崩溃      如果用new的方式生成,则不会崩溃,所以给出一个临时的快速解决方案,即主窗口都用new生成,_t ...

  4. duilib教程之duilib入门简明教程15.自绘控件

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

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

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

  6. duilib教程之duilib入门简明教程11.部分bug

    一.WindowImplBase的bug    在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题,    1.最大化按钮的样式还是没 ...

  7. duilib教程之duilib入门简明教程1.前言

    关于duilib的介绍就不多讲了,一来不熟,二来小伙伴们想必已经对比了多个界面库,也无需赘述.下面进入正题:    不看广告看疗效! 已有众多知名公司采用duilib做为界面库,如华为网盘.PPS(P ...

  8. duilib教程之duilib入门简明教程7.XML基础类

    现在大家应该对XML描述界面不那么陌生了,那么我们做进一步介绍. 前面的教程我们写了很多代码,为的是让大家了解下基本流程,其实duilib已经对常用的操作做了很好的包装,正式使用时无需像前面的教程那样 ...

  9. duilib教程之duilib入门简明教程9.界面布局

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

随机推荐

  1. 前端自动化构建工具——gulp环境搭建教程

    gulp是前端工程化的工具,它可以对html,css,js等代码和图片进行压缩,也可以对sass和less等预处理语言进行编译,代码部署.gulp学起来简单,用起来方便,大大提高我们工作效率. 这里可 ...

  2. 从身份证号提取生日并更新到生日字段中的SQL语句

    1:根据身份证号 更新 生日字段 SQL update 学生信息 ,)+,)+,) 2:根据身份证号 更新 性别字段 SQL update 学生信息 set 性别='男' and substring( ...

  3. python pathlib模块详解

    python pathlib模块详解    

  4. PHP ftp_rename() 函数

    定义和用法 ftp_rename() 函数重命名 FTP 服务器上的文件或目录. 如果成功,该函数返回 TRUE.如果失败,则返回 FALSE. 语法 ftp_rename(ftp_connectio ...

  5. js实现canvas保存图片为png格式并下载到本地

    canvas 保存图片 下载到本地 function base64Img2Blob(code){ var parts = code.split(';base64,'); var contentType ...

  6. Android中的Serialable和Parcelable的区别

    本文主要介绍Parcelable和Serializable的作用.效率.区别及选择,关于Serializable的介绍见<Java中的序列化Serialable高级详解> 1.作用 Ser ...

  7. hive的行列互转

    行转列 多行转多列 数据表 row2col col1 col2 col3 a c 1 a d 2 a e 3 b c 4 b d 5 b e 6 现在要将其转化为: col1 c d e a 1 2 ...

  8. hibernate 一对多查询 对多的一方进行分页

    //查询用户留言@Overridepublic List<LeaveWords> getLeaveWords(String userName) {Session session = nul ...

  9. 牛客多校第八场 C CDMA 线性代数:沃尔什矩阵

    题意: 构造出一个由1和-1组成的$2^k*2^k$的矩阵,使得矩阵任意两列内积为0 题解: 数学知识,沃尔什矩阵.沃尔什矩阵的特性被CDMA(码分多址)采用,使得编码成为无线信号的频段和振幅之外的第 ...

  10. Comet OJ - 2019 六一欢乐赛

    传送门 #A: 思路:等差数列求和,看成俩次1+2+…+ n,多加的n减去,所以 ans = n*(n+1) - n. AC代码: #include<iostream> #include& ...