引入duilib時請確保引入頭文件開始時先引入COMUTIL.H頭文件
#include "COMUTIL.H"
#include "UIlib.h"
duilib基本程序結構
在stdafx.h文件中加入
[cpp] view plaincopy print?
<span?style="font-size:18px;">#include?"COMUTIL.H"??#include?"UIlib.h"??using?namespace?DuiLib;</span>??
<span style="font-size:18px;">#include "COMUTIL.H"
#include "UIlib.h"
using namespace DuiLib;</span>
[cpp] view plaincopy print?
<span?style="font-size:18px;">#ifndef?LoginView_h__??#define?LoginView_h__??????class?LoginView?:??????public?WindowImplBase??{??????public:??????DUI_DECLARE_MESSAGE_MAP()??public:??????LoginView(void);??????~LoginView(void);??????????void?on_btn_click(?DuiLib::TNotifyUI?&msg?);??????????virtual?CDuiString?GetSkinFolder()?{?return?_T?("skin\\");?}??????virtual?CDuiString?GetSkinFile()?{?return?_T("login.xml");?}??????virtual?LPCTSTR?GetWindowClassName(?void?)?const?{?return?_T("LoginView");?}??};??????#endif?//?LoginView_h__</span>??
<span style="font-size:18px;">#ifndef LoginView_h__
#define LoginView_h__class LoginView :public WindowImplBase// 只能放在最后,否則其消息路由出問題
{public:DUI_DECLARE_MESSAGE_MAP()
public:LoginView(void);~LoginView(void);void on_btn_click( DuiLib::TNotifyUI &msg );virtual CDuiString GetSkinFolder() { return _T ("skin\\"); }virtual CDuiString GetSkinFile() { return _T("login.xml"); }virtual LPCTSTR GetWindowClassName( void ) const { return _T("LoginView"); }
};#endif // LoginView_h__</span>
[cpp] view plaincopy print?
<span?style="font-size:18px;">#include?"StdAfx.h"??#include?"LoginView.h"????DUI_BEGIN_MESSAGE_MAP(LoginView,?WindowImplBase)??DUI_ON_MSGTYPE(DUI_MSGTYPE_CLICK,on_btn_click)??DUI_END_MESSAGE_MAP()??????LoginView::LoginView(void)??{??}????LoginView::~LoginView(void)??{??}??????void?LoginView::on_btn_click(?DuiLib::TNotifyUI?&msg?)??{????}</span>??
<span style="font-size:18px;">#include "StdAfx.h"
#include "LoginView.h"DUI_BEGIN_MESSAGE_MAP(LoginView, WindowImplBase)
DUI_ON_MSGTYPE(DUI_MSGTYPE_CLICK,on_btn_click)
DUI_END_MESSAGE_MAP()LoginView::LoginView(void)
{
}LoginView::~LoginView(void)
{
}void LoginView::on_btn_click( DuiLib::TNotifyUI &msg )
{}</span>
[cpp] view plaincopy print?
<span?style="font-size:18px;">??????#include?"stdafx.h"??#include?"chatme.h"????#include?"LoginView.h"????int?APIENTRY?_tWinMain(HINSTANCE?hInstance,?????????????????????????HINSTANCE?hPrevInstance,?????????????????????????LPTSTR????lpCmdLine,?????????????????????????int???????nCmdShow)??{??????CPaintManagerUI::SetInstance(hInstance);??????CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());??????????HRESULT?Hr?=?::CoInitialize(NULL);??????if(?FAILED(Hr)?)?return?0;????????LoginView?login_view;??????login_view.Create(NULL,?_T("LoginView"),?UI_WNDSTYLE_DIALOG,?WS_EX_STATICEDGE?|?WS_EX_APPWINDOW);????????login_view.CenterWindow();????????CPaintManagerUI::MessageLoop();??????::CoUninitialize();??????return?0;??}</span>??
<span style="font-size:18px;">// chatme.cpp : 定義應用程序的入口點。
//#include "stdafx.h"
#include "chatme.h"#include "LoginView.h"int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{CPaintManagerUI::SetInstance(hInstance);CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());HRESULT Hr = ::CoInitialize(NULL);if( FAILED(Hr) ) return 0;LoginView login_view;login_view.Create(NULL, _T("LoginView"), UI_WNDSTYLE_DIALOG, WS_EX_STATICEDGE | WS_EX_APPWINDOW);login_view.CenterWindow();CPaintManagerUI::MessageLoop();::CoUninitialize();return 0;
}</span>
問:如何把資源放入zip?
答: 先SetResourcePath設置資源目錄,再SetResourceZip設置壓縮資源文件名
問:如何設置窗體的初始化大小?
答:設置XML文件的Window標簽的size屬性。
問:如何設置鼠標可拖動窗體的范圍大小?
答:設置XML文件的Window標簽的caption屬性。
問:如何設置窗體可以通過拖動邊緣改變大小?
答:在窗體創建函數的第三個參數設置為UI_WNDSTYLE_FRAME才可響應拖動改變大小,和雙擊標題事件。
問:為何鼠標移動到邊緣沒有改變窗體大小的箭頭出現,不能通過拖動改變窗體大小?
答:設置window標簽的sizebox屬性,例如sizebox="2,2,2,2"
問:窗體不可雙擊最大化如何實現?
答:在窗體創建函數的第三個參數設置為UI_WNDSTYLE_DIALOG。
問:應用程序exe圖標如何設置?
答:使用窗體成員函數SetIcon,參數為資源icon的id。
問:初始化時,最大化窗體如何實現?
答:調用窗體的SendMessage給窗體發送最大化消息SC_MAXIMIZE,SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE,0);
問:動態改變窗體的大小如何實現?
答:使用窗體函數ResizeClient,參數分別重設的寬和高。
問:如何設置窗體屏幕居中顯示?
答:使用窗體的CenterWindow函數。
問:窗體透明度如何設置?
答:設置window標簽屬性bktrans="true" alpha="200" alpha的值為0-255。這種設置是全體窗體透明度,所有控件都將變透明。
如果想單純設置背景透明度控件不透明度,可以制作半透明的背景圖片,設置window標簽的bktrans="true",并且不設置alpha屬性,切記!此時背景透明,其它控件不透明。
單獨設置某個控件的透明度,可以使用圖片的fade屬性,或者mask屬性。fade表示設置圖片透明度,取值0-255。mask為設置透明的顏色。
問:默認設置的圖片為拉伸平鋪模式,如何設置不拉伸顯示?
答:設置圖片的source和dest屬性,soure="左,上,右,下" dest="左,上,右,下"?
表示將source區域的圖片顯示到按鈕的dest區域上。這里的右和下是指坐標,不是指寬度和高度。右=左+width.下=top+height。
問:如何設置選定編輯框文字的背景顏色?
答:設置nativebkcolor屬性。
問:如何設置按鈕的鼠標懸浮時的字體顏色?
答:設置按鈕的hottextcolor屬性,相對的還有pushedtextcolor和focustextcolor.
問:如何設置按鈕按下時字體的顏色?
答:設置按鈕的pushedtextcolor屬性,相對的還有hottextcolor和focustextcolor.
問:如何自定義xml控件?
答:自定義控件和復雜的控件類型都是由簡單基本控件組成。
在寫好一個自定義的控件xml模板后,
CDialogBuilder dlg_builder;
CControlUI * pControl = dlg_builder.Create("item.xml");
注意這里的item.xml要放在主界面的xml所在的文件夾內,并且無需在指定路徑了。
該函數返回一個CControlUI的一個句柄,得到這樣一個句柄就是一個控件了。
如果要獲取復雜控件的某個子控件的句柄,然后想通過該句柄改變子控件的狀態。
首先給這個子控件取一個名字,然后可以通過pControl的FindSubControl("name")來獲取該
控件的句柄了。得到句柄后就可以設置它的所有屬性了,例如
pbtn->SetAttribute(_T("normalimage"), _T("file='images\\downlist_ok.png' dest='20,14,32,26'"));就能更改它的狀態圖片了。
問:多線程下如何更改dui的界面信息?
答:線程里不要操作界面的信息,應該通過SendMessage或者PostMessage給界面的m_hWnd發送自定義消息。然后在界面的消息循環里面在做操作界面的動作。
自定義處理的消息處理函數可以從重寫方法
LRESULT MyWnd::HandleCustomMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
//這里處理完后,bHandled置true 返回基類,讓基類去操作
return WindowImplBase::HandleCustomMessage(uMsg, wParam, lParam, bHandled);
}
具體可以如下使用:
#define ON_PERCENT_MSG ? ? ? ? ? ? ?WM_USER + 500
然后在線程函數中發送消息給界面
int DownloadView::on_percent( double percent, int index, INT_PTR user_data )
{
? ? ::SendMessage(m_hWnd, ON_PERCENT_MSG, (WPARAM)&percent, (LPARAM)user_data);
? ? return 0;
}
最后在界面消息循環中進行處理消息
LRESULT DownloadView::HandleCustomMessage( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
? ? switch (uMsg)
? ? {
? ? case ON_PERCENT_MSG:
? ? ? ? ?// 處理界面相關的操作
? ? ? ? break;
? ? default:
? ? ? ? break;
? ? }
? ? return WindowImplBase::HandleCustomMessage(uMsg, wParam, lParam, bHandled);
}
問:如何讓使用duilib的win32工程支持MFC?
答:
1、在stdafx.h加入以下
#define VC_EXTRALEAN
#include <afxwin.h> ? ? ? ? // MFC 核心組件和標準組件
#include <afxext.h> ? ? ? ? // MFC 擴展
#include <afxdisp.h> ? ? ? ?// MFC 自動化類
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h>
// MFC 對 Internet Explorer 4 公共控件的支持
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h>
// MFC 對 Windows 公共控件的支持
#endif // _AFX_NO_AFXCMN_SUPPORT
2、在程序初始化main的開始加入mfc的初始化。
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
return 1;
}
3、設置頁屬性-->常規-->使用mfc設置為 Use MFC in a Shared DLL
4、設置C++-->代碼生成-->運行時庫根據debug或者release設置為MDD或者MD。
[cpp] view plaincopy print?
#pragma?once??????#define?DUI_MFCCTRL_COMMAND_MSG?_T("MFC_CTRL_NOTIFY_MSG")??#define?DUI_MFCCTRL_NOTIFY_MSG?_T("MFC_CTRL_COMMAND_MSG")??????????class?CDUIMFCCtrlWrapper?:?public?DuiLib::CControlUI,?public?DuiLib::IMessageFilterUI??{??public:??????CDUIMFCCtrlWrapper(void)?:?m_hWnd(NULL),?m_bAddedMessageFilter(FALSE){}??????????~CDUIMFCCtrlWrapper(void){}????????????????BOOL?Attach(HWND?hWndNew);??????????HWND?Detach();??????protected:????????????virtual?void?SetInternVisible(bool?bVisible?=?true);????????????????virtual?void?SetPos(RECT?rc);??????????????????????virtual?LRESULT?MessageHandler(?UINT?uMsg,?WPARAM?wParam,?LPARAM?lParam,?bool&?bHandled?);??????????virtual?void?SetManager(?DuiLib::CPaintManagerUI*?pManager,?DuiLib::CControlUI*?pParent,?bool?bInit?=?true?);??????protected:??????HWND?m_hWnd;??????BOOL?m_bAddedMessageFilter;???};??
#pragma once#define DUI_MFCCTRL_COMMAND_MSG _T("MFC_CTRL_NOTIFY_MSG")
#define DUI_MFCCTRL_NOTIFY_MSG _T("MFC_CTRL_COMMAND_MSG")// 封裝MFC控件到DUI控件中,實現duilib中嵌入MFC控件
// 通過維護一個HWND實現
class CDUIMFCCtrlWrapper : public DuiLib::CControlUI, public DuiLib::IMessageFilterUI
{
public:CDUIMFCCtrlWrapper(void) : m_hWnd(NULL), m_bAddedMessageFilter(FALSE){}~CDUIMFCCtrlWrapper(void){}// 綁定BOOL Attach(HWND hWndNew);HWND Detach();protected:// 控制顯示virtual void SetInternVisible(bool bVisible = true);// 控制位置virtual void SetPos(RECT rc);// 對控件消息的分派,例如對發送給如對命令消息和通知消息進行分派// 通過SendNotify實現,可以在OnNotify中進行響應。virtual LRESULT MessageHandler( UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled );virtual void SetManager( DuiLib::CPaintManagerUI* pManager, DuiLib::CControlUI* pParent, bool bInit = true );protected:HWND m_hWnd;BOOL m_bAddedMessageFilter; // 防止重復設置消息監聽
};
[cpp] view plaincopy print?
#include?"StdAfx.h"??????#include?"DUIMFCCtrlWrapper.h"??????using?namespace?DuiLib;??????void?CDUIMFCCtrlWrapper::SetManager(?CPaintManagerUI*?pManager,?CControlUI*?pParent,?bool?bInit??)??{??????if?(pManager?&&?!m_bAddedMessageFilter)??????{??????????m_bAddedMessageFilter?=?TRUE;????????????????????pManager->AddMessageFilter(this);??????}??????CControlUI::SetManager(pManager,?pParent,?false);??}??????LRESULT?CDUIMFCCtrlWrapper::MessageHandler(?UINT?uMsg,?WPARAM?wParam,?LPARAM?lParam,?bool&?bHandled?)??{??????bHandled?=?TRUE;???????if?(uMsg?==?WM_NOTIFY)??????{??????????NMHDR*?pNMHDR?=?(NMHDR*)lParam;??????????HWND?hWndCtrl?=?pNMHDR->hwndFrom;??????????UINT?nId?=?LOWORD(wParam);??????????int?nCode?=?pNMHDR->code;??????????ASSERT(NULL?!=?hWndCtrl);??????????ASSERT(::IsWindow(hWndCtrl));??????????typedef?struct?_CtrlNotifyStruct??????????{??????????????NMHDR*?pNMHDR;??????????????int?nCode;??????????}CtrlNotifyStruct;??????????CtrlNotifyStruct?ns;??????????ns.pNMHDR?=?pNMHDR;??????????ns.nCode?=?nCode;??????????m_pManager->SendNotify(this,?DUI_MFCCTRL_COMMAND_MSG,?WPARAM(nId),?LPARAM(&ns));??????}??????else?if?(WM_COMMAND?==?uMsg)??????{??????????UINT?nID?=?LOWORD(wParam);??????????HWND?hWndCtrl?=?(HWND)lParam;??????????int?nCode?=?HIWORD(wParam);??????????m_pManager->SendNotify(this,?DUI_MFCCTRL_NOTIFY_MSG,?nID,?nCode);??????}??????????????????????????????else??????{????????????????????bHandled?=?FALSE;??????????return?1;??????}??????return?0;??}??????void?CDUIMFCCtrlWrapper::SetPos(?RECT?rc?)??{??????__super::SetPos(rc);??????::SetWindowPos(m_hWnd,?NULL,?rc.left,???????????rc.top,?rc.right?-?rc.left,?rc.bottom?-?rc.top,??????????SWP_NOZORDER?|?SWP_NOACTIVATE);??}??????void?CDUIMFCCtrlWrapper::SetInternVisible(?bool?bVisible??)??{??????__super::SetInternVisible(bVisible);??????::ShowWindow(m_hWnd,?bVisible);??}??????HWND?CDUIMFCCtrlWrapper::Detach()??{??????HWND?hWnd?=?m_hWnd;??????m_hWnd?=?NULL;??????return?hWnd;??}??????BOOL?CDUIMFCCtrlWrapper::Attach(?HWND?hWndNew?)??{??????if?(!?::IsWindow(hWndNew))??????{??????????return?FALSE;??????}??????m_hWnd?=?hWndNew;??????return?TRUE;??}??
#include "StdAfx.h"#include "DUIMFCCtrlWrapper.h"using namespace DuiLib;void CDUIMFCCtrlWrapper::SetManager( CPaintManagerUI* pManager, CControlUI* pParent, bool bInit /*= true */ )
{if (pManager && !m_bAddedMessageFilter){m_bAddedMessageFilter = TRUE;// 設置本控件封裝能接收到消息,從而進行分派pManager->AddMessageFilter(this);}CControlUI::SetManager(pManager, pParent, false);
}LRESULT CDUIMFCCtrlWrapper::MessageHandler( UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled )
{bHandled = TRUE; // 如果是命令消息和通知消息等MFC控件消息則不用再傳遞下去if (uMsg == WM_NOTIFY){NMHDR* pNMHDR = (NMHDR*)lParam;HWND hWndCtrl = pNMHDR->hwndFrom;UINT nId = LOWORD(wParam);int nCode = pNMHDR->code;ASSERT(NULL != hWndCtrl);ASSERT(::IsWindow(hWndCtrl));typedef struct _CtrlNotifyStruct{NMHDR* pNMHDR;int nCode;}CtrlNotifyStruct;CtrlNotifyStruct ns;ns.pNMHDR = pNMHDR;ns.nCode = nCode;m_pManager->SendNotify(this, DUI_MFCCTRL_COMMAND_MSG, WPARAM(nId), LPARAM(&ns));}else if (WM_COMMAND == uMsg){UINT nID = LOWORD(wParam);HWND hWndCtrl = (HWND)lParam;int nCode = HIWORD(wParam);m_pManager->SendNotify(this, DUI_MFCCTRL_NOTIFY_MSG, nID, nCode);}//else if(XTPWM_PROPERTYGRID_NOTIFY == uMsg)//{// m_pManager->SendNotify(this, DUI_MFCCTRL_NOTIFY_MSG, wParam, lParam);//}else{// 否則該消息需要繼續傳遞下去bHandled = FALSE;return 1;}return 0;
}void CDUIMFCCtrlWrapper::SetPos( RECT rc )
{__super::SetPos(rc);::SetWindowPos(m_hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,SWP_NOZORDER | SWP_NOACTIVATE);
}void CDUIMFCCtrlWrapper::SetInternVisible( bool bVisible /*= true*/ )
{__super::SetInternVisible(bVisible);::ShowWindow(m_hWnd, bVisible);
}HWND CDUIMFCCtrlWrapper::Detach()
{HWND hWnd = m_hWnd;m_hWnd = NULL;return hWnd;
}BOOL CDUIMFCCtrlWrapper::Attach( HWND hWndNew )
{if (! ::IsWindow(hWndNew)){return FALSE;}m_hWnd = hWndNew;return TRUE;
}
[cpp] view plaincopy print?
#include?"stdafx.h"??#include?"DUIMFCCtrlWrapper.h"??#include?"Mycug.h"??????using?namespace?DuiLib;??????class?CFrameWindowWnd?:?public?WindowImplBase??{??????DUI_DECLARE_MESSAGE_MAP()??public:????????protected:??????virtual?CDuiString?GetSkinFolder()???????{??????????return?CPaintManagerUI::GetInstancePath();??????}??????????virtual?CDuiString?GetSkinFile()???????{??????????return?_T("test.xml");??????}??????????virtual?LPCTSTR?GetWindowClassName(?void?)?const??????{??????????return?_T("CFrameWindowWnd");??????}??????????virtual?CControlUI*?CreateControl(?LPCTSTR?pstrClass?)???????{??????????if?(_tcscmp(pstrClass,?_T("MfcCtrl"))?==?0)??????????{??????????????return?new?CDUIMFCCtrlWrapper();??????????}??????????return?NULL;??????}?????????void?OnClick(TNotifyUI&?msg)??????{??????????CDuiString?sCtrlName?=?msg.pSender->GetName();??????????if(?sCtrlName?==?_T("closebtn")?)??????????{??????????????PostMessage(WM_QUIT,?0,?0);??????????????return;???????????}??????????else?if(?sCtrlName?==?_T("minbtn"))??????????{???????????????SendMessage(WM_SYSCOMMAND,?SC_MINIMIZE,?0);???????????????return;???????????}??????????else?if(?sCtrlName?==?_T("maxbtn"))??????????{???????????????SendMessage(WM_SYSCOMMAND,?SC_MAXIMIZE,?0);???????????????return;???????????}??????????else?if(?sCtrlName?==?_T("restorebtn"))??????????{???????????????SendMessage(WM_SYSCOMMAND,?SC_RESTORE,?0);???????????????return;???????????}??????}???????????virtual?void?InitWindow()???????{??????????CDUIMFCCtrlWrapper*?pCtrl?=?(CDUIMFCCtrlWrapper*)m_PaintManager.FindControl(_T("grid"));??????????if?(pCtrl)??????????{??????????????m_GridCtrl.CreateGrid(WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),CWnd::FromHandle(GetHWND()),1234);??????????????pCtrl->Attach(m_GridCtrl.GetSafeHwnd());??????????}??????}??????????MyCug?m_GridCtrl;??};??
#include "stdafx.h"
#include "DUIMFCCtrlWrapper.h"
#include "Mycug.h"using namespace DuiLib;class CFrameWindowWnd : public WindowImplBase
{DUI_DECLARE_MESSAGE_MAP()
public:protected:virtual CDuiString GetSkinFolder() {return CPaintManagerUI::GetInstancePath();}virtual CDuiString GetSkinFile() {return _T("test.xml");}virtual LPCTSTR GetWindowClassName( void ) const{return _T("CFrameWindowWnd");}virtual CControlUI* CreateControl( LPCTSTR pstrClass ) {if (_tcscmp(pstrClass, _T("MfcCtrl")) == 0){return new CDUIMFCCtrlWrapper();}return NULL;}void OnClick(TNotifyUI& msg){CDuiString sCtrlName = msg.pSender->GetName();if( sCtrlName == _T("closebtn") ){PostMessage(WM_QUIT, 0, 0);return; }else if( sCtrlName == _T("minbtn")){ SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0); return; }else if( sCtrlName == _T("maxbtn")){ SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0); return; }else if( sCtrlName == _T("restorebtn")){ SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0); return; }} virtual void InitWindow() {CDUIMFCCtrlWrapper* pCtrl = (CDUIMFCCtrlWrapper*)m_PaintManager.FindControl(_T("grid"));if (pCtrl){m_GridCtrl.CreateGrid(WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),CWnd::FromHandle(GetHWND()),1234);pCtrl->Attach(m_GridCtrl.GetSafeHwnd());}}MyCug m_GridCtrl;
};
[cpp] view plaincopy print?
DUI_BEGIN_MESSAGE_MAP(CFrameWindowWnd,?WindowImplBase)??????DUI_ON_MSGTYPE(DUI_MSGTYPE_CLICK,OnClick)??DUI_END_MESSAGE_MAP()??????int?APIENTRY?WinMain(HINSTANCE?hInstance,?HINSTANCE?,?LPSTR?,?int?nCmdShow)??{????????????if?(!AfxWinInit(::GetModuleHandle(NULL),?NULL,?::GetCommandLine(),?0))??????{????????????????????_tprintf(_T("Fatal?Error:?MFC?initialization?failed\n"));??????????return?1;??????}??????CPaintManagerUI::SetInstance(hInstance);??????CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());??????????HRESULT?Hr?=?::CoInitialize(NULL);??????if(?FAILED(Hr)?)?return?0;??????????CFrameWindowWnd*?pFrame?=?new?CFrameWindowWnd();??????if(?pFrame?==?NULL?)?return?0;??????pFrame->Create(NULL,?_T("測試"),?UI_WNDSTYLE_FRAME,?WS_EX_WINDOWEDGE);??????pFrame->CenterWindow();??????pFrame->ShowWindow(true);??????CPaintManagerUI::MessageLoop();??????????::CoUninitialize();??????return?0;??}??
DUI_BEGIN_MESSAGE_MAP(CFrameWindowWnd, WindowImplBase)DUI_ON_MSGTYPE(DUI_MSGTYPE_CLICK,OnClick)
DUI_END_MESSAGE_MAP()int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
{// initialize MFC and print and error on failureif (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){// TODO: change error code to suit your needs_tprintf(_T("Fatal Error: MFC initialization failed\n"));return 1;}CPaintManagerUI::SetInstance(hInstance);CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());HRESULT Hr = ::CoInitialize(NULL);if( FAILED(Hr) ) return 0;CFrameWindowWnd* pFrame = new CFrameWindowWnd();if( pFrame == NULL ) return 0;pFrame->Create(NULL, _T("測試"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);pFrame->CenterWindow();pFrame->ShowWindow(true);CPaintManagerUI::MessageLoop();::CoUninitialize();return 0;
}
duilib繪圖部分
圖像的繪制大部分使用了繪制引擎的DrawImageString函數,該函數實現知道圖像名稱繪制到指定目標區域的功能
并且通過指定pStrModify的屬性能夠進行不同需求的繪制,例如,僅扣取源圖像的某個位置繪制到目標的某個區域、
設置四邊圓角繪制、為bmp等指定某種顏色為透明顏色、平鋪或者拉伸繪制、設置透明度等。
DrawImageString最終又調用CRenderEngine::DrawImage進行繪制。
[cpp] view plaincopy print?
??????????????????????bool?CRenderEngine::DrawImageString(HDC?hDC,?CPaintManagerUI*?pManager,?const?RECT&?rc,?const?RECT&?rcPaint,?????????????????????????????????????????????LPCTSTR?pStrImage,?LPCTSTR?pStrModify)??{??????if?((pManager?==?NULL)?||?(hDC?==?NULL))?return?false;????????????????????????????}??void?CRenderEngine::DrawImage(HDC?hDC,?HBITMAP?hBitmap,?const?RECT&?rc,?const?RECT&?rcPaint,??????????????????????????????????????const?RECT&?rcBmpPart,?const?RECT&?rcCorners,?bool?alphaChannel,???????????????????????????????????????BYTE?uFade,?bool?hole,?bool?xtiled,?bool?ytiled)??
// hDc HDC句柄
// CPaintManagerUI句柄
// rc 目標畫布的大小
// rcPaint 繪制區域
// pStrImage 為源圖像的名稱,不需提供路徑,函數內部會自動加上資源位置的路徑,路徑為CPaintManagerUI::SetResourcePath設置的路徑。
// pStrModify 設置繪制屬性,含義為:
// 2、file='aaa.jpg' res='' restype='0' dest='0,0,0,0' source='0,0,0,0' corner='0,0,0,0'
// mask='#FF0000' fade='255' hole='false' xtiled='false' ytiled='false'
// source和dest表示從源圖像的source區域貼到目標圖像的dest區域,mask表示讓某顏色為透明色,例如mask="#FF000000",設置黑色為透明色。
// xtiled,ytiled 設置為true表示橫向和縱向的圖像不拉伸顯示而是平鋪顯示
// hole 為true表示不繪制中間部分,為某些場合提高性能
bool CRenderEngine::DrawImageString(HDC hDC, CPaintManagerUI* pManager, const RECT& rc, const RECT& rcPaint, LPCTSTR pStrImage, LPCTSTR pStrModify)
{if ((pManager == NULL) || (hDC == NULL)) return false;// 1、aaa.jpg// 2、file='aaa.jpg' res='' restype='0' dest='0,0,0,0' source='0,0,0,0' corner='0,0,0,0' // mask='#FF0000' fade='255' hole='false' xtiled='false' ytiled='false'}
void CRenderEngine::DrawImage(HDC hDC, HBITMAP hBitmap, const RECT& rc, const RECT& rcPaint,const RECT& rcBmpPart, const RECT& rcCorners, bool alphaChannel, BYTE uFade, bool hole, bool xtiled, bool ytiled)
duilib中所有元素的顯示都在整個消息循環的WM_PAINT中進行繪制。
第一次繪制之前會發送一個名為_T("windowinit")的通知。
然后為CControlUI的繪制,繪制的順序為:背景顏色->背景圖->狀態圖->文本->邊框
會順序調用CControlUI的以下函數。 ? ? ? ?
[cpp] view plaincopy print?
PaintBkColor(hDC);??????????????PaintBkImage(hDC);????????????PaintStatusImage(hDC);?????PaintText(hDC);???????????????????PaintBorder(hDC);??????????????
PaintBkColor(hDC); // 繪制背景顏色
PaintBkImage(hDC); // 繪制背景圖
PaintStatusImage(hDC); // 繪制狀態圖
PaintText(hDC); // 繪制文本
PaintBorder(hDC); // 繪制邊框
所以有需求在界面上動態繪制一些內容時,可以通過CControlUI進行子類化,然后重寫PaintStatusImage,
在PaintStatusImage里面進行繪圖操作。繪制時可以直接調用duilib繪制引擎進行繪制,比較便捷。當然也可以使用GDI+等庫直接進行繪制。
duilib的圖像文件的加載是通過一個開源庫stb_image.c實現。
并只使用了該庫的stbi_load_from_memory和stbi_image_free這兩個功能函數。
該庫的鏈接地址:http://nothings.org/stb_image.c
該庫對圖片的格式的支持情況說明如下:
JPEG 支持Baseline標準型的JPEG,不支持漸進式Progressive的JPEG
PNG ? 僅支持8位的png圖像
BMP ?不支持1bpp的bmp,不支持行程編碼RLE的bmp
PSD ?緊顯示合成的圖像,不支持額外的通道
GIF *comp always reports as 4-channel
所以在duilib中使用的圖片時需要注意到這個限制,否則有些圖片將顯示不出來。
duilib中把圖片文件加載到內存后,由庫stb_image.c解析并最終轉為DIB處理。
duilib支持從圖片文件、從包含圖片文件的壓縮包文件和VC資源中載入圖片。
載入后最終返回TImageInfo結構體指針,包含HBITMAP、圖像寬度、圖像高度、alpha通道、mask和資源類型等信息。
載入函數為:TImageInfo* CRenderEngine::LoadImage(STRINGorID bitmap, LPCTSTR type, DWORD mask);
duilib中所有的圖片資源只從加載一次,然后保存在CPaintManagerUI中的m_mImageHash成員中,該成員為一個
hashmap存儲TImageInfo*信息,當已經存在要繪制顯示的圖片信息時,直接從map中獲取顯示,否則從文件加載
在添加到map中。
問:如何管理duilib界面皮膚資源?
答:把所有XML文件在同一個目錄下,圖片資源另外放在一個地方。當如下進行布局資源時,skin目錄為設置資源的目錄,imagedir1目錄放置1.xml文件利用到的圖片資源,imagedir2放置2.xml文件利用到的資源。
然后1.xml文件文件中的圖片資源名稱需要加上相對于當前xml文件的路徑信息即可。例如:normalimage="imagedir1/1.png"這樣的形式。使用設計器為XML添加資源時會自動轉化為相對路徑。
skin/
1.xml
2.xml
imagedir1/
1.png
2.png
imagedir2/
1.png
2.png
需注意一個問題,那就是字體的管理。字體對于一個窗口來說是全局的,索引從0開始,font = 0表示使用排在第一位的字體。如果一個界面被拆分為多個XML文件管理,并且當每個單獨的文件自己添加字體時,聯合起來的時候,會跟其它的字體發生沖突,即索引不是原來的索引了。索引得從全局來看。按照全局的方式進行設置好索引后,對于每個xml文件的預覽操作時,又看不到所見即所得的效果了。
關于設計器
問題:為什么給控件設置name屬性后保存,但該屬性信息丟失?
答:設置控件名稱,需要注意,名稱中不能含有該控件類名的字段,例如設置其中一個選項按鈕的名字為OptionUIMyTest,將不會被保存,因為默認的OptionUI1、OptionUI2等為設計器默認使用的名字當存在OptionUI時,設計器認為是默認的,并非用戶設定,所以沒有保存該信息到XML文件中。
問:如何把一個內容很長的xml文件分為拆分進行管理?
答:可以使用ChildLayout布局。指定xmlfile屬性設置為引用的xml文件。例如以下例子,必須注意一個問題,就是tab_main.xml設置上<Window>標簽,并且不要設置size屬性,否則會跟主窗體沖突,該大小會作為主窗體的大小而發生錯誤。
? ? ? ? ? ? <TabLayout name="MainTab" width="870" height="362">
? ? ? ? ? ? ? ? <ChildLayout xmlfile="tab_main.xml" />
? ? ? ? ? ? ? ? <VerticalLayout padding="1,0,1,1" bkcolor="#FFFFFFFF" />
? ? ? ? ? ? </TabLayout>
除了使用ChildLayout布局外,可以使用Include標簽,例如:
<Include source="scrollbar.xml" />
總結
以上是生活随笔為你收集整理的duilib入门问题集的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。