DirectUI的初步分析

來源:互聯網
上載者:User

最近由於項目的需要學習了一下DirectUI方面的東西,主要借鑒的是一個國外程式員寫的代碼(見引用一),看了後發現它更多的是探討一種實現的可能性和思路,和實際應用還是有距離的,不過其實現還是很有意思的。在寫此小結的時候又發現國內一個程式員將這個代碼部分移植到WINCE下的代碼(見引用二),因為平台的差異性要完全開發一個WINCE下的實際代碼還是需要時間的。
由於本人GUI開發做得少,工作中有關這方面的東西主要是提供思路和方法,學習DirectUI的主要目的是為了更新知識學習思路,文章中難免出現錯誤。

一、核心
1、CWindowWnd: 視窗對象類(視窗執行個體對象父類)
2、CDialogBuilder: 建立控制項類,分析指令碼並用遞迴方式(_Parse函數)建立所有控制項執行個體
3、CPaintManagerUI: 視窗訊息及圖形繪製管理器類
4、CGUIRenderEngineUI: 圖形渲染引擎類,在離屏DC中產生最終顯示的圖形,可根據需要擴充多種圖形效果顯示。
5、INotifyUI: 事件通知抽象類別
6、IMessageFilterUI: 訊息過濾抽象類別

二、控制項
CControlUI: 控制項管理抽象父類,父類INotifyUI
1、button
CButtonUI: 按鈕控制項
COptionUI: 選擇按鈕控制項

2、combox
CSingleLinePickUI:
CDropDownUI: 下拉控制項,父類另有CContainerUI和IListOwnerUI

3、decoration
CTitleShadowUI: 陰影製作效果
CListHeaderShadowUI
CSeparatorLineUI
CFadedLineUI

4、edit
CSingleLineEditUI: 單行編輯框控制項
CMultiLineEditUI: 多行編輯框控制項

5、label
CLabelPanelUI: 可設定背景色和文字色的靜態標籤控制項
CGreyTextHeaderUI

6、list
第一種:
CListUI: 清單控制項,包含以下幾個子控制項
(1)CListHeaderItemUI: 列表頭
(2)CListExpandElementUI: 清單項目
第二種:用法不明
CListHeaderUI: 列表頭
CListElementUI: 清單項目,父類另有IListItemUI
CListLabelElementUI: 清單項目,父類CListElementUI
CListTextElementUI: 清單項目
CListFooterUI: 列表尾

7、panel
CTextPanelUI: 父類CLabelPanelUI
CTaskPanelUI:
CNavigatorPanelUI: 導航面板,父類另有IListOwnerUI,包含CNavigatorButtonUI子控制項
CSearchTitlePanelUI:
CImagePanelUI: 圖片顯示
CWarningPanelUI: 警告提示,父類CTextPanelUI
CPaddingPanelUI: 填充欄

8、tab
CTabFolderUI: 父類另有CContainerUI和IListOwnerUI
CTabPageUI: 父類另有CContainerUI

9、toolbar
CToolbarUI: 工具列,包含以下幾個子控制項
(1)CToolButtonUI: 圖形按鈕
(2)CToolSeparatorUI: 分隔字元
(3)CToolGripperUI:  gripper

10、title
CToolbarTitlePanelUI:

11、statusbar
CStatusbarUI: 狀態列,父類另有CContainerUI

12、anim
CAnimJobUI: 動畫顯示類

13、ActiveX
CActiveXUI:

三、容器:
CContainerUI: 容器類,父類CControlUI和IContainerUI。可以認為容器是特殊的控制項(見上面控制項類關於父類的說明),其目的之一是具有容器特性的控制項可以容納其它控制項,這樣可以方便的實現控制項的疊加;目的之二實際的視窗只有一個,對於疊加的控制項必須要進行層次管理才能正確繪圖和事件分發。另外可參見引用三
1、畫布: CCanvasUI(父類CContainerUI),可繪製背景色、畫線、貼圖
CWindowCanvasUI: 父類CCanvasUI
CControlCanvasUI: 父類CCanvasUI
CWhiteCanvasUI: 父類CCanvasUI
CDialogCanvasUI: 父類CCanvasUI
CTabFolderCanvasUI: 父類CCanvasUI
2、布局: 管理不同層次的控制項
CDialogLayoutUI: 父類CContainerUI
CVerticalLayoutUI: 父類CContainerUI
CHorizontalLayoutUI: 父類CContainerUI
CTileLayoutUI: 父類CContainerUI

四、通用
1、script
CMarkup
CMarkupNode

2、language
CUIUtility

3、multi-thread
CriticalSection
AutoCriticalSection
CMutex
CAutoMutex
CEvent
CAutoEvent
CManualEvent

五、主要資料成員
1、CPaintManagerUI
CControlUI* m_pRoot: 如果控制項是疊加的則存放最下層的控制項對象,否則存放第一個建立的控制項對象
CControlUI* m_pFocus: 存放獲得焦點的控制項對象指標
CControlUI* m_pEventHover: 存放當前有滑鼠移進移出事件的控制項對象指標
CControlUI* m_pEventClick: 存放當前有點擊事件的控制項對象指標
CControlUI* m_pEventKey: 存放當前有按鍵事件的控制項對象指標
CStdPtrArray m_aNotifiers: 記錄所有需要事件通知的視窗,根據視窗名稱調用相應的訊息處理函數
CStdPtrArray m_aNameHash: 儲存控制項對象指標hash表(用控制項名稱產生hash值)
CStdPtrArray m_aPostPaint: panel的fade效果
CStdPtrArray m_aMessageFilters: 儲存需要進行訊息過濾的控制項或功能(如動畫類)
CStdPtrArray m_aDelayedCleanup:
CStdPtrArray m_aPreMessages: 預先處理訊息
HWND m_hWndPaint: 控制項布局視窗控制代碼
HDC m_hDcPaint: 控制項布局視窗裝置DC
HDC m_hDcOffscreen: 離屏記憶體DC
HBITMAP m_hbmpOffscreen: 離屏記憶體DC相關聯HBITMAP

2、CControlUI
CPaintManagerUI* m_pManager: 視窗訊息或繪圖管理器
CControlUI* m_pParent: 邏輯上的父視窗(控制項)對象指標
CStdString m_sName: 控制項標識
CStdString m_sText: 控制項顯示標題或顯示指令碼字串
CStdString m_sToolTip: 控制項的Tip資訊

3、CContainerUI
CStdPtrArray m_items: 同一層的控制項對象或控制項對象的子物件,例如canvas上放置的按鈕、combox由edit和list兩個子物件組成,其它還有tab等。具體見CDropDownUI、CTabFolderUI、CNavigatorPanelUI三個類定義

4、CDialogLayoutUI
CStdValArray m_aModes: 用於存放在Layout上絕對座標轉成相對座標(CDialogLayoutUI::RecalcArea)的控制項對象(指標、大小、模式),目的是否為了讓布局上的控制項隨布局變化而變化,能夠正確繪圖???

六、控制項屬性
待完成

七、指令碼例子
<Dialog>
  <WindowCanvas pos=/"0,0,600,800/">
  <DialogLayout pos=/"0,0,600,800/">
    <Button pos=/"390, 30, 490, 58/" text=/"OK/" name=/"ok/"/>
  </DialogLayout>
  </WindowCanvas>
</Dialog>

