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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM