整體框架組件模塊:
1. 層用層模塊;2. 組件與控件層模塊;
3. XML 數(shù)據(jù)加載層模塊
4. 渲染模塊
5. 具體數(shù)據(jù)模塊PNG BMP ICO XML(界面布局?jǐn)?shù)據(jù))
問(wèn)題導(dǎo)讀:
1. 入口函數(shù)是什么?2. 窗口過(guò)程在哪里定義, 如何修改窗口過(guò)程?
3. 如何加載XML , 加載的XML 數(shù)據(jù)放到哪個(gè)數(shù)據(jù)結(jié)構(gòu)中.如何建立起關(guān)聯(lián)的?
4. 界面元素 (控件) 是如何動(dòng)態(tài)建立起來(lái)的?
5. 如何讓控件與事件關(guān)聯(lián)起來(lái)?
6. 如何編寫(xiě)XML 文件?
一步一步源碼閱讀
①: 框架程序基本流程-> WinMain(入口函數(shù))
-> CPaintManagerUI::SetResourceInstance (實(shí)例句柄與渲染類(lèi)關(guān)聯(lián))
-> ::CoInitialize (初始化COM庫(kù), 為加載COM庫(kù)提供支持)
-> new C360SafeFrameWnd (創(chuàng)建窗口類(lèi))
-> pFrame->Create (注冊(cè)窗口類(lèi)與創(chuàng)建窗口)
-> RegisterSuperclass (注冊(cè)一個(gè)超類(lèi) 即已有一個(gè)窗口類(lèi)的基上再注冊(cè)一個(gè)窗口類(lèi))
-> RegisterWindowClass (注冊(cè)窗口類(lèi))
-> ::CreateWindowEx (創(chuàng)建窗口,此時(shí)觸發(fā) WM_CREATE 消息)
-> HandleMessage ( WM_CREATE消息處理OnCreate)
-> pFrame->CenterWindow (窗口居中顯示)
-> CPaintManagerUI::MessageLoop (處理消息循環(huán))
-> ::CoUninitialize(); (退出程序并釋放COM庫(kù))
②:上面的流程圖是一個(gè)基本的WIN32 程序框架,相對(duì)于 DUILIB 庫(kù),此時(shí)我們應(yīng)關(guān)心的是窗口上的元素是如何建立起來(lái)的。這時(shí)我們應(yīng)關(guān)心WM_CREATE的消息處理函數(shù)OnCreate的實(shí)現(xiàn)
-> C360SafeFrameWnd:: OnCreate
-> m_pm.Init(m_hWnd) (主窗口類(lèi)與窗口句柄關(guān)聯(lián))
-> CControlUI* pRoot = builder.Create (加載XML并動(dòng)態(tài)創(chuàng)建界面無(wú)素,與布局界面元素,核心函數(shù) 單獨(dú)分析 注意:CDialogBuilder 并不是一個(gè)對(duì)話框類(lèi))
-> m_pm.AttachDialog (附加控件數(shù)據(jù)到HASH表中)
-> InitControls (初始化控件)
-> FindControl
-> __FindControlFromNameHash
->pManager->m_mNameHash.Insert(把控件插入到Hash中)
-> m_pm.AddNotifier 增加通知處理
③:接下來(lái)我們應(yīng)關(guān)心的是XML的加載過(guò)程,及XML中的數(shù)是如何與窗口類(lèi)進(jìn)行關(guān)聯(lián)的
-> CDialogBuilder::Create (加載XML文件)
-> m_xml.LoadFromFile
-> CMarkup::LoadFromFile (也可從資源文件中加載::LoadResource)
-> CMarkup::LoadFromMem (把外部XML數(shù)據(jù)加入到內(nèi)存)
-> m_xml.GetRoot (獲得XML 根結(jié)點(diǎn), 開(kāi)始解析XML數(shù)據(jù))
-> "window" (解析根結(jié)點(diǎn)window下的三個(gè)公共元素屬性)
-> "image" pManager->AddImage (加載設(shè)備無(wú)關(guān)位圖并關(guān)聯(lián)到圖像HASH中m_mImageHash.Insert)
-> "font" pManager->AddFont (增加字體)
-> CPaintManagerUI::AddFont (增加字體 并關(guān)聯(lián)字體數(shù)組m_aCustomFonts.Add)
-> "default" (增加默認(rèn)屬性 如:垂直滾動(dòng)條和水平滾動(dòng)條)
-> _Parse (解析具體的控件元素 動(dòng)態(tài)生成控件元素)
-> node.GetName (跳過(guò)已經(jīng)解析過(guò)的三個(gè)元素 "image" "font" "default")
-> _tcscmp (根據(jù)元素的名稱(chēng) 動(dòng)態(tài)生成控件 "Edit" "List" "Text" "Combo" "Label" "Button" "Option" "Slider" "Control" "ActiveX" "Progress" "Container" "TabLayout" "ListHeader" "TileLayout" "DialogLayout" "VerticalLayout" "ListHeaderItem" "ListTextElement" "HorizontalLayout" "ListLabelElement" "ListExpandElement" "ListContainerElement" )
-> pContainer->Add(pControl) (增加控件)
-> m_items.Add (關(guān)聯(lián)于控件數(shù)組中)
-> pControl->SetAttribute 設(shè)置控件屬性
④ 上面的工作完成了XML 數(shù)據(jù)的加載,并動(dòng)態(tài)生成了控件,把控件加載到了控件列表,建立了與控件相關(guān)的HASH 表 。接下來(lái)我們應(yīng)關(guān)心的是控件如何顯示在界面上的。
通過(guò)上面的源碼,我們應(yīng)關(guān)心幾個(gè)核心類(lèi)的關(guān)聯(lián):
->首先產(chǎn)生主窗口類(lèi):C360SafeFrameWnd ,
->在主窗口類(lèi)中放置成變量 CPaintManagerUI m_pm; 與 控件繪制和消息處理關(guān)聯(lián)起來(lái)
->CPaintManagerUI::MessageHandler WM_PAINT
->雙緩存繪圖
-> m_pRoot->DoPaint 繪背景圖
-> CControlUI::DoPaint
-> CRenderEngine 真正的繪圖類(lèi)
-> pPostPaintControl->DoPostPaint 在背景圖上繪制控件
->::BitBlt 把離屏視圖畫(huà)到主屏上
⑤ 當(dāng)界面元素正常顯示后,接下來(lái)我們應(yīng)關(guān)心的是如何處理控件的事件
-> C360SafeFrameWnd:: HandleMessage (應(yīng)用需要處理的消息及處理函數(shù))
-> m_pm.MessageHandler (DUILIB 庫(kù)幫我們處理的消息及相關(guān)的處理函數(shù))
-> CWindowWnd::HandleMessage (應(yīng)用層和 DUILIB都不處理的消息交由系統(tǒng)默認(rèn)處理)