duilib实战源码功能汇总.

目录:

基于CWindow

0.Duilib之基于CWindowWnd的窗口.

1.无标题栏窗口拖动.

2.win32窗口源码.

3.自定义控件.<这里说一下,WindowImplBase比CWindow 简单>




基于WindowImplBase

1.MFC中嵌入Duilib窗口.


常用控件使用:

1.Richedit控件



基于CWindow

0.Duilib之基于CWindowWnd的窗口.



实际上是由入门程序进行逐渐封装的,思想在这一块,循序渐进的看入门程序章节哦.


源码:没必要细说,直接贴代码了,看懂就行.

参照duilib入门简明教程,这段实际上是存在误区的,已由源码表明,前言不在赘述.


.cpp文件

#pragma once
#include <UIlib.h>
#include <tchar.h>
using namespace DuiLib;


#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib_d.lib")
#   else
#       pragma comment(lib, "DuiLibA_d.lib")
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib.lib")
#   else
#       pragma comment(lib, "DuiLibA.lib")
#   endif
#endif


class CDuiFrameWnd : public CWindowWnd, public INotifyUI
{
public:
    virtual LPCTSTR GetWindowClassName() const { return _T("DUIMainFrame"); }
//这里进行notify消息响应:比如按钮点击
    virtual void    Notify(TNotifyUI& msg) 
{
if (msg.sType == _T("click"))
{
if (msg.pSender->GetName() == _T("Button"))
{
::MessageBox(NULL, _T("我是按钮"), _T("点击了按钮"), NULL);
}
}
}
    virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        LRESULT lRes = 0;


//响应截获消息的相关操作:开始
//响应WM_CREATE消息
        if( uMsg == WM_CREATE ) 
        {
/*

//它提供的例子这块,这段源码直接注释了吧,实际上没什么用,本就有xml进行布局设置的.
            CControlUI *pWnd = new CButtonUI;
    pWnd->SetName(_T("Button"));
            pWnd->SetText(_T("Hello World"));   // 设置文字
            pWnd->SetBkColor(0xFF00FF00);       // 设置背景色
           m_PaintManager.Init(m_hWnd);
*/

      CDialogBuilder builder;
            CControlUI* pRoot = builder.Create(_T("duilib.xml"), (UINT)0, NULL, &m_PaintManager);   // duilib.xml需要放到exe目录下
            ASSERT(pRoot && "Failed to parse XML");
       m_PaintManager.AttachDialog(pRoot);


//通过FindControl获取button句柄,然后进行SetAttribute进行相关属性的设置.
CControlUI *pButton = m_PaintManager.FindControl("Button");
pButton->SetAttribute("pos", "0,0,100,100");
pButton->SetAttribute("bkcolor", "0xFFFF00FF");


/*响应按钮消息事件
1、调用AddNotifier函数将消息加入duilib的消息循环
2、给按钮设置一个唯一的控件ID(SetName函数)
3、在Notify函数里处理按钮点击消息。
*/
    m_PaintManager.AddNotifier(this);
            return lRes;
}//自行脑补if - else if结构:然后下面三个消息的筛选,duilib其实并没有区分标题栏和客户区,它的实现方法是屏蔽了系统自带的标题栏
else if (WM_NCACTIVATE == uMsg)
{
if (!::IsIconic(m_hWnd))
{
return (wParam == 0) ? TRUE : FALSE;
}
}
else if (WM_NCCALCSIZE == uMsg)
{
return 0;
}
else if (WM_NCPAINT ==  uMsg)
{
return 0;
}


        if( m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes) ) 
        {
            return lRes;
        }
//响应截获消息的相关操作:开始
//没哟处理:调用基类的消息响应函数进行处理.
        return __super::HandleMessage(uMsg, wParam, lParam);
    }
protected:
    CPaintManagerUI m_PaintManager;
};
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
//类静态成员函数
     CPaintManagerUI::SetInstance(hInstance);
     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());   // 设置资源的默认路径(此处设置为和exe在同一目录)
    CDuiFrameWnd duiFrame;
    duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    duiFrame.CenterWindow();
    duiFrame.ShowModal();
    return 0;
}


.xml文件

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


设置按钮属性前样式:



设置按钮样式后:


1.无标题栏窗口拖动.

这里无标题 指的是: Window 标签属性 caption="0,0,0,0"

