备感Duilib相比较吻合做界面包车型客车要求,  在DuiFarm.cpp文件首引进头文件UIlib.h

My first Duilib program

因为集团项目以来入了MFC的那几个大坑,用MFC做UI做了一段时间,感觉不是很便宜,开发效用有点慢。

  1. Prepare for development

看了c++里面做界面包车型大巴类库,感觉Duilib相比吻合做界面包车型大巴要求,而且许多大商店也在动用Duilib,这就随一下大流,并在此表述对Duilib作者及大面积的开源小编的拥戴。

  打开DuiFarm项目DuiFarm.cpp文件,将除_tWinMain函数之外全体剧情剔除。删除后的DuiFarm.cpp内容如下:

Duilib支持win32程序及MFC程序。

int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{return 0;}

 

  在DuiFarm.cpp文件首引进头文件UIlib.h,并引述namespace,及连锁预编写翻译指令。如下:

步骤如下:

 1 #include "..\\..\\duilib-master\\DuiLib\\UIlib.h"
 2 using namespace DuiLib;
 3 #ifdef _DEBUG
 4     #ifdef _UNICODE
 5         #pragma comment(lib,"..\\..\\duilib-master\\Lib\\Duilib_ud.lib")
 6     #else
 7         #pragma comment(lib,"..\\..\\duilib-master\\Lib\\Duilib_d.lib")
 8     #endif
 9 #else
10     #ifdef _UNICODE
11         #pragma comment(lib,"..\\..\\duilib-master\\Lib\\Duilib_u.lib")
12     #else
13         #pragma comment(lib,"..\\..\\duilib-master\\Lib\\Duilib.lib")
14     #endif
15 #endif
16 int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
17 {
18     //TODO: Input code here...
19 }

 

 

1. 设置Duilib环境

可以去https://github.com/duilib/duilib下载框架,将Duilib框架在UnicodeDebug及Debug下编写翻译生成库文件

上边都以VS二零一零的环境操作。在VC++ 选项->项目与缓解方案-> VC++目录

引入Duilib的

含蓄文件

图片 1

库文件

图片 2

源文件

图片 3

设置系统的环境变量

图片 4

不设置环境变量的话,也能够直接把DuiLib_ud.dll及DuiLib_d.dll复制到应用程序的生成目录。不然会报贫乏相关dll的一无所长。

 

 

一. 添加引用及dll

在stdafx.h文件中参与duilib的头文件及库

 1 #include <ObjBase.h>
 2 #include <UIlib.h>
 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

 

小心:假设将转移的主次得到其余机器上运转,一定要复制DuiLib的连锁Dll到应用程序的根目录。

 

 

  那样,Duilib已经打响集成在项目DuiFarm项目中了。注意我项目标文本结构,引用Duilib.h与Duilib_x.lib文件使用相对路径必须科学(,相对路径以DuiFarm下Debug目录内为参照)。

一. 创制对应的类

 

 

创设一个C++类,让这么些类继承Duilib的CWindowWnd和INotifyUI

如下所示:

图片 5

 

在温馨定义的类的头文件中拉长

1 public:
2 
3 LPCTSTR GetWindowClassName() const;
4 
5 void    Notify(TNotifyUI& msg);
6 
7 LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);

private:

    CPaintManagerUI m_pm;

 

  在编排其他代码以前,供给鲜明多少个知识点。Duilib的多少个放置对象。

GetWindowClassName

 

GetWindowClassName是设置类的类名称

 

源文件能够如下概念:

1 LPCTSTR CDuiLib_Dialog::GetWindowClassName() const
2 {
3     return (LPCTSTR)"CTestDlg"; /*自己可以随意取个名字*/
4 }

 

  1. CWindowWnd:窗口对象父类,负责创制窗口、窗口音讯进度处理、提供窗口子类化与超类化接口。
  2. CPaintManagerUI:负责窗口图形绘制。CPaintManagerUI多个根本作用:绘制控件、管理新闻、事件通报。
  3. CDialogBuilder:控件布局类,首要功效:解析XML,营造控件树,创立控件对象。
  4. INotifyUI:处管事人件和通报。子类重载Notify(TNotify
    &msg)虚函数,完成处监护人件文告作用。
  5. CControlUI:控件管理的父类,为控件提供通用属性。

Notify

 

Notify是Duilib中央控制件的响应函数,比如说有些控件按钮点击之后的拍卖。

源文件能够如下概念:

 1 void CDuiLib_Dialog::Notify(TNotifyUI& msg)
 2 {
 3     if( msg.sType == _T("click") )
 4     {
 5         if( msg.pSender->GetName() == _T("closebtn") )
 6         {
 7             Close();
 8         }
 9     }
10 }

 

 

HandleMessage

 

HandleMessage是Duilib中对信息循环的消息处理函数。

能够在这几个函数中对Duilib进行起初化

