duilib是一个windows下的皮肤库,用win32写的。。。
先看个效果图吧:
要使用duilib库,必须先把库导入,代码如下:
View Row Code
1#include "xxx\UIlib.h" //xxx为UIlib.h的路径2using namespace Duilib; 34#ifdef _DEBUG5 #ifdef _UNICODE6 #pragma comment(lib,"xxx\Duilib_ud.lib")7 #else8 #pragma comment(lib,"xxx\Duilib_d.lib")9 #endif10#else11 #ifdef _UNICODE12 #progma comment(lib,"xxx\Duilib_u.lib")13 #else14 #progma comment(lib,"xxx\Duilib.lib")15#endif使用duilib库的程序和win32程序一样也是从WinMain开始的。在WinMain函数中,一般是这样做的:
View Row Code
1CPaintManagerUI::SetInstance(hInstance);2CPaintMamagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()+ TEXT("skin"));3CPaintManagerUI::SetResourceZip();4567在duilib中每个窗口均要定义一个CPaintManagerUI成员对象用来管理整个窗口的绘制。
duilib中的窗口均继承自CWindowWnd类,在CWindowWnd类中有虚函数HandleMessage来处理Windows消息(如WM_CREATE、WM_SIZE等)。另外,如果你的窗口想要响应鼠标的点击、编辑框内容改变等消息的话,可以把你的窗口类继承INotify接口,这样你的窗口上的一个按钮被点击了,可以在继承自INotify接口的Notify函数中进行处理。
在自己定义的窗口类中一般这样来处理HandleMessage:
View Row Code
1LRESULT CHelloWorld::HandleMessage( UINT uMsg,WPARAM wParam, LPARAM lParam )2{3 LRESULT lRes= 0;4 BOOL bHandled= TRUE;5 switch (uMsg)6 {7 case WM_CREATE:8 lRes =OnCreate(uMsg ,wParam, lParam, bHandled);9 break;10 default:11 bHandled =FALSE; break;12 }13 14 if (bHandled)return lRes;15 if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)!= 0)16 return lRes;17 return CWindowWnd::HandleMessage(uMsg, wParam, lParam);18}INotifyUI接口的Notify()由CPaintManagerUI::MessageHandler调用。继承INotifyUI接口的类对象会被加入到CPaintManagerUI的m_aNotifiers数组中,而要加入m_aNotifiers数组一般由窗口类自己在OnCreate函数调用CPaintManagerUI的静态方法AddNotifier将自己加入到m_aNotifiers中。
而在自己的窗口类的OnCreate函数中,通常调用m_pm.Init(m_hWnd)来把自己的窗口句柄与窗口绘制管理器挂接在一起,即用于向CPaintManagerUI提供窗口句柄及窗口上下文句柄。
View Row Code
1LRESULT CHelloWorld::OnCreate(UINT uMsg,WPARAM wParam, LPARAM lParam,BOOL& bHandled)2{3 m_pm.Init(m_hWnd); 4 CDialogBuilder builder;5 CControlUI* pRoot= builder.Create(TEXT("HelloWorld.xml"), (UINT)0,NULL, &m_pm); 6 ASSERT(pRoot&& "Failure to parse XML");7 m_pm.AttachDialog(pRoot);8 m_pm.AddNotifier(this); 9 Init();10 return 0;1112}以上就是关于duilib程序的一个建立过程。
详细代码如下:
View Row Code
123456#pragma once78#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料910#include <windows.h>11#include <objbase.h>121314#include "..\..\DuiLib\UIlib.h"1516using namespace DuiLib;1718#ifdef _DEBUG19# ifdef _UNICODE20# pragma comment(lib,"..\\..\\bin\\DuiLib_ud.lib")21# else22# pragma comment(lib,"..\\..\\bin\\DuiLib_d.lib")23# endif24#else25# ifdef _UNICODE26# pragma comment(lib,"..\\..\\bin\\DuiLib_u.lib")27# else28# pragma comment(lib,"..\\..\\bin\\DuiLib.lib")29# endif30#endifView Row Code
12345#include "stdafx.h"678View Row Code
12#pragma once34class CHelloWorld: public CWindowWnd,public INotifyUI 5{6 7 8public:9 CHelloWorld();10 void Init(); 11 void OnOK(); 12 void OnClose(); 1314 15 LRESULT OnCreate(UINT uMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled);16 17 LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled);18 LRESULT OnSize(UINT uMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled);19 LRESULT OnNcActivate(UINT uMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled);20 LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled);21 LRESULT OnSysCommand(UINT uMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled);22 LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam,LPARAM lParam, BOOL& bHandled);2324 25 26public:27 LPCTSTR GetWindowClassName() const ; 28 UINT GetClassStyle() const;29 void OnFinalMessage(HWND ); 30 LRESULT HandleMessage(UINT uMsg, WPARAM wParam,LPARAM lParam); 3132 3334 35public:36 void Notify(TNotifyUI& msg);3738 3940 41 42private:43 CButtonUI* m_pBtnOK; 44 CButtonUI* m_pBtnClose;4546 CPaintManagerUI m_pm; 47};View Row Code
1234#include "stdafx.h"5#include "HelloWorld.h"6#include "resource.h"78int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE ,LPSTR , int nCmdShow)9{10 CPaintManagerUI::SetInstance(hInstance); 11 12 CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()+ TEXT("skin"));1314 HRESULT Hr = ::CoInitialize(NULL);15 if( FAILED(Hr) ) return0;1617 CHelloWorld* pHW= new CHelloWorld();18 if (pHW== NULL)19 return0;20 pHW->Create(NULL,TEXT("Hello World"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE | WS_EX_APPWINDOW);21 pHW->SetIcon(IDI_HW);22 pHW->CenterWindow();23 pHW->ShowWindow();24 CPaintManagerUI::MessageLoop();2526 ::CoUninitialize();27 return 0;28}2930CHelloWorld::CHelloWorld()31: m_pBtnOK(NULL)32, m_pBtnClose(NULL)33{3435}3637void CHelloWorld::Init() 38{39 m_pBtnOK =static_cast<CButtonUI*>(m_pm.FindControl(TEXT("OK")));40 if (m_pBtnOK== NULL)41 return;42 43 4445 m_pBtnClose =static_cast<CButtonUI*>(m_pm.FindControl(TEXT("Close")));46 if (m_pBtnClose== NULL)47 return;48 49}5051void CHelloWorld::OnOK()52{53 Close(); 54}5556void CHelloWorld::OnClose()57{58 Close();59}6061LPCTSTR CHelloWorld::GetWindowClassName() const62{63 return TEXT("HelloWorld");64}6566UINT CHelloWorld::GetClassStyle() const67{68 return UI_CLASSSTYLE_FRAME | CS_DBLCLKS;69}7071void CHelloWorld::OnFinalMessage( HWND )72{73 delete this;74}7576LRESULT CHelloWorld::HandleMessage( UINT uMsg,WPARAM wParam, LPARAM lParam )77{78 LRESULT lRes= 0;79 BOOL bHandled= TRUE;80 switch (uMsg)81 {82 case WM_CREATE:83 lRes =OnCreate(uMsg ,wParam, lParam, bHandled);84 break;8586 case WM_DESTROY:87 ::PostQuitMessage(0);88 bHandled =FALSE;89 break;9091 case WM_NCHITTEST:92 lRes =OnNcHitTest(uMsg, wParam, lParam, bHandled);93 break;9495 case WM_KEYDOWN:96 if (wParam== VK_ESCAPE)97 {98 OnClose();99 }100 break;101102 case WM_SIZE:103 lRes =OnSize(uMsg, wParam, lParam, bHandled);104 break;105106 case WM_NCACTIVATE:107 lRes =OnNcActivate(uMsg, wParam, lParam, bHandled);108 break;109110 case WM_GETMINMAXINFO:111 lRes =true;112 OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); 113 break;114115 case WM_SYSCOMMAND:116 lRes =OnSysCommand(uMsg, wParam, lParam, bHandled); 117 break;118119 case WM_NCCALCSIZE:120 lRes =OnNcCalcSize(uMsg, wParam, lParam, bHandled); 121 break;122123 default:124 bHandled =FALSE; break;125 }126 127 if (bHandled)return lRes;128 if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)!= 0)129 return lRes;130 return CWindowWnd::HandleMessage(uMsg, wParam, lParam);131}132133LRESULT CHelloWorld::OnCreate(UINT uMsg,WPARAM wParam, LPARAM lParam,BOOL& bHandled)134{135 136 137 138 139 140 141142 m_pm.Init(m_hWnd); 143 CDialogBuilder builder;144 145 CControlUI* pRoot= builder.Create(TEXT("HelloWorld.xml"), (UINT)0,NULL, &m_pm);146 ASSERT(pRoot&& "Failure to parse XML");147 m_pm.AttachDialog(pRoot); 148 m_pm.AddNotifier(this); 149 Init();150 return 0;151152}153154LRESULT CHelloWorld::OnSize( UINT uMsg,WPARAM wParam, LPARAM lParam,BOOL& bHandled )155{156 SIZE szRoundCorner= m_pm.GetRoundCorner(); 157 if( !::IsIconic(*this)&& (szRoundCorner.cx != 0 || szRoundCorner.cy !=0) ) {158 CRect rcWnd;159 ::GetWindowRect(*this,&rcWnd);160 rcWnd.Offset(-rcWnd.left,-rcWnd.top); 161 rcWnd.right++; rcWnd.bottom++;162 HRGN hRgn= ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);163 ::SetWindowRgn(*this, hRgn,TRUE); 164 ::DeleteObject(hRgn);165 }166167 bHandled =FALSE;168 return 0;169}170171LRESULT CHelloWorld::OnNcHitTest(UINT uMsg,WPARAM wParam, LPARAM lParam,BOOL& bHandled)172{173 POINT pt; pt.x= GET_X_LPARAM(lParam); pt.y= GET_Y_LPARAM(lParam);174 ::ScreenToClient(*this,&pt);175176 RECT rcClient;177 ::GetClientRect(*this,&rcClient);178179 if( !::IsZoomed(*this) ) {180 RECT rcSizeBox= m_pm.GetSizeBox(); 181 if( pt.y< rcClient.top + rcSizeBox.top ) {182 if( pt.x< rcClient.left + rcSizeBox.left )return HTTOPLEFT;183 if( pt.x> rcClient.right - rcSizeBox.right )return HTTOPRIGHT;184 returnHTTOP;185 }186 elseif( pt.y > rcClient.bottom- rcSizeBox.bottom ) {187 if( pt.x< rcClient.left + rcSizeBox.left )return HTBOTTOMLEFT;188 if( pt.x> rcClient.right - rcSizeBox.right )return HTBOTTOMRIGHT;189 returnHTBOTTOM;190 }191 if( pt.x< rcClient.left + rcSizeBox.left )return HTLEFT;192 if( pt.x> rcClient.right - rcSizeBox.right )return HTRIGHT;193 }194195 RECT rcCaption= m_pm.GetCaptionRect(); 196 if( pt.x>= rcClient.left + rcCaption.left && pt.x< rcClient.right - rcCaption.right&& pt.y >= rcCaption.top && pt.y< rcCaption.bottom ) {197 CControlUI* pControl= static_cast<CControlUI*>(m_pm.FindControl(pt));198 if( pControl&& _tcsicmp(pControl->GetClass(),_T("ButtonUI")) != 0 && _tcsicmp(pControl->GetClass(),_T("OptionUI")) != 0)199 returnHTCAPTION;200 }201202 return HTCLIENT;203}204205void CHelloWorld::Notify( TNotifyUI& msg )206{207 if (msg.sType== TEXT("click")) 208 {209 if (msg.pSender->GetName()== TEXT("OK"))210 OnOK();211 if (msg.pSender->GetName()== TEXT("Close"))212 OnClose();213 }214 else if (msg.sType ==TEXT("windowinit"))215 {216 }217}218219LRESULT CHelloWorld::OnNcActivate( UINT uMsg,WPARAM wParam, LPARAM lParam,BOOL& bHandled )220{221 if( ::IsIconic(*this) ) bHandled= FALSE;222 return (wParam== 0) ? TRUE : FALSE;223}224225LRESULT CHelloWorld::OnGetMinMaxInfo( UINT uMsg, WPARAM wParam, LPARAM lParam,BOOL& bHandled )226{227 MONITORINFO oMonitor= {};228 oMonitor.cbSize = sizeof(oMonitor);229 ::GetMonitorInfo(::MonitorFromWindow(*this,MONITOR_DEFAULTTOPRIMARY), &oMonitor);230 CRect rcWork= oMonitor.rcWork;231 rcWork.Offset(-rcWork.left,-rcWork.top);232233 LPMINMAXINFO lpMMI= (LPMINMAXINFO) lParam;234 lpMMI->ptMaxPosition.x = rcWork.left;235 lpMMI->ptMaxPosition.y = rcWork.top;236 lpMMI->ptMaxSize.x = rcWork.right;237 lpMMI->ptMaxSize.y = rcWork.bottom;238239 bHandled =FALSE;240 return 0;241}242243LRESULT CHelloWorld::OnSysCommand( UINT uMsg, WPARAM wParam, LPARAM lParam,BOOL& bHandled )244{245 if (wParam== SC_CLOSE)246 {247 bHandled =TRUE;248 SendMessage(WM_CLOSE);249 return0;250 }251#if defined(WIN32) && !defined(UNDER_CE)252 BOOL bZoomed= ::IsZoomed(*this);253 LRESULT lRes= CWindowWnd::HandleMessage(uMsg, wParam, lParam);254 if( ::IsZoomed(*this)!= bZoomed )255 {256 }257#else258 LRESULT lRes= CWindowWnd::HandleMessage(uMsg, wParam, lParam);259#endif260 return lRes;261}262263LRESULT CHelloWorld::OnNcCalcSize( UINT uMsg, WPARAM wParam, LPARAM lParam,BOOL& bHandled )264{265 return 0;266 267}View Row Code
1// xml皮肤配置文件2<?xml version="1.0" encoding="utf-8" standalone="yes" ?>3<Window size="400,250" caption="0,0,0,30" roundcorner="6,6" sizebox="4,4,4,4" mininfo="100,50" maxinfo="500,300">4 <VerticalLayout bkcolor="#FF000000">5 <HorizontalLayout width="400" height="30" bkimage="file='top_bg.png' corner='5,5,5,5'">6 <HorizontalLayout widht="80">7 <Button name="OK" text="OK" align="center" width="80" height="30" textcolor="#FFC8C8C8" disabletextcolor="#FFA7A6AA" normalimage="file='BtnOK.png' source='0,0,80,30'" hotimage="file='BtnOK.png' source='80,0,160,30'" pushedimage="file='BtnOK.png' source='160,0,240,30'" disabledimage="file='BtnOK.png' source='240,0,320,30'" />8 </HorizontalLayout>9 <HorizontalLayout width="240">10 <Label name="caption" text="Hello World" textcolor="#FFFFFFFF" align="center" />11 </HorizontalLayout>12 <HorizontalLayout widht="80">13 <Button name="Close" text="Close" align="center" width="79" height="30" textcolor="#FFC8C8C8" disabletextcolor="#FFA7A6AA" normalimage="file='BtnClose.png' source='0,0,79,30'" hotimage="file='BtnClose.png' source='80,0,158,30'" pushedimage="file='BtnClose.png' source='159,0,237,30'" disabledimage="file='BtnClose.png' source='238,0,316,30'" />14 </HorizontalLayout>15 </HorizontalLayout>16 <VerticalLayout bkimage="file='MBbottombg.png' corner='6,6,6,6'">17 18 </VerticalLayout>19 </VerticalLayout>20</Window>其他:
1.开始写完程序运行后发现任务栏上没有图标,原来可以用SetIcon函数来设置,SetIcon函数的参数是一个资源ID(UINT类型),可以自己绘制一个图标或者导入一个,然后将该图标的id传入即可,还是比较方便的。注意的是SetIcon不需要使用MAKEINTRESOURCE来转换,在SetIcon函数内调用了MAKEINTRESOURCE。
2.在用窗口类的Create函数时,指定UI_WNDSTYLE_FRAME为第三个参数时,窗口可以双击最大化,而使用UI_WNDSTYLE_DIALOG时无法最大化。原来:
View Row Code
1#define UI_WNDSTYLE_FRAME (WS_VISIBLE | WS_OVERLAPPEDWINDOW)2#define UI_WNDSTYLE_CHILD (WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)3#define UI_WNDSTYLE_DIALOG (WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION | WS_DLGFRAME | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)WS_OVERLAPPEDWINDOW默认带有WM_MAXIMIZEBOX属性,固默认可以双击最大化。
S_POPUPWINDOW默认有WS_BORDER,WS_POPUP和WS_SYSMENU属性,没有WM_MAXIMIZEBOX属性,固POPUPWINDOW默认无法双击最大化。
3.WM_NCCALCSIZE消息的处理,MSDN中有这么一段描述:
When wParam is TRUE, simply returning 0 without processing the NCCALCSIZE_PARAMS rectangles will cause the client area to resize to the size of the window, including the window frame. This will remove the window frame and caption items from your window, leaving only the client area displayed.
也就是说这个消息处理时返回0,则窗口将会没有标题栏和外边框,只有客户区了。
4.WM_NCHITTEST消息的处理,可以返回HTTOPLEFT(窗口的左上角,鼠标变为可调边框标识)、HTTOPRIGHT等。返回HTCAPTION标识击中为标题栏,返回HTCLIENT标识击中为客户区。