DuiLib主要用于创建一个漂亮的界面程序,界面的全部定义放到了xml文件中保存。程序加载xml文件中的内容就能够显示之前定义的界面。定义可以用DuiLib提供的一个工具UIDesigner.exe进行定义,如果你技术足够好的话也可以自己编写xml文件。
下面看一下用UIDesigner.exe定义的一个简单界面:
下面看一下在xml文件中定义形式:
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<Window size="589,439" sizebox="4,4,6,6" caption="0,0,0,30">
<VerticalLayout name="VerticalLayoutUI1" text="第二个测试文本框" bkcolor="#FF0000FF" inset="1,1,1,1">
<HorizontalLayout name="HorizontalLayoutUI1" pos="0,0,0,68" height="68" bkimage="file='titlebar.png' fade='205'" inset="1,1,1,1">
<HorizontalLayout name="HorizontalLayoutUI2" pos="0,0,0,71" height="71">
<Label name="LabelUI1" text="第一个测试程序" float="true" pos="71,13,277,56" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" />
<Control name="ControlUI1" float="true" pos="9,7,60,59" bkimage="theworld.png" />
</HorizontalLayout>
<HorizontalLayout name="HorizontalLayoutUI3" pos="497,21,606,92" width="109" height="71">
<Button name="closeBtn" float="true" pos="74,4,108,29" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file='title_close.png' dest='0,0,30,25' source='0,0,30,25'" hotimage="file='title_close2.png' dest='0,0,30,25' source='45,0,86,25'" />
<Button name="bigBtn" float="true" pos="40,4,74,29" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file='title_max.png' dest='0,0,32,20' source='0,0,32,20'" hotimage="file='title_max.png' dest='0,0,32,20' source='35,0,65,20'" pushedimage="file='title_max.png' dest='0,0,32,20' source='32,0,63,20'" />
<Button name="restoreBtn" visible="false" float="true" pos="33,5,67,30" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file='title_max2.png' dest='0,0,32,25' source='0,0,32,25'" hotimage="file='title_max2.png' dest='0,0,32,25' source='32,0,64,25'" pushedimage="file='title_max2.png' dest='0,0,32,25' source='64,0,96,25'" />
<Button name="minBtn" float="true" pos="3,3,37,28" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="file='title_min.png' dest='0,0,32,25' source='0,0,32,25'" hotimage="file='title_min.png' dest='0,0,32,25' source='64,0,96,25'" />
</HorizontalLayout>
</HorizontalLayout>
<VerticalLayout name="VerticalLayoutUI2" bkcolor="#FFFFFBF0">
<VerticalLayout name="VerticalLayoutUI3">
<VerticalLayout name="VerticalLayoutUI4">
<HorizontalLayout name="HorizontalLayoutUI5" pos="0,0,0,39" height="39" bkimage="titlebar.png" bkcolor="#FF0000FF" bkcolor2="#000000FF">
<Button name="ButtonUI1" text="硬件检测" float="true" pos="22,7,97,34" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="button_down.bmp" hotimage="button_nor.bmp" pushedimage="button_over.bmp" />
<Button name="ButtonUI2" text="木马查杀" float="true" pos="106,9,180,34" textcolor="#FF000000" disabledtextcolor="#FFA7A6AA" align="center" normalimage="button_down.bmp" hotimage="button_nor.bmp" pushedimage="button_over.bmp" />
</HorizontalLayout>
</VerticalLayout>
<HorizontalLayout name="HorizontalLayoutUI4" pos="0,208,0,261" height="53" bkimage="titlebar.png" />
</VerticalLayout>
</VerticalLayout>
</VerticalLayout>
</Window>
说明一下:DuiLib所制作的界面就仅仅是显示的界面,其中并没有包含任何的处理逻辑。所有的处理逻辑都在C++编写的代码中实现。所做的每一个界面都对应着一个类来和这个界面对应。在其中能够进行处理逻辑,比如说按钮的响应。
下面编写一个类和上面的界面对应,代码如下:
头文件:
class CMyFirstWnd : public CWindowWnd, public INotifyUI
{
public:
CMyFirstWnd();
//这个函数将被系统所调用
LPCTSTR GetWindowClassName() const;
//当窗口关闭的时候会调用这个函数
void OnFinalMessage(HWND hWnd);
//处理一些系统消息
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
//对窗口进行一些初始化工作
void Init();
// 前期的准备工作,在这里我什么都没做
void OnPrepare();
// 处理按钮消息
void Notify(TNotifyUI& msg);
// 屏蔽自带的系统关闭,最大化,最小化按钮。
LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
// 自定义的最大化,最小化,关闭按钮的图片切换
LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
public:
CPaintManagerUI m_pm;
};
下面看一下cpp文件中的实现代码:
#include "StdAfx.h"
#include "MyFirstWindow.h"
#include <exdisp.h>
#include <comdef.h>
CMyFirstWnd::CMyFirstWnd()
{
}
LPCTSTR CMyFirstWnd::GetWindowClassName() const
{
return _T("UIMainFrame");
}
void CMyFirstWnd::OnFinalMessage(HWND hWnd)
{
delete this;
}
LRESULT CMyFirstWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if( uMsg == WM_CREATE )
{
m_pm.Init(m_hWnd);
CDialogBuilder builder;
CControlUI* pRoot = builder.Create(_T("testSkin.xml"), (UINT)0, NULL, &m_pm);
ASSERT(pRoot && "Failed to parse XML");
m_pm.AttachDialog(pRoot);
m_pm.AddNotifier(this);
Init();
return 0;
}
else if( uMsg == WM_ERASEBKGND )
{
return 1;
}
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;
}
else if (uMsg == WM_DESTROY)
{
PostQuitMessage(0);
}
else if (uMsg == WM_SYSCOMMAND)
{
BOOL bHandled = false;
return OnSysCommand(uMsg, wParam, lParam, bHandled);
}
if (uMsg == WM_NCHITTEST)
{
BOOL bHandled = false;
return OnNcHitTest(uMsg, wParam, lParam, bHandled);
}
LRESULT lRes = 0;
if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) )
return lRes;
return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
}
void CMyFirstWnd::Init()
{
}
void CMyFirstWnd::OnPrepare()
{
}
void CMyFirstWnd::Notify(TNotifyUI& msg)
{
if( msg.sType == _T("windowinit") )
OnPrepare();
else if( msg.sType == _T("click") )
{
if(msg.pSender->GetName() == _T("closeBtn"))
{
PostQuitMessage(0);
}
else if (msg.pSender->GetName() == _T("bigBtn"))
{
PostMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
}
else if (msg.pSender->GetName() == _T("restoreBtn"))
{
PostMessage(WM_SYSCOMMAND, SC_RESTORE, 0);
}
else if (msg.pSender->GetName() == _T("minBtn"))
{
PostMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
}
}
}
LRESULT CMyFirstWnd::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam);
::ScreenToClient(*this, &pt);
RECT rcClient;
::GetClientRect(*this, &rcClient);
RECT rcCaption = m_pm.GetCaptionRect();
if( pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom ) {
CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
if( pControl && _tcscmp(pControl->GetClass(), _T("ButtonUI")) != 0 &&
_tcscmp(pControl->GetClass(), _T("OptionUI")) != 0 &&
_tcscmp(pControl->GetClass(), _T("TextUI")) != 0 )
return HTCAPTION;
}
return HTCLIENT;
}
LRESULT CMyFirstWnd::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// 有时会在收到WM_NCDESTROY后收到wParam为SC_CLOSE的WM_SYSCOMMAND
if( wParam == SC_CLOSE ) {
::PostQuitMessage(0L);
bHandled = TRUE;
return 0;
}
BOOL bZoomed = ::IsZoomed(*this);
LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
if( ::IsZoomed(*this) != bZoomed ) {
if( !bZoomed ) {
CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("bigBtn")));
if( pControl )
pControl->SetVisible(false);
pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restoreBtn")));
if( pControl )
pControl->SetVisible(true);
}
else {
CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("bigBtn")));
if( pControl ) pControl->SetVisible(true);
pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restoreBtn")));
if( pControl ) pControl->SetVisible(false);
}
}
return lRes;
}
下面实在main函数中的编写方式:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
{
CPaintManagerUI::SetInstance(hInstance);
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());
HRESULT Hr = ::CoInitialize(NULL);
if(FAILED(Hr))
return 0;
CMyFirstWnd* pFrame = new CMyFirstWnd();
if( pFrame == NULL ) return 0;
pFrame->Create(NULL, _T("我的第一个DUILIB程序"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
pFrame->CenterWindow();
pFrame->ShowWindow(true);
CPaintManagerUI::MessageLoop();
::CoUninitialize();
return 0;
}
这样一个程序窗口就能够显示出来了。如下图所示:
一个界面就完成了。你也试一试吧!!!!!