源文件能够如下概念:

 1 LRESULT CDuiLib_Dialog::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 2 {
 3     if( uMsg == WM_CREATE )
 4     {
 5         CPaintManagerUI::SetInstance(AfxGetInstanceHandle());//加载XML的时候,需要使用该句柄去定位EXE的路径,才能加载XML的路径
 6         CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("skin"));//定位图片等资源的位置
 7 
 8         m_pm.Init(m_hWnd);
 9         CDialogBuilder builder;
10         CControlUI *pRoot = builder.Create(_T("MainActivity.xml"), (UINT)0, NULL, &m_pm); //加载的XML文件的名称
11         ASSERT(pRoot && "Failed to parse XML");
12         m_pm.AttachDialog(pRoot);
13         m_pm.AddNotifier(this);
14 
15         return 0;
16     }
17     else if( uMsg == WM_DESTROY )
18     {
19         ::PostQuitMessage(0);
20     }
21     LRESULT lRes = 0;
22 
23     if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;
24 
25     return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
26 }

 

 

  2.Starting coding “Hello World”

一. 创办窗体

 

在主窗体中创制这些Duilib,

 

在主窗体的那么些类中加叁个方才扩大的类对象
m_dlgDuilib(对象名自由)

由此下边代码创立

1     if(m_dlgDuilib == NULL)
2     {
3         m_dlgDuilib.Create(this->m_hWnd, NULL, UI_WNDSTYLE_DIALOG & (~( WS_BORDER | WS_CAPTION )) , 0, 0, 0, 800, 600);
4     }
5     m_dlgDuilib.CenterWindow();
6     m_dlgDuilib.ShowWindow(TRUE);

 

能够设置打开的窗体样式为

UI_WNDSTYLE_DIALOG & (~(WS_CAPTION | WS_BORDER))

 

 

  在DuiFarm.cpp中新建类DuiFarm,继承自CWindowWnd与INotifyUI,重写CWindowWnd的虚函数GetWindowClassName、HandleMessage与INotify的虚函数Notify。代码如下:

一. 统一筹划布局及体制

 

Duilib的窗体布局是通过xml来反映的,在Duilib中有三个Dui
Designer,能够透过其开始展览统一筹划。关于Duilib的利用能够查看那篇小说:http://www.cnblogs.com/lin1270/p/4106944.html

 

Demo下载地址

class DuiFarm: public CWindowWnd, public INotifyUI
{
protected:
    CPaintManagerUI m_PaintManager;
public:
    virtual LPCTSTR GetWindowClassName() const 
    {/*some code*/}
    virtual void    Notify(TNotifyUI& msg) 
    {/*some code*/}
    virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {/*some code*/}
};

  当中多少个函数的最首要职能:

  1. GetWindowClassName:重临窗口名称。
  2. Notify:事件响应,如点击事件。
  3. HandleMessage:处理音信,例如创造窗口音讯。

  首先补全GetWindowClassName函数的代码,在函数体内,直接回到窗体名字符串。

virtual LPCTSTR GetWindowClassName() const 
{return _T("DuiFramFrame");}

  HandleMessage函数中补全对窗体创立等新闻的拍卖。

 1 virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 2 {
 3     LRESULT lRes = 0;
 4     if( uMsg == WM_CREATE ) 
 5     {
 6         m_PaintManager.Init(m_hWnd);    //init dialog paint
 7         CDialogBuilder builder;        
 8         /* load xml, create widget obj, draw dialog */
 9         CControlUI *pRoot = builder.Create(_T("dui-design.xml"),(UINT)0,NULL,&m_PaintManager);
10         ASSERT(pRoot&&"### XML error!");
11         m_PaintManager.AttachDialog(pRoot);    //widget attach to dialog
12         m_PaintManager.AddNotifier(this);      //add msg notify to window
13         return lRes;
14     }
15     if( m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes)) 
16     {
17         return lRes;
18     }
19     return __super::HandleMessage(uMsg, wParam, lParam);
20 }

  第四行在音讯为窗体创制(WM_CREATE)时,执行:

  1. 初阶化当前窗口绘制(line 陆)
  2. 加载窗口设计xml文件,开头化窗口部件(line 9)
  3. 窗口部件对象附着对话框(line 1①)
  4. 添加消息文告(line 12)

  执行完上述代码,窗体即绘制完结,事件通报已可用。在上述代码中,第八行加载xml文件即为duilib的界面设计xml。犹如html之于浏览器,dui通过解析xml将控件绘制到窗体上。

  xml文件如下:

1 <?xml version="1.0" encoding="utf-8"?>
2 <Window size="100,100">
3   <HorizontalLayout bkcolor="#FFFFFF00">
4     <Button name="btnHello" text="Hello World :-)"/>
5   </HorizontalLayout>
6 </Window>

  将文件保留到品种Debug目录下(因日前项目以Debug格局运营)。那段xml描述了窗体的完全布局:

  • 其次行定义了窗体大小,长度宽度各500像素。
  • 其三行定义了一个横向布局,背景士林蓝(bkcolor为背景象设置)。
  • 第四行定义了三个按钮,名称是btnHello,显示文字为Hello World 🙂

  未来窗体已经定义好,必要添加对按钮事件的拍卖。依据上1篇介绍,按钮事件处理要在重载的Notify函数中编辑。

