在上篇中我們手寫了一個界面端壳,并在上面添加了兩個按鈕,在收到WM_CREATE
消息后枪蘑,創(chuàng)建界面损谦。一般界面包含很多個控件岖免,而且界面經(jīng)常發(fā)生變化,如果還是手寫的畫照捡,顯然不現(xiàn)實颅湘。
在duilib中可以使用xml來描述界面,框架通過解析xml栗精,創(chuàng)建界面闯参,這和我們手動寫xml的效果是一樣的。使用xml來描述界面悲立,實現(xiàn)了界面和界面處理邏輯的分離鹿寨。
這種界面和界面處理邏輯分離的方式其實和Qt是一樣的,Qt 使用的是.ui
文件(實質(zhì)上是xml格式的文件)來描述界面薪夕。
在duilib源碼中的屬性列表.xml
這個文件描述了duilib支持解析的元素和屬性脚草。以Button
為例:
<Button parent="Label" notifies="setfocus killfocus timer menu click windowinit(root)">
<Attribute name="name" default="" type="STRING" comment="控件名字,同一窗口內(nèi)必須唯一原献,如(testbtn)"/>
<Attribute name="pos" default="0,0,0,0" type="RECT" comment="位置馏慨,如果為float控件則指定位置和大小,否則只指定大小,如(0,0,100,100)"/>
<Attribute name="padding" default="0,0,0,0" type="RECT" comment="外邊距,如(2,2,2,2)"/>
<Attribute name="bkcolor" default="0x00000000" type="DWORD" comment="背景顏色,如(0xFFFF0000)"/>
<Attribute name="bkcolor2" default="0x00000000" type="DWORD" comment="背景漸變色2,和bkcolor配合使用,如(0xFFFFFF00)"/>
...省略很多...
</Button>
他的父節(jié)點為Label
控件姑隅,他的屬性有name
写隶,pos
,padding
讲仰,bkcolor
等樟澜。
屬性名、默認值叮盘、值的類型、屬性的用途都在屬性列表.xml
有描述霹俺。
我們編寫界面xml時要根據(jù)屬性列表.xml
柔吼。
我們用xml這么描述上篇手寫的界面:
<?xml version="1.0" encoding="UTF-8"?>
<Window size="800,600"> <!-- 窗口的初始尺寸 -->
<HorizontalLayout bkcolor="#FF00FF00"> <!-- 整個窗口的背景 -->
<Button name="btnHello1" pos="30,80,0,0" width="70" height="30" text="btnHello1"/> <!-- 按鈕的屬性,如名稱丙唧、文本 -->
<Button name="btnHello2" pos="120,80,0,0" width="70" height="40" text="btnHello2"/>
</HorizontalLayout>
</Window>
創(chuàng)建窗口時的對應(yīng)代碼要修改為:
if (uMsg == WM_CREATE)
{
m_PaintManager.Init(m_hWnd);
CDialogBuilder builder;
CControlUI* pRoot = builder.Create(_T("duilib.xml"), (UINT)0, NULL, &m_PaintManager);
ASSERT(pRoot && "Failed to parse XML");
m_PaintManager.AttachDialog(pRoot);
m_PaintManager.AddNotifier(this);
return lRes;
}
同時我們要設(shè)置xml的路徑:
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
CPaintManagerUI::SetInstance(hInstance);
// 設(shè)置資源的默認路徑(此處設(shè)置為和exe在同一目錄)
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetCurrentPath()+"\\Debug");
CDuiFrameWnd duiFrame;
duiFrame.Create(NULL, _T("DUIWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
duiFrame.CenterWindow(); // 啟動居中;
duiFrame.ShowModal();
return 0;
}
大家可能覺得愈魏,手寫界面xml也很麻煩,看效果也不是很方便想际,網(wǎng)友還是提供了一些ui設(shè)計工具培漏,比如DuiDesigner,通過工具操作胡本,可以幫助我們生成xml牌柄,還可以預(yù)覽效果。
其實對比下Qt的代碼:
class dlg_login : public QDialog
{
Q_OBJECT
public:
dlg_login(QWidget *parent = Q_NULLPTR);
~dlg_login();
signals:
void mainWndLogin();
private slots:
void OnLogin();
void showLoginWnd();
private:
void InitEvent();
private:
Ui::dlg_login ui;
};
duilib的業(yè)務(wù)代碼:
class CDuiFrameWnd : public CWindowWnd, public INotifyUI
{
public:
virtual LPCTSTR GetWindowClassName() const;
virtual void Notify(TNotifyUI& msg);
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
CPaintManagerUI m_PaintManager;
};
是不是有點類似呢侧甫?CPaintManagerUI m_PaintManager
相當(dāng)于Ui::dlg_login ui;
他們都是用來管理ui上的控件珊佣。
不同的是Qt的通信機制使用的是信號槽蹋宦,而duilib使用的是windows消息。