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