方法1://这种会对控件的消息照成消息无法响应,除非无控件,不然不推荐

[cpp]  view plain  copy
  1. LRESULT Mydlg::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)  
  2. {  
  3.     if (uMsg == WM_LBUTTONDOWN)  
  4.     {  
  5.         POINT point = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };  
  6.         ReleaseCapture();  
  7.         SendMessage(WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);  
  8.     }  
  9. }  

方法二:<有控件的消息响应,包含标题栏拖动功能>

在使用过程中有特需需求添加移动功能. 具体代码:

这里实现类似标题栏的功能. 只有在 特定高度操作才生效:

[cpp]  view plain  copy
  1. bool m_bStartMove = false;  
  2. POINT m_StartPt;  
  3. LRESULT CTestDialog::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)  
  4. {  
  5.    if (uMsg == WM_MOUSEMOVE) {  
  6.         if (::GetAsyncKeyState(VK_LBUTTON) != 0 && m_bStartMove)  
  7.         {  
  8.             POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  9.             if (!IsDragRect(pt)) return 0;  
  10.             int dx = pt.x - m_StartPt.x;  
  11.             int dy = pt.y - m_StartPt.y;  
  12.             RECT curRect;  
  13.             ::GetWindowRect(m_hWnd, &curRect);  
  14.   
  15.             int cx = curRect.left + dx;  
  16.             int cy = curRect.top + dy;  
  17.   
  18.             int  w = curRect.right - curRect.left;  
  19.             int  h = curRect.bottom - curRect.top;  
  20.   
  21.             SetWindowPos(m_hWnd, NULL, cx, cy, w, h, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);  
  22.         }  
  23.   
  24.     } else if (uMsg == WM_LBUTTONDOWN){  
  25.         POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };  
  26.         m_bStartMove = TRUE;  
  27.         m_StartPt = pt;  
  28.     }else if (uMsg == WM_LBUTTONUP)  
  29.     {  
  30.         m_bStartMove = FALSE;  
  31.     }  
  32.   
  33.     return FALSE;  

[cpp]  view plain  copy
  1. bool CTestDialog::IsDragRect(POINT pt)  
  2. {  
  3.     RECT rcWnd;  
  4.     BOOL ret = ::GetWindowRect(m_hWnd, &rcWnd);  
  5.     int captionHeight = 60; //caption heigth.  
  6.   
  7.     if (pt.y < captionHeight) {  
  8.         return true;  
  9.     }  
  10.     return false;  
  11. }  
原文转载自:http://blog.csdn.net/w839687571/article/details/52294959

2.win32窗口源码.

部分代码引用了1标题栏无窗口拖动,请注意甄别.

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
CPaintManagerUI::SetInstance(hInstance);
CDuiString strResourcePath = CPaintManagerUI::GetInstancePath();//获取EXE目录路劲
strResourcePath += _T("skin/");
CPaintManagerUI::SetResourcePath(strResourcePath);   // 设置资源的默认路径(此处设置为和exe在同一目录)


CMainWind duiFrame;
duiFrame.Create(NULL, _T("WindowTitle"), UI_WNDSTYLE_CONTAINER, WS_EX_WINDOWEDGE);
duiFrame.ShowModal();

return 0;
}


#pragma once
#include "LoginWnd.h"


class CMainWind : public CWindowWnd, public INotifyUI
{
public:
CMainWind();
virtual ~CMainWind();

public:
virtual LPCTSTR GetWindowClassName() const { return _T("CMainWind"); }
virtual void    Notify(TNotifyUI& msg) 
{
if (msg.sType == _T("click"))
{

if (msg.pSender->GetName() == _T("HelloWorld"))
{
::MessageBox(NULL, _T("我是按钮"), _T("点击了按钮"), NULL);
}

}
}


//自己封装的函数
bool IsDragRect(POINT pt)
{
RECT rcWnd;
BOOL ret = ::GetWindowRect(m_hWnd, &rcWnd);
int captionHeight = 30; //标题栏高度为30


if (pt.y < captionHeight) {
return true;
}

return false;
}


virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = 0;

if (uMsg == WM_CREATE)
{
m_PaintManager.Init(m_hWnd);


CDialogBuilder builder;
CControlUI* pRoot = builder.Create(_T("Main.xml"), (UINT)0, NULL, &m_PaintManager);   // duilib.xml需要放到exe目录下
ASSERT(pRoot && "Failed to parse XML");

m_PaintManager.AttachDialog(pRoot);
m_PaintManager.AddNotifier(this);   // 添加控件等消息响应,这样消息就会传达到duilib的消息循环,我们可以在Notify函数里做消息处理

/*
//穿件登陆窗口
CLoginWnd LoginFrame;
LoginFrame.Create(NULL, _T("LoginTitle"), UI_WNDSTYLE_CONTAINER, WS_EX_WINDOWEDGE);
LoginFrame.CenterWindow();
LoginFrame.ShowModal();
*/
/*
CListTextElementUI* pItem = new CListTextElementUI;
CDuiString str1, str2, str3;
str1.Format(_T("%s, "),"loWorld");
*/
/*
CListUI* m_Tem = static_cast<CListUI*>(m_PaintManager.FindControl(_T("list_data"))); //Init进行初始化获取控件指针
CListTextElementUI* pItem = new CListTextElementUI();
pItem->SetFixedHeight(30);
m_Tem->Add(pItem);
pItem->SetText(0, _T("HrlloWorld"));
*/
CListUI* pList = static_cast<CListUI*>(m_PaintManager.FindControl(_T("list_data")));
CLabelUI *NewLable = new CLabelUI;
NewLable->SetText(_T("Hello"));
pList->Add(NewLable);
return lRes;
}else if (uMsg == WM_NCACTIVATE)
{
//修改了窗口样式
if (!::IsIconic(m_hWnd))
{
return (wParam == 0) ? TRUE : FALSE;
}
}else if (uMsg == WM_NCCALCSIZE)
{
return 0;
}else if (uMsg == WM_NCPAINT)
{
return 0;
}
static bool m_bStartMove = false;
static POINT m_StartPt;
if (uMsg == WM_MOUSEMOVE) 
{
if (::GetAsyncKeyState(VK_LBUTTON) != 0 && m_bStartMove)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if (!IsDragRect(pt)) return 0;
int dx = pt.x - m_StartPt.x;
int dy = pt.y - m_StartPt.y;
RECT curRect;
::GetWindowRect(m_hWnd, &curRect);
int cx = curRect.left + dx;
int cy = curRect.top + dy;
int  w = curRect.right - curRect.left;
int  h = curRect.bottom - curRect.top;
SetWindowPos(m_hWnd, NULL, cx, cy, w, h, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
}else if (uMsg == WM_LBUTTONDOWN)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
m_bStartMove = TRUE;
m_StartPt = pt;
}else if (uMsg == WM_LBUTTONUP)
{
m_bStartMove = FALSE;
}
if (m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes))
{
return lRes;
}
return __super::HandleMessage(uMsg, wParam, lParam);
}
protected:
CPaintManagerUI m_PaintManager;
};


3.自定义控件.<这里说一下,WindowImplBase比CWindow 简单>"WindowImplBase直接重写接口,但是CWindow 要继承和知名create"

步骤依次是:创建自定义控件类;添加窗口类的基类IDialogBuilderCallback并重写接口CreateControl;在CDialogBuilder 中Create第三个参数传this;XML中添加该控件.

类.h

#pragma once
const TCHAR kSkinPickerPictureItemClassName[] = _T("SkinPikerPictureItemUI");
const TCHAR kSkinPickerPictureItemInterface[] = _T("SkinPikerPictureItem");


//黑色的前景图的位置
const TCHAR kSkinPickerPictureItemForeImage[] = _T("file='UI\\LeftTab\\listitem\\ListBk.png' fade='150'");


//边框的颜色、图片名称的文字颜色、作者信息的文字颜色
const DWORD kBorderColor = 0xFF64B0FA;
const DWORD kBkNameColor = 0xFFFFFFFF;
const DWORD kAuthorColor = 0xFFAAAAAA;


class CSkinPikerPictureItemUI: public CButtonUI
{
public:
CSkinPikerPictureItemUI();
virtual ~CSkinPikerPictureItemUI();
public:
LPCTSTR GetClass() const;
LPVOID GetInterface(LPCTSTR pstrName);
void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue);
void PaintStatusImage(HDC hDC);
private:
CDuiString m_BkName;
CDuiString m_Author;
};

类.cpp

