Duilib界面庫是一款由杭州月牙兒網絡技術有限公司開發的界面開源庫,以viksoe項目下的UiLib庫的基礎上開發(此后也將對UiLib庫進行源碼分析);通過XML布局界面,將用戶界面和處理邏輯徹底分離,極大地提高用戶界面的開發效率。一般常用於開發小型項目Windows桌面客戶端軟件;其子窗口不以窗口句柄的形式創建,只是邏輯上的窗口,繪制在父窗口之上。目前開源協議以BSD發布,可使用於商業應用,好了,其他更為詳細的介紹,請查閱其官網或百度。
源碼獲取:
目前duilib不在被維護,基本上網絡中各種duilib版本都是被個人維護,原始duilib源碼可以在github:https://github.com/disable/duilib;中獲取,此外比較活躍的版本:https://github.com/redrains/DuiLib_Redrain;以及https://github.com/duisharp/DuiLib_Ultimate;另外包含一個擴展版本:https://github.com/shaoyuan1943/Duilib_Ext;為了便於理解dullib項目,我們將采用原始版本的duilib源碼分析。
源碼文件組織:
源碼文件中主要分為:DuiLib庫、用以XML腳本配置的DuiDesigner設計器、doc文檔入門手冊、bin編譯后的設計器和duilib.dll以及各demo需要的xml資源、各種用例demo、包含各種控件的屬性列表.XML、其他不重要的文件;
題外話--》源碼分析步驟:
基本上作為分析源碼的步驟大致應該是:
1. 閱讀官方簡介,了解其特性、功能、應用場景;
2. 獲取源碼和開發文檔等一系列說明文檔;
3. 思考自己開發該項目應該會如何架構、功能實現等;
4. 編譯源碼、順利執行程序,觀察執行效果,從入口點跟蹤程序;
5. 先了解項目大致運行方式、模塊組織結構,體會其中可以學習的設計模式;
6. 再從細節上學習其使用到得慣用法、奇淫技巧;
7. 與第3步作對比,感受項目實現和自己的想法的異同點;
8. 在學習過程中作筆記、畫草圖,此后若有時間建議可以自己嘗試實現該項目,拷貝部分源碼分步驟學習也是不錯的方式。
事實上,每個人學習的方式不同,有的人會從開發文檔或入門手冊開始,有的人會從demo用例開始了解使用。
以后將以DuLlib庫文件分析說明,其他如設計器請自行查看入門手冊和使用,因設計器會產生很多無用代碼且存在BUG,后期配置XNL時可手動填寫即可,填寫后可以設計器簡單查看效果即可:
DuLlib庫:
文件結構:
Core:核心組件(渲染器、容器、構建器、解析器、控件基類);
Layout:界面布局組件(水平、垂直、子控件、Tab等);
Utils:輔助工具相關(解壓縮、圖片、窗口基類、委托等);
Control:各種控件(button、combox、label、checkbox、list等);
執行流程:
以下以TestApp1作為入手demo;找到入口點:WinMain,可以看到實際上是對Win32程序的另外一套不同於MFC框架的封裝過程;
1. CPaintManagerUI:界面顯示、消息管理類;此處其設置當前應用程序實例句柄以及實例所需要的資源路徑目錄;
2. 初始化COM組件(::CoInitialize() ),以使得duilib可調用COM相關函數;
3. 創建當前窗口實例並創建、顯示窗口,執行CPaintManagerUI的消息循環;
4. 卸載COM組件(::CoUninitialize() )。
注意:申請的資源pFrame並沒有顯式地析構,事實上在退出消息循環前已被析構,請留意消息WM_NCDESTROY,並調用了OnFinalMessage(hWnd)執行了析構;
運行該程序,一個比較炫的界面展示在我們面前,我們通過斷點跟蹤每一個步驟:
我們重點關注第3個流程,窗口如何被創建、界面是如何布局、消息如何流轉等;進入Create函數,一眼看見我們熟悉的注冊窗口中定義窗口類,
注冊窗口、創建窗口;其中重點關注注冊窗口類中的消息處理函數CWindowWnd::__WndProc;在創建窗口前(窗口已存在),執行了一系列的操作;
__WndProc首先得到消息WM_GETMINMAXINFO,然后是WM_NCCREATE,該消息內部處理為保存當前句柄對象,並將本類對象放置在窗口的用戶數據中,這樣后期可以取出該對象,
並直接使用該對象成員處理函數即可,實現類靜態或全局處理函數轉化為類普通成員消息處理函數的目的,即HandleMessage;此外還有其他的消息,如WM_NCSIZE, WM_SIZE等,
其中消息WM_CREATE下的構建器將實際地根據提供的XML配置、遍歷創建各控件元素、並將本類對象和創建的root根控件依附於繪制管理器中;
消息流轉大體方式為:CWindowWnd::__WndProc -> HandleMessage -> CPaintManager::MessageHandler;其中有些消息不被處理將還給::DefWindowProc或
::CallWindowProc默認處理;
消息循環:調用CPaintManagerUI中的MessageLoop,內部采用GetMessage、TranslateMessage、DispatchMessage獲取消息、翻譯消息、分派消息;其中在調用全局的
TranslateMessage前,先調用了CPaintManagerUI::TranslateMessage,給予用戶自己翻譯消息碼的機會;
基本的流程框架如上,若要站在一個比較高的角度去看整體框架,需要對所有的組織結構有所了解,對於初次接觸duilib的話可以先看文檔是否有對整體結構的文檔說明,然后再對症下葯,從自己感興趣的部分入手;不過沒有關系,我們一步一步來,接下來我們將對各組織部分的主要內容進行詳細的分析。