1 virtual void Notify(TNotifyUI& msg) 
2 {
3     if(msg.sType==_T("click"))
4     {
5         if(msg.pSender->GetName()==_T("btnHello"))
6             ::MessageBox(NULL,_T("Hello World :-)"),_T("Hallo Welt :-D"),NULL);
7     }
8 }
  • 第一行代码表示:“此处要收下类型为‘click’的轩然大波”。
  • 第伍行代码表示:“在有着click事件中,此处仅吸收接纳名字为‘btnHello’这玩意儿的风浪”。
  • 第陆行代码表示:“提醒英德比较的Hello World,以及它们对应的口型”。

  编写到此地,项目早就拥有窗口绘制、窗口布局和事件处理的基本功效,下面必要在入口函数中为之开头化与分配能源:

 1 int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
 2 {
 3     CPaintManagerUI::SetInstance(hInstance);
 4     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());
 5     DuiFarm duiFarm;
 6     duiFarm.Create(NULL, _T("Dui Farm"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
 7     duiFarm.CenterWindow();
 8     duiFarm.ShowModal();
 9     return 0;
10 }
  • 第3行~第6行,入口函数对实例和财富拓展分红,第6行实参为当前项目路线。
  • 第5行:创制窗口。
  • 第七行:设置窗口在显示屏居中。
  • 第十行:展现窗口。

  在调节和测试运维前,必要肯定DuiLib[x].dll是或不是位于DuiFarm项指标Debug目录下(x为_d,_ud或不存在,依照项目编码以及是还是不是为Debug模式而定)。

  运转作效果果如下:

  图片 6

图2.2.一 呈现窗体

  如图,窗体突显橄榄棕,而按钮实际上占据了任何窗体。点击按钮如下:

图片 7

图2.二.二 点击按钮(按钮占据了方方面面窗体)

   通过以上代码,作者完毕了四个最简单易行的Duilib窗体界面——四个窗体,1个铺满了整整窗口区域的艳情按钮(由xml定义可见,窗体呈现“HelloWorld
:-)”的有的是Windows按钮)。

  Duilib叁有的区划业务与体现:XML、(XML-)UI引擎、Win3贰,并且Duilib能够退出守旧Windows界面限制,开发出别具壹格的UI界面风格。大家透过重写HandleMessage函数来完成简单的无边界窗口:

 1 virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 2 {
 3     LRESULT lRes = 0;
 4     if( uMsg == WM_CREATE ) 
 5     {
 6         m_PaintManager.Init(m_hWnd);    //init dialog paint
 7         CDialogBuilder builder;        
 8         /* load xml, create widget obj, draw dialog */
 9         CControlUI *pRoot = builder.Create(_T("dui-design.xml"),(UINT)0,NULL,&m_PaintManager);
10         ASSERT(pRoot&&"### XML error!");
11         m_PaintManager.AttachDialog(pRoot);    //widget attach to dialog
12         m_PaintManager.AddNotifier(this)    ;//add msg to window
13         return lRes;
14     }
15     /* blocked message: WM_NCACTIVATE,WM_NCCALCSIZE,WM_NCPAINT*/
16     else if(uMsg == WM_NCACTIVATE)
17     {
18         if(!::IsIconic(m_hWnd))
19             return (wParam == 0)?TRUE:FALSE;
20     }
21     else if(uMsg == WM_NCCALCSIZE || uMsg == WM_NCPAINT)
22     {
23         return 0;
24     }
25     if( m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes)) 
26     {
27         return lRes;
28     }
29     return __super::HandleMessage(uMsg, wParam, lParam);
30 }

 

  通过上面代码第25行~28行,屏蔽WM_NCACTIVATE,WM_NCCALCSIZE,WM_NCPAINT三个新闻,完结无疆界窗体设计。呈现和点击效果如图:

图片 8

 

   在实质上软件开发进度中,突显与业务分别是软件开发的指点性思想,UI与事务分别使得软件开发工作越来越好的分开张营业务范围。与原来的支付格局相比较,XML定义界面比较C++代码定义界面特别简明方便,后台开发职员能够从界面设计、图片图标呈现等非本标准工作中解放出来,专注于工作逻辑和数码处理;美术工作与UI设计职员注意于界面美化而不要顾及后台包容性难点。Duilib通过xml解析、对象成立、部件附着将复杂的UI设计包装到可安顿的库中,完全依据win3贰阳台使开发人员不必另学一种技术,从而制止了“重新造轮子”给程序员带来极度的就学开支耗费。