#include "stdafx.h"
#include "SkinPikerPictureItemUI.h"

CSkinPikerPictureItemUI::CSkinPikerPictureItemUI()
{
m_Author = _T("作者:");
}

CSkinPikerPictureItemUI::~CSkinPikerPictureItemUI()
{
}

LPCTSTR CSkinPikerPictureItemUI::GetClass() const
{
return kSkinPickerPictureItemClassName;
}

LPVOID CSkinPikerPictureItemUI::GetInterface(LPCTSTR pstrName)
{
if( _tcscmp(pstrName, kSkinPickerPictureItemInterface) == 0 ) return static_cast<CSkinPikerPictureItemUI*>(this);
return CButtonUI::GetInterface(pstrName);
}

void CSkinPikerPictureItemUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
if( _tcscmp(pstrName, _T("bkname")) == 0 ) m_BkName = pstrValue;
else if( _tcscmp(pstrName, _T("author")) == 0 ) m_Author += pstrValue;
CButtonUI::SetAttribute(pstrName, pstrValue);
}

void CSkinPikerPictureItemUI::PaintStatusImage(HDC hDC)
{
CButtonUI::PaintStatusImage(hDC);

if( IsFocused() ) m_uButtonState |= UISTATE_FOCUSED;
else m_uButtonState &= ~ UISTATE_FOCUSED;
if( !IsEnabled() ) m_uButtonState |= UISTATE_DISABLED;
else m_uButtonState &= ~ UISTATE_DISABLED;

if( (m_uButtonState & UISTATE_PUSHED) != 0 || (m_uButtonState & UISTATE_HOT) != 0) {

DrawImage(hDC, kSkinPickerPictureItemForeImage) ;
//计算作者信息文字和背景图片名字文字的显示位置,这里是用了硬编码,请使用者自己修改
RECT rcBkName = m_rcItem;
LONG nTextPadding = (m_rcItem.right - m_rcItem.left  - CRenderEngine::GetTextSize(hDC, GetManager(),\
m_BkName.GetData(), m_iFont, m_uTextStyle).cx) / 2;
rcBkName.left += nTextPadding;
rcBkName.right -= nTextPadding;
rcBkName.top += 15;
rcBkName.bottom = rcBkName.top + 20;

RECT rcAuthor = m_rcItem;
nTextPadding = (m_rcItem.right - m_rcItem.left - CRenderEngine::GetTextSize(hDC, GetManager(),\
m_Author.GetData(), m_iFont, m_uTextStyle).cx) / 2;
rcAuthor.left += nTextPadding;
rcAuthor.right -= nTextPadding;
rcAuthor.top += 40;
rcAuthor.bottom = rcAuthor.top + 20;
CRenderEngine::DrawText(hDC, m_pManager, rcBkName, m_BkName, kBkNameColor, m_iFont, m_uTextStyle);
CRenderEngine::DrawText(hDC, m_pManager, rcAuthor, m_Author, kAuthorColor, m_iFont, m_uTextStyle);
CRenderEngine::DrawRect(hDC, m_rcItem, 2, kBorderColor);

}
}

派生:

class CMainWind : public CWindowWnd, public INotifyUI, public IDialogBuilderCallback


在HandleMessage处理Create消息.并:

