前面那些教程都是為了讓小伙伴們從win32、MFC過渡到duilib,讓大家覺得duilib不是那么陌生,如果大家現在還對duilib非常陌生的話,那就說明前面的教程做得不好,請大家在下面留言,我會一一查看,並做出改進。
從這個教程開始就是見證奇跡的時刻啦~\(^o^)/~
其實duilib主打的界面制作方式是XML + UI引擎 + win32框架,其實和瀏覽器HTML + CSS + 渲染引擎的方式非常類似,可以將其理解為一個非常mini的瀏覽器。
而用duilib寫界面時,大部分是在寫XML,類似於寫HTML,這點可能會讓習慣MFC等windows界面的伙伴們有點不習慣,需要克服克服,相信在看完Alberl的教程之后,就會習慣啦~
前面的教程所使用的界面制作方式大家應該不算陌生,那么如果用XML來實現,會是什么樣子呢?
其實也是很簡單的,
1、把if( uMsg == WM_CREATE ) 里面的代碼改成下面這樣:
if( uMsg == WM_CREATE ) { 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); m_PaintManager.AddNotifier(this); // 添加控件等消息響應,這樣消息就會傳達到duilib的消息循環,我們可以在Notify函數里做消息處理 return lRes; }
2、設置XML的路徑:
在CPaintManagerUI::SetInstance(hInstance); 下面調用SetResourcePath函數:
CPaintManagerUI::SetInstance(hInstance); CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()); // 設置資源的默認路徑(此處設置為和exe在同一目錄)
3、建立XML:
新建一個XML,文件名為“duilib.xml”,保存為UTF-8格式(
不要使用windows自帶的記事本編輯,可以使用UltraEdit、EditPlus等編輯器),內容如下:
<?xml version="1.0" encoding="UTF-8"?> <Window size="800,600"> <!-- 窗口的初始尺寸 --> <HorizontalLayout bkcolor="#FF00FF00"> <!-- 整個窗口的背景 --> </HorizontalLayout> </Window>
4、將"duilib.xml"放到exe目錄下。
現在即可看到一個綠色的窗口,是不是也很簡單呢。
那么我們繼續來添加Hello World按鈕吧~O(∩_∩)O~
上面的XML只是描述了窗口的大小和背景色,但是並沒有添加按鈕,下面我們添加一個Hello 按鈕,只需在XML里面添加一行即可:
<?xml version="1.0" encoding="UTF-8"?> <Window size="800,600"> <!-- 窗口的初始尺寸 --> <HorizontalLayout bkcolor="#FF00FF00"> <!-- 整個窗口的背景 --> <Button name="btnHello" text="Hello World"/> <!-- 按鈕的屬性,如名稱、文本 --> </HorizontalLayout> </Window>
再次運行一下exe,是不是又看到了熟悉的畫面,怎么樣,寫XML很簡單吧~O(∩_∩)O~ :

不過大家可以發現,改成XML后,窗口啟動后不居中了,怎么辦呢?
在duiFrame.ShowModal上面那行加上duiFrame.CenterWindow();就可以啦
main.cpp的完整代碼如下:
#pragma once #include <UIlib.h> using namespace DuiLib; #ifdef _DEBUG # ifdef _UNICODE # pragma comment(lib, "DuiLib_ud.lib") # else # pragma comment(lib, "DuiLib_d.lib") # endif #else # ifdef _UNICODE # pragma comment(lib, "DuiLib_u.lib") # else # pragma comment(lib, "DuiLib.lib") # endif #endif class CDuiFrameWnd : public CWindowWnd, public INotifyUI { public: virtual LPCTSTR GetWindowClassName() const { return _T("DUIMainFrame"); } virtual void Notify(TNotifyUI& msg) { if(msg.sType == _T("click")) { if(msg.pSender->GetName() == _T("btnHello")) { ::MessageBox(NULL, _T("我是按鈕"), _T("點擊了按鈕"), NULL); } } } 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("duilib.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函數里做消息處理 return lRes; } // 以下3個消息WM_NCACTIVATE、WM_NCCALCSIZE、WM_NCPAINT用於屏蔽系統標題欄 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; } 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; }
注意:以上已給出完整代碼,由於最前面的17行是#include等信息,基本不會變動,所以后面的教程不再列出這些代碼。