八、繪圖及事件處理
1、繪圖
STEP01. CWindowWnd::__WndProc: 主視窗程式
STEP02. pThis->HandleMessage: pThis是布局視窗對象指標,並與布局視窗綁定(SetWindowLongPtr)
STEP03. m_pm.MessageHandler: m_pm為CPaintManagerUI唯一執行個體對象
STEP04. CPaintManagerUI::MessageHandler: 處理WM_PAINT
STEP05. m_pRoot->DoPaint: m_pRoot為最下層的控制項對象(在本例中為CWindowCanvasUI控制項,對應指令碼中的WindowCanvas)
STEP06. CCanvasUI::DoPaint: 往畫布上繪製背景色、邊角弧形、浮水印等。
STEP07. CContainerUI::DoPaint: 在最下層具有容器特性的控制項(CWindowCanvasUI控制項)上畫容器內所有控制項(控制項執行個體對象儲存在m_items中)
STEP08. pControl->DoPaint: pControl為控制項對象執行個體之一,利用多態性來調用不同控制項的繪圖方法
STEP09. CButtonUI::DoPaint: 按鈕(對應指令碼中Button)繪圖方法,有下面兩種方法
i)文字方法: CGUIRenderEngineUI::DPaintButton
ii)圖片方法: CGUIRenderEngineUI::DoPaintBitmap
STEP10. 新一輪訊息迴圈

2、事件
STEP01. CWindowWnd::__WndProc:
STEP02. pThis->HandleMessage:
STEP03. m_pm.MessageHandler:
STEP04. CPaintManagerUI::MessageHandler: 處理WM_LBUTTONDOWN
STEP05. CPaintManagerUI::FindControl: 根據滑鼠座標尋找相應控制項對象
STEP06. m_pRoot->FindControl:
STEP07. CContainerUI::FindControl: 在最下層具有容器特性的控制項(CWindowCanvasUI控制項)容器內尋找相應控制項對象
STEP08. CControlUI::FindControl: 在m_items中尋找相對應的控制項對象
STEP09. pControl->Event: pControl為控制項對象執行個體之一,利用多態性來調用不同控制項的事件方法
STEP10. CPaintManagerUI::MessageHandler: 處理WM_LBUTTONUP
STEP11. m_pEventClick->Event: 利用多態性來調用不同控制項的事件方法(m_pEventClick說明見"主要資料成員")
STEP12. CButtonUI::Event: 按鈕(對應指令碼中Button)事件方法
STEP13. CButtonUI::Activate:
STEP14. m_pManager->SendNotify: 傳遞控制項對象指標和觸發事件(文本方式)
STEP15. CPaintManagerUI::SendNotify: 注意以下兩點實現是完成控制和業務分離的關鍵
i)利用重載特性調用註冊的監聽對象(視窗)的訊息處理函數Notify(監聽對象儲存在m_aNotifiers中)
for( int i = 0; i < m_aNotifiers.GetSize(); ++i )
{
    static_cast<INotifyUI*>(m_aNotifiers[i])->Notify(Msg);
}
ii)布局視窗CStartPageWnd的訊息處理,宏定義展開後實際就是重載的Notify函數
DIRECT_BEGIN_NOTIFYMAP(CStartPageWnd)
    PROCESS_BUTTON_CLICK(_T("ok"),OnOk)
    。。。
DIRECT_END_NOTIFYMAP(CStandardPageWnd)
STEP16. CStartPageWnd::OnOk: 控制項訊息處理函數,此處可以加入具體的事務邏輯處理
STEP17. 新一輪訊息迴圈

3、訊息定義(文本)
"click"、"changed"、"link"、"browse"、"itemclick"、"itemselect"、"dropdown"、"itemactivate"、"headerdragging"、"headerclick"、"headerdragged"、"itemexpand"、"itemcollapse"、"windowinit"、"killfocus"、"setfocus"、"timer"

九、疑問
1、Edit、Combox的下拉式清單部分、ScrollBar、Tooltip控制項是建立的實際視窗,這個與DirectUI思路還是有差別的
2、執行個體中有建立一個不進行訊息處理的視窗(CFrameWindowWnd),然後又建立了一個視窗(CStandardPageWnd)用於具體的控制項布局。但是我用一個視窗也能實現,原作者為什麼這樣還不清楚
3、控制項是用文本形式來做標識的,訊息類型是文本形式,是否改成數值型比較好

十、引用
引用一: http://www.viksoe.dk/code/windowless1.htm
引用二: http://directui.googlecode.com/
引用三: http://www.cnblogs.com/cutepig/archive/2010/06/14/1758204.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.