if (uMsg == WM_CREATE)
{
m_PaintManager.Init(m_hWnd);

CDialogBuilder builder;
CControlUI* pRoot = builder.Create(_T("Main.xml"), (UINT)0,this, &m_PaintManager);   // 

// 这个函数 的第一个参数指定为xml文件的路径;第二个参数一般指定为NULL,我这里不详解了;第三个参数,就是识别自定义控件的关键了,这

//个参数要指定为继承了IDialogBuilderCallback接口的类对象的指针,比如窗体类继承IDialogBuilderCallback,这个参数就填写窗体类对象的指针。只有填写了这个参数,自定义控件才会被识别,经常有人问自己的自定义控件为什么无法被识别。多数情况就是这里没处理好;第四

//个参数指定CPaintManagerUI类对象指针,这个肯定会伴随着窗体类对象一起存在。最后一个参数一般为NULL。 

重写:

CControlUI* CreateControl(LPCTSTR pstrClass)
{
if (_tcsicmp(pstrClass, kSkinPickerPictureItemInterface) == 0)
return new CSkinPikerPictureItemUI();


return NULL;
}

XML中进行描述:

<SkinPikerPictureItem name="" width="118" height="70" bkcolor="#FF7F0000" bkimage="BKImage\1small.png" bkname="测试" author="Redrain" />    

/*备注*/

从Duilib的自带控件上可以看出,比如当前的自定义控件类名为CSkinPickerPictureItemUI,那么GetClass函数返回的字符串SkinPickerPictureItemUI。而GetInterface函数是根据传入的参数,是否与自身的字符串匹配,来决定能否把自己转换为需要的控件类型。GetInterface中用来匹配的字符串,应该与xml中的对应的控件的标签名称一直,这里应该是SkinPickerPictureItem。 

感谢:http://www.bkjia.com/ASPjc/992050.html提供的相关讲解,感谢群duilib的小伙伴.


基于:WindowImplBase

1.MFC中嵌入Duilib窗口.

在MFC中使用duilib
    只需要将前面教程的CDuiFrameWnd的父窗口指定为MFC的窗口就好啦,<理解,实际上,CDuiFrameWnd本身就是一个窗口,了解继承关系剖析WindowImplBase逐步上追>

    建立 基于对话框的MFC应用程序,将CDuiFrameWnd m_duiFrame; 定义为MFC的成员变量,在MFC的初始化函数OnInitDialog里面创建duilib的窗口,代码如下:

CDuiFrameWnd的类申明文件:

#include <UIlib.h>
#include <tchar.h>
using namespace DuiLib;


#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib_d.lib")
#   else
#       pragma comment(lib, "DuiLibA_d.lib")
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib.lib")
#   else
#       pragma comment(lib, "DuiLibA.lib")
#   endif
#endif
class CDuiFrameWnd : public WindowImplBase
{


public:
virtual LPCTSTR    GetWindowClassName() const   { return _T("DUIMainFrame"); }
virtual CDuiString GetSkinFile()                { return _T("duilib.xml"); }
virtual CDuiString GetSkinFolder()              { return _T(""); }

virtual void OnFinalMessage(HWND hwnd) {WindowImplBase::OnFinalMessage(hWnd);delete this;}//进行窗口清理和收尾工作.


};

/*

实际上,不管是基于对话框还是基于单文档的应用程序,都可以讲duilib窗口嵌入进去.理解思想,实际上CDuiFrameWnd本身就是窗口.

*/


    // TODO: 在此添加额外的初始化代码
    CPaintManagerUI::SetInstance(AfxGetInstanceHandle());                    // 指定duilib的实例
    CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());    // 指定duilib资源的路径,这里指定为和exe同目录
    ::CoInitialize(NULL);  //  记得释放::CoUninitialize();
 
    m_duiFrame.Create(*this, _T("DUIWnd"), UI_WNDSTYLE_CHILD, 0, 0, 0, 800, 600); 
    m_duiFrame.ShowWindow(TRUE); 

    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE


常用控件使用:

1.Richedit控件

Richedit如何支持TextChanged

在duilib开发中,小伙伴会因为CEditUI的各种问题,而转为使用CRichEditUI来代替。但是CRichEditUI控件却不支持文字变化通知事件,下面通过简单几行代码让RichEdit支持文字变化事件。

在UIRichEdith.cpp文件中搜索::OnTxNotify,然后使用以下代码替换此函数:

void CRichEditUI::OnTxNotify(DWORD iNotify, void *pv)
{
    switch(iNotify)
    { 
    case EN_CHANGE:
        {
            GetManager()->SendNotify(this, DUI_MSGTYPE_TEXTCHANGED);
            break;
        }
    case EN_DROPFILES:   
    case EN_MSGFILTER:   
    case EN_OLEOPFAILED:   
    case EN_PROTECTED:   
    case EN_SAVECLIPBOARD:   
    case EN_SELCHANGE:   
    case EN_STOPNOUNDO:   
    case EN_LINK:   
    case EN_OBJECTPOSITIONS:   
    case EN_DRAGDROPDONE:   
        {
            if(pv) 
            {   
                LONG nId =  GetWindowLong(this->GetManager()->GetPaintWindow(), GWL_ID);   
                NMHDR  *phdr = (NMHDR *)pv;   
                phdr->hwndFrom = this->GetManager()->GetPaintWindow();   
                phdr->idFrom = nId;   
                phdr->code = iNotify;  

                if(SendMessage(this->GetManager()->GetPaintWindow(), WM_NOTIFY, (WPARAM) nId, (LPARAM) pv))   
                {   
                }   
            }    
        }
        break;
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

好了,需要的小伙伴赶紧试试吧!

duilib开源项目圈QQ群:261675375 
最新代码托管地址:https://github.com/qdtroy/DuiLib_Ultimate

原文转载自:http://blog.csdn.net/duisharp/article/details/45395837


实际上是由入门程序进行逐渐封装的,思想在这一块,循序渐进的看入门程序章节哦.


源码:没必要细说,直接贴代码了,看懂就行.

参照duilib入门简明教程,这段实际上是存在误区的,已由源码表明,前言不在赘述.


.cpp文件

#pragma once
#include <UIlib.h>
#include <tchar.h>
using namespace DuiLib;


#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib_d.lib")
#   else
#       pragma comment(lib, "DuiLibA_d.lib")
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "DuiLib.lib")
#   else
#       pragma comment(lib, "DuiLibA.lib")
#   endif
#endif


class CDuiFrameWnd : public CWindowWnd, public INotifyUI
{
public:
    virtual LPCTSTR GetWindowClassName() const { return _T("DUIMainFrame"); }
//这里进行notify消息响应:比如按钮点击
    virtual void    Notify(TNotifyUI& msg) 
{
if (msg.sType == _T("click"))
{
if (msg.pSender->GetName() == _T("Button"))
{
::MessageBox(NULL, _T("我是按钮"), _T("点击了按钮"), NULL);
}
}
}
    virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        LRESULT lRes = 0;


//响应截获消息的相关操作:开始
//响应WM_CREATE消息
        if( uMsg == WM_CREATE ) 
        {
/*

//它提供的例子这块,这段源码直接注释了吧,实际上没什么用,本就有xml进行布局设置的.
            CControlUI *pWnd = new CButtonUI;
    pWnd->SetName(_T("Button"));
            pWnd->SetText(_T("Hello World"));   // 设置文字
            pWnd->SetBkColor(0xFF00FF00);       // 设置背景色
           m_PaintManager.Init(m_hWnd);
*/

      CDialogBuilder builder;
            CControlUI* pRoot = builder.Create(_T("duilib.xml"), (UINT)0, NULL, &m_PaintManager);   // duilib.xml需要放到exe目录下
            ASSERT(pRoot && "Failed to parse XML");
       m_PaintManager.AttachDialog(pRoot);


//通过FindControl获取button句柄,然后进行SetAttribute进行相关属性的设置.
CControlUI *pButton = m_PaintManager.FindControl("Button");
pButton->SetAttribute("pos", "0,0,100,100");
pButton->SetAttribute("bkcolor", "0xFFFF00FF");


/*响应按钮消息事件
1、调用AddNotifier函数将消息加入duilib的消息循环
2、给按钮设置一个唯一的控件ID(SetName函数)
3、在Notify函数里处理按钮点击消息。
*/
    m_PaintManager.AddNotifier(this);
            return lRes;
}//自行脑补if - else if结构:然后下面三个消息的筛选,duilib其实并没有区分标题栏和客户区,它的实现方法是屏蔽了系统自带的标题栏
else if (WM_NCACTIVATE == uMsg)
{
if (!::IsIconic(m_hWnd))
{
return (wParam == 0) ? TRUE : FALSE;
}
}
else if (WM_NCCALCSIZE == uMsg)
{
return 0;
}
else if (WM_NCPAINT ==  uMsg)
{
return 0;
}


        if( m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes) ) 
        {
            return lRes;
        }
//响应截获消息的相关操作:开始
//没哟处理:调用基类的消息响应函数进行处理.
        return __super::HandleMessage(uMsg, wParam, lParam);
    }
protected:
    CPaintManagerUI m_PaintManager;
};
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
//类静态成员函数
     CPaintManagerUI::SetInstance(hInstance);
     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());   // 设置资源的默认路径(此处设置为和exe在同一目录)
    CDuiFrameWnd duiFrame;
    duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    duiFrame.CenterWindow();
    duiFrame.ShowModal();
    return 0;
}


.xml文件

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


设置按钮属性前样式:



设置按钮样式后:

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值