Duilib 源码分析(一)示例推演
Duilib源码下载地址
官网地址:https://github.com/duilib/duilib
源码下载地址https://github.com/duilib/duilib/archive/master.zip
Duilib示范例子
使用Duilib编写一个界面软件,本质上还是一个Win32的软件,只不过这个软件的界面不使用Windows自带的控件,而是交给Duilib绘制界面。
关于消息处理,底层还是处理Window消息,但Duilib会进一步转化成Duilib消息,方便编写响应的逻辑。
最简单的Win32程序如下:
#include <windows.h>
int APIENTRY _tWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd)
{
MessageBox(NULL, _T("Hello World"), NULL, NULL);
return 0;
}
加载Duilib动态库
#include "UIlib.h" // 引入头文件:UIlib.h
using namespace DuiLib; // 使用命名空间:DuiLib
#pragma comment(lib, "DuiLib_ud.lib") // 加载导入库:DuiLib_ud.lib
int APIENTRY _tWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd)
{
MessageBox(NULL, _T("Hello World"), NULL, NULL);
return 0;
}
带界面的软件,可以分成两大模块:界面显示和消息处理
Duilib中的CPaintManagerUI负责管理界面和消息
Duilib中的CWindowWnd负责处理Window消息
Duilib中的INotifyUI负责处理Duilib消息
#include "UIlib.h" // 引入头文件:UIlib.h
using namespace DuiLib; // 使用命名空间:DuiLib
#pragma comment(lib, "DuiLib_ud.lib") // 加载导入库:DuiLib_ud.lib
class CDuilibWnd :public CWindowWnd, public INotifyUI
{
// 绘制管理器:负责绘制界面和管理消息
CPaintManagerUI m_PaintManager
// CWindowWnd中处理Window消息
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
// INotifyUI中处理Duilib消息
void Notify(TNotifyUI& msg);
}
int APIENTRY _tWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd)
{
MessageBox(NULL, _T("Hello World"), NULL, NULL);
return 0;
}
绘制管理器初始化
#include "UIlib.h" // 引入头文件:UIlib.h
using namespace DuiLib; // 使用命名空间:DuiLib
#pragma comment(lib, "DuiLib_ud.lib") // 加载导入库:DuiLib_ud.lib
class CDuilibWnd :public CWindowWnd, public INotifyUI
{
// 绘制管理器:负责绘制界面和管理消息
CPaintManagerUI m_PaintManager
// CWindowWnd中处理Window消息
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
// INotifyUI中处理Duilib消息
void Notify(TNotifyUI& msg);
}
int APIENTRY _tWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd)
{
// 绘制管理器CPaintManagerUI绑定窗口句柄
CPaintManagerUI::SetInstance(hInstance);
// 绘制管理器CPaintManagerUI设置资源目录,用于加载XML
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstan
return 0;
}
创建并显示界面
#include "UIlib.h" // 引入头文件:UIlib.h
using namespace DuiLib; // 使用命名空间:DuiLib
#pragma comment(lib, "DuiLib_ud.lib") // 加载导入库:DuiLib_ud.lib
class CDuilibWnd :public CWindowWnd, public INotifyUI
{
// 绘制管理器:负责绘制界面和管理消息
CPaintManagerUI m_PaintManager
// CWindowWnd中处理Window消息
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
// INotifyUI中处理Duilib消息
void Notify(TNotifyUI& msg);
}
int APIENTRY _tWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nShowCmd)
{
// 绘制管理器CPaintManagerUI绑定窗口句柄
CPaintManagerUI::SetInstance(hInstance);
// 绘制管理器CPaintManagerUI设置资源目录,用于加载XML
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstan
// 创建窗口
CDuilibWnd duilibWnd;
duilibWnd.Create(NULL, _T("标题"),UI_WNDSTYLE_FRAME,WS_EX_WINDOWEDGE);
// 显示窗口并且监听消息
duilibWnd.ShowModal();
return 0;
}
处理Window消息
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = 0;
// 初始化窗口消息
if (uMsg == WM_CREATE)
{
// 初始化绘制管理器,m_hWnd句柄在一个消息WM_NCCREATE中赋值
m_PaintManager.Init(m_hWnd);
// 使用XML布局文件生成界面
CDialogBuilder builder;
CControlUI* pRoot = builder.Create(_T("duilib.xml"), 0, NULL, &m_PaintManager);
ASSERT(pRoot && "Failed to parse XML");
// 添加CControlUI对象,用于管理界面
m_PaintManager.AttachDialog(pRoot);
// 添加INotifyUI对象,用于处理消息
m_PaintManager.AddNotifier(this);
return lRes;
}
// CPaintManagerUI处理消息
if (m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;
// CWindowWnd兜底处理消息
return __super::HandleMessage(uMsg, wParam, lParam);
}
处理Duilib消息
void Notify(TNotifyUI& msg)
{
if (msg.sType == DUI_MSGTYPE_CLICK)
{
if (msg.pSender->GetName() == _T("btn"))
{
::MessageBox(NULL, _T("按钮内容"), _T("按钮标题"), NULL);
}
}
}
其中生成界面的逻辑代码
CPaintManagerUI m_PaintManager;
CDialogBuilder builder;
CControlUI* pRoot = builder.Create(_T("duilib.xml"), 0, NULL, &m_PaintManager);
m_PaintManager.AttachDialog(pRoot);
小结
Duilib只是个界面库,软件本质还是Win32软件,只不过界面的绘制交给Duilib中的CPaintManagerUI负责处理,而解析界面XML文件的是CDialogBuilder 。软件的消息交给CWindowWnd和INotifyUI处理。
Duilib技术交流群:799142530
源码地址:https://github.com/KongKong20/DuilibTutor