1. 程式人生 > >Duilib學習日記1

Duilib學習日記1

Duilib C++

一、Duilib中各個類的簡單介紹
DirectUI意為直接在父窗口上繪圖(Paint on parent dc directly)。即子窗口不以窗口句柄的形式創建(windowless),只是邏輯上的窗口,繪制在父窗口之上。微軟的“DirectUI”技術廣泛的應用於Windows XP、Vista、Windows 7,如瀏覽器左側的TaskPanel,控制面板導航界面,Media Player播放器,即時通訊工具MSN Messager等。

DirectUI好處在於可以很方便的構建高效、絢麗的、非常易於擴展的界面。國外如微軟,國內如騰訊、百度等公司的客戶端產品多采用這種方式來組織界面,從而很好的將界面和邏輯分離,同時易於實現各種超炫的界面效果如換色、換膚、透明等。

DirectUI可以理解為一個輕量級的WPF,可以讓C++做出C#般絢麗的界面。目前國內做DirectUI皮膚庫的公司主要有兩家:第一家是UIPower(即Skin++的公司),網址www.uipower.com,其DirectUI產品網站www.directui.com,做的很專業;另一家是UIEASY,網址www.uieasy.com,一個輕量級皮膚庫DSkinLite。但是,網上關於DirectUI的技術文章卻很少;早在 6/26/2005,一個國外的程序員就已經寫了一個開源的DirectUI例子,應該算是國內所有directui界面庫的起源了,網址http://www.viksoe.dk/code/windowless1.htm,探討一種實現的可能性和思路,和實際應用雖有一定距離,不過卻是一個很好的學習資料。再後來,一個國內的程序員“當個傻瓜蛋”,基於此代碼,進行重構和修正Bug,並放到了google上開源,網址http://code.google.com/p/duilib/,下載地址svn checkout http://duilib.googlecode.com/svn/trunk/ duilib-read-only。

本人通過學習這個duilib的源代碼,學到了很多知識、思路和經驗,分享給看到此文的朋友,共同探討DirectUI技術,並歡迎大家加入到開發開源DirectUI皮膚庫的行列當中。分析難免有誤,見諒!

一、核心類

  1. CWindowWnd,窗口對象管理父類,主要作用:

1) 創建窗口。

2) 窗口消息過程處理。

3) 提供窗口子類化與超類化接口。

  1. CDialogBuilder,控件布局類,主要作用:

1) 讀取XML腳本,分析腳本,構建控件樹。

2) 創建控件對象。

  1. CPaintManagerUI,窗口消息及圖形繪制管理器類,與窗口綁定,主要作用:

1) 繪制控件。

2) 消息管理。

3) 事件通知。

  1. INotifyUI,事件通知抽象類,主要作用:

1) 重載Notify虛函數,處理事件通知。

二、控件類

  1. CControlUI,控件管理父類,主要作用:

1) 控件的通用基類,提供控件通用屬性管理。

  1. CLabelUI,靜態標簽類,父類CControlUI。

  2. CButtonUI,按鈕類,父類CLabelUI。

  3. COptionUI,選擇按鈕類,父類CButtonUI。

  4. CTextUI,靜態文本類,父類CLabelUI。

  5. CProgressUI,進度條類,父類CLabelUI。

  6. CSliderUI,父類CProgressUI。

  7. CEditUI,編輯框類,父類CLabelUI。

  8. CListUI,列表框類,父類CVerticalLayoutUI、IListUI。

1) CListHeaderUI,父類CHorizontalLayoutUI。

2) CListHeaderItemUI,列表頭類,父類CControlUI。

3) CListTextElementUI,類表文本類,父類CListLabelElementUI。

4) CListLabelElementUI,父類CListElementUI。

  1. CComboUI,組合框類,父類CContainerUI、IListOwnerUI。

  2. CActiveXUI,ActiveX控件類,父類CControlUI、 IMessageFilterUI。

  3. CContainerUI,容器類,父類CControlUI、IContainerUI。

  4. CTabLayoutUI,選項頁布局類,父類CContainerUI。

  5. CTileLayoutUI,父類CContainerUI。

  6. CDialogLayoutUI,對話框布局類,父類CContainerUI。、

  7. CVerticalLayoutUI,垂直布局類,父類CContainerUI。

  8. CHorizontalLayoutUI,水平布局類,父類CContainerUI。

  9. CListExpandElementUI,父類CListTextElementUI。

  10. CListContainerElementUI,父類CContainerUI、IListItemUI。

三、輔助類

  1. CStdPtrArray,指針數組。
  1. CStdValArray,數據數組。

  2. CStdString,字符串數組。

  3. CStdStringPtrMap,字符串指針映射數組。

二、DUiLib 源碼分析——第一篇UIManager
本篇分析一下源文件
UIManager.h/UIManager.cpp

CPaintManagerUI
成員變量

窗體句柄
o---m_hWndPaint 要CPaintManagerUI進行Direct繪圖操作的窗體句柄
o---m_hwndTooltip 提示窗口句柄
o---m_hInstance 當前管理的Instance實例
o---m_hResourceInstance 當前管理的資源DLL Instance實例
o---m_pStrResourcePath 當前使用的資源路徑
o---m_pStrResourceZip 當前使用的資源壓縮包文件全稱

------------------------------------------------------CPaintManagerUI使用的資源
繪圖設備
o---m_hDcPaint 直接繪制到窗體的DC(為窗體的整個區域包括費客戶區)
o---m_hDcOffscreen 內存緩沖區繪圖DC
o---m_hDcBackground 背景繪制(支持AlphaBackground時使用)
位圖
o---m_hbmpOffscreen m_hDcPaint的後臺作圖畫布
o---m_hbmpBackground 背景圖片bmp

------------------------------------------------------CPaintManagerUI用到的信息
o---m_ToolTip 提示消息
typedef struct tagTOOLINFOA {
UINT cbSize; //該結構體的大小 sizeof(TOOLINFO)
UINT uFlags; //附加標識類信息
HWND hwnd; //消息接受的窗體
UINT_PTR uId; //控件ID
RECT rect; //消息產生的區域位置
HINSTANCE hinst; //消息接收的實例
LPSTR lpszText; //提示消息
LPARAM lParam; //IE3.0以上的版本有該屬性
void *lpReserved; //NT5.0以上的版本有該屬性 附加信息
} TOOLINFO
標識類信息
o---m_bShowUpdateRect 是否顯示更新區域
o---m_bFirstLayout 是否是首個布局
o---m_bUpdateNeeded 是否需要更新界面
o---m_bFocusNeeded 是否需要焦點
o---m_bOffscreenPaint 是否需要開雙緩存繪圖
o---m_bAlphaBackground 窗體背景是否需要支持Alpha通道(如png圖片的半透明效果)
o---m_bMouseTracking 是否需要支持鼠標追蹤
o---m_bMouseCapture 是否需要支持鼠標捕獲

控件信息
o---m_pRoot xml根節點解析成的對象,通常為各種Window
o---m_pFocus 處於獲得焦點狀態的控件
o---m_pEventHover 處於鼠標懸停狀態的控件
o---m_pEventClick 被鼠標點擊的控件
o---m_pEventKey 接收鍵盤輸入的控件

位置記錄信息
o---m_pLastMousePos 鼠標最新的位置
o---m_szMinWindow 設置窗體可以調整到的最小大小
o---m_szMaxWindow 窗體可以調整到的最大大小
o---m_szInitWindowSize 窗體初始化是的大小
o---m_rcSizeBox 窗體外邊框區域的大小
o---m_szRoundCorner 窗體四角的圓角弧度
o---m_rcCaption 窗體標題欄區域大小
o---m_uTimerID 當前定時器ID

集合類信息
o---m_aNotifiers 能夠接收通知的對象集合
o---m_aTimers 定時器集合
o---m_aPreMessage 預處理消息集合
o---m_aPreMessageFilters 預處理消息過濾器集合
o---m_aMessageFilters 消息過濾器集合
o---m_aPostPaintControls 發送繪制請求的控件集合
o---m_aDelayedCleanup 延遲清理的對象集合
o---m_aAsyncNotify 異步通知消息集合
o---m_mNameHash 名稱HashMap
o---m_mOptionGroup 選項組Map

xml對應資源
o---m_pParentResourcePM 上級(父類)資源的PaintManagerUI繪圖管理器
o---m_dwDefaultDisabledColor 默認失效狀態顏色
o---m_dwDefaultFontColor 默認字體顏色
o---m_dwDefaultLinkFontColor 默認超鏈接字體顏色
o---m_dwDefaultLinkHoverFontColor默認超鏈接鼠標懸停狀態的字體顏色
o---m_dwDefaultSelectedBkColor 默認選中狀態背景色
o---m_DefaultFontInfo 默認字體信息
TFontInfo{
hFont 該字體的句柄
sFontName 字體名稱
iSize 字號
bBold 是否粗體
bUnderline 是否有下劃線
bItalic 是否為斜體
TEXTMETRIC tm 該字體的TEXTMETRIC信息
}
o---m_aCustonFonts 自定義字體資源集合
o---m_mImageHash 圖片資源HashMap
o---m_DefaultAttrHash DefaultAttr資源HashMap

私有方法
將所有的控件添加到m_mNameHash哈希表中
o---static CControlUI CALLBACK __FindControlFromNameHash(CControlUI pThis, LPVOID pData);
計算控件數量
o---static CControlUI CALLBACK __FindControlFromCount(CControlUI pThis, LPVOID pData);
根據點是否在區域中,查詢控件
o---static CControlUI CALLBACK __FindControlFromPoint(CControlUI pThis, LPVOID pData);
通過Tab信息查詢控件
o---static CControlUI CALLBACK __FindControlFromTab(CControlUI pThis, LPVOID pData);
從快照中查詢控件
o---static CControlUI CALLBACK __FindControlFromShortcut(CControlUI pThis, LPVOID pData);
查找需要更新的控件
o---static CControlUI CALLBACK __FindControlFromUpdate(CControlUI pThis, LPVOID pData);
通過名稱比較查詢控件
o---static CControlUI CALLBACK __FindControlFromName(CControlUI pThis, LPVOID pData);

公開方法
繪圖管理器的初始化(m_hWndPaint,m_hDcPaint賦值,在預處理消息中加入管理器)
+---void Init(HWND hWnd);
當前需要更新界面
+---void NeedUpdate();
指定區域失效
+---void Invalidate(RECT& rcItem);
獲取繪圖設備DC
+---HDC GetPaintDC() const;
獲取繪圖的窗口句柄
+---HWND GetPaintWindow() const;
獲取提示窗體句柄
+---HWND GetTooltipWindow() const;
獲取當前鼠標的位置
+---POINT GetMousePos() const;
獲取客戶區大小
+---SIZE GetClientSize() const;
獲取窗體初始化時的大小
+---SIZE GetInitSize();
設置窗體初始化大小
+---void SetInitSize(int cx, int cy);
獲取窗體的邊框區域大小
+---RECT& GetSizeBox();
設置窗體的邊框區域大小
+---void SetSizeBox(RECT& rcSizeBox);
獲取標題區域位置
+---RECT& GetCaptionRect();
設置標題區域位置
+---void SetCaptionRect(RECT& rcCaption);
獲取窗體四角的圓角弧度
+---SIZE GetRoundCorner() const;
設置窗體四角的圓角弧度
+---void SetRoundCorner(int cx, int cy);
獲取窗體可以調整到的最小大小
+---SIZE GetMinInfo() const;
設置窗體可以調整到的最小大小
+---void SetMinInfo(int cx, int cy);
獲取窗體可以調整到的最大大小
+---SIZE GetMaxInfo() const;
設置窗體可以調整到的最大大小
+---void SetMaxInfo(int cx, int cy);
窗體的不透明度(0完全透明-255完全不透明)
+---void SetTransparent(int nOpacity);
設置繪圖是否支持透明處理
+---void SetBackgroundTransparent(bool bTrans);
是否顯示更新區域
+---bool IsShowUpdateRect() const;
設置是否顯示更新
+---void SetShowUpdateRect(bool show);
獲取當前管理的實例句柄
+---static HINSTANCE GetInstance();
獲得當前運行的實例的路徑
+---static CStdString GetInstancePath();
獲得當前的工作路徑
+---static CStdString GetCurrentPath();
獲取資源DLL的實例句柄
+---static HINSTANCE GetResourceDll();
獲取資源的路徑(以"\"結尾)
+---static const CStdString& GetResourcePath();
獲得Zip資源的路徑
+---static const CStdString& GetResourceZip();
設置實例句柄
+---static void SetInstance(HINSTANCE hInst);
設置當前的工作路徑
+---static void SetCurrentPath(LPCTSTR pStrPath);
設置當前的DLL資源的實例句柄
+---static void SetResourceDll(HINSTANCE hInst);
設置資源所在文件夾路徑
+---static void SetResourcePath(LPCTSTR pStrPath);
設置Zip資源的路徑(包括Zip文件名)
+---static void SetResourceZip(LPCTSTR pStrZip);
設置使用上級資源的繪圖管理器
+---bool UseParentResource(CPaintManagerUI pm);
獲得上級資源繪圖管理器
+---CPaintManagerUI
GetParentResource() const;
獲取禁用狀態的默認顏色
+---DWORD GetDefaultDisabledColor() const;
設置禁用狀態的默認顏色
+---void SetDefaultDisabledColor(DWORD dwColor);
獲取字體默認顏色
+---DWORD GetDefaultFontColor() const;
設置字體默認顏色
+---void SetDefaultFontColor(DWORD dwColor);
設置鏈接文字的默認字體顏色
+---DWORD GetDefaultLinkFontColor() const;
獲取鏈接文字的默認顏色
+---void SetDefaultLinkFontColor(DWORD dwColor);
獲取鼠標懸停與超鏈上的默認字體顏色
+---DWORD GetDefaultLinkHoverFontColor() const;
獲取鼠標懸停與超鏈上的默認字體顏色
+---void SetDefaultLinkHoverFontColor(DWORD dwColor);
獲取選中狀體的默認背景顏色
+---DWORD GetDefaultSelectedBkColor() const;
設置選中狀態的默認背景顏色
+---void SetDefaultSelectedBkColor(DWORD dwColor);
獲取默認使用的字體信息
+---TFontInfo GetDefaultFontInfo();
設置默認使用的字體信息
+---void SetDefaultFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
獲取用戶自定義字體的數量(一般對應xml中Font的數量)
+---DWORD GetCustomFontCount() const;
向字體數組列表追加字體資源
+---HFONT AddFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
向字體數組列表中插入字體資源
+---HFONT AddFontAt(int index, LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
獲取數組中指定下標的字體對象句柄
+---HFONT GetFont(int index);
從字體數組中獲取指定配置的字體對象句柄
+---HFONT GetFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
字體數組集合中是否存在字體對象
+---bool FindFont(HFONT hFont);
字體數組集合中是否存在指定配置的字體對象
+---bool FindFont(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
獲得字體對象的
+---int GetFontIndex(HFONT hFont);
根據指定的配置信息查詢字體索引
+---int GetFontIndex(LPCTSTR pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic);
從字體數組列表中移除字體對象
+---bool RemoveFont(HFONT hFont);
從字體數組列表中移除指定位置的字體信息
+---bool RemoveFontAt(int index);
清空字體數組列表
+---void RemoveAllFonts();
通過字體數組索引查找字體信息
+---TFontInfo
GetFontInfo(int index);
通過字體對象句柄獲取字體信息
+---TFontInfo GetFontInfo(HFONT hFont);
根據圖像路徑查找圖像信息
+---const TImageInfo
GetImage(LPCTSTR bitmap);
根據名稱,類型,遮罩色 查詢 圖像信息
+---const TImageInfo GetImageEx(LPCTSTR bitmap, LPCTSTR type = NULL, DWORD mask = 0);
添加圖像
+---const TImageInfo
AddImage(LPCTSTR bitmap, LPCTSTR type = NULL, DWORD mask = 0);
添加圖像
+---const TImageInfo AddImage(LPCTSTR bitmap, HBITMAP hBitmap, int iWidth, int iHeight, bool bAlpha);
根據圖像名稱移除圖像
+---bool RemoveImage(LPCTSTR bitmap);
移除全部圖像
+---void RemoveAllImages();
添加控件的默認配置信息(如button)
+---void AddDefaultAttributeList(LPCTSTR pStrControlName, LPCTSTR pStrControlAttrList);
根據控件名稱查詢該類控件的默認配置
+---LPCTSTR GetDefaultAttributeList(LPCTSTR pStrControlName) const;
移除指定控件類型名稱的默認配置
+---bool RemoveDefaultAttributeList(LPCTSTR pStrControlName);
獲取默認配置信息列表
+---const CStdStringPtrMap& GetDefaultAttribultes() const;
清空默認配置信息列表
+---void RemoveAllDefaultAttributeList();
將對話框控件附加到當前的管理器中
+---bool AttachDialog(CControlUI
pControl);
控件初始化
+---bool InitControls(CControlUI pControl, CControlUI pParent = NULL);
控件回收
+---void ReapObjects(CControlUI* pControl);

        添加控件到指定的選項組

+---bool AddOptionGroup(LPCTSTR pStrGroupName, CControlUI pControl);
查詢指定選項組名稱中的全部選項
+---CStdPtrArray
GetOptionGroup(LPCTSTR pStrGroupName);
從指定控件中移除指定選項組名稱的選項組
+---void RemoveOptionGroup(LPCTSTR pStrGroupName, CControlUI* pControl);
清空全部選項組列表
+---void RemoveAllOptionGroups();

        獲取焦點狀態的控件

+---CControlUI GetFocus() const;
設置控件為獲得焦點狀態
+---void SetFocus(CControlUI
pControl);
設置控件為需要繪制焦點
+---void SetFocusNeeded(CControlUI* pControl);

        設置下一個獲得Tab鍵會獲得焦點的控件,Tab是否繼續往下走

+---bool SetNextTabControl(bool bForward = true);

        為指定控件以及其子控件設置定時器

+---bool SetTimer(CControlUI pControl, UINT nTimerID, UINT uElapse);
移除指定控件上的指定編號的定時器
+---bool KillTimer(CControlUI
pControl, UINT nTimerID);
清空所有的定時器
+---void RemoveAllTimers();

        設置窗體接受鼠標事件

+---void SetCapture();
釋放窗體捕獲鼠標事件
+---void ReleaseCapture();
判斷窗體是否接受鼠標事件
+---bool IsCaptured();

        添加控件到通知集合中

+---bool AddNotifier(INotifyUI pControl);
將控件從通知集合中移除
+---bool RemoveNotifier(INotifyUI
pControl);
發送同步/異步通知
+---void SendNotify(TNotifyUI& Msg, bool bAsync = false);
構建同步或異步通知並發送
+---void SendNotify(CControlUI* pControl, LPCTSTR pstrMessage, WPARAM wParam = 0, LPARAM lParam = 0, bool bAsync = false);

        向預處理消息過濾器鏈中添加消息過濾器

+---bool AddPreMessageFilter(IMessageFilterUI pFilter);
從預處理消息過濾器鏈合中移除指定的消息過濾器
+---bool RemovePreMessageFilter(IMessageFilterUI
pFilter);

        向消息過濾器鏈中添加消息過濾器

+---bool AddMessageFilter(IMessageFilterUI pFilter);
從消息過濾器鏈中移除消息過濾器
+---bool RemoveMessageFilter(IMessageFilterUI
pFilter);
獲取發送需要繪制的控件的數量
+---int GetPostPaintCount() const;
向繪制請求集合中添加要繪制的控件
+---bool AddPostPaint(CControlUI pControl);
從繪制請求集合中移除指定的控件
+---bool RemovePostPaint(CControlUI
pControl);
將繪制請求控件插入到繪制請求集合的指定位置
+---bool SetPostPaintIndex(CControlUI pControl, int iIndex);
向延遲清理集合中添加需要延遲清理的對象
+---void AddDelayedCleanup(CControlUI
pControl);
獲取根節點控件
+---CControlUI GetRoot() const;
從根節點開始查找指定點所在的控件
+---CControlUI
FindControl(POINT pt) const;
從指定節點開始查找指定點所在的控件
+---CControlUI FindControl(CControlUI pParent, POINT pt) const;
從根節點開始,查找指定名稱的控件
+---CControlUI FindControl(LPCTSTR pstrName);
從指定節點開始查找指定名稱的控件
+---CControlUI
FindControl(CControlUI* pParent, LPCTSTR pstrName);

        消息循環,非遊戲框架消息泵,無法利用無消息的空閑時間            

+---static void MessageLoop();
消息翻譯,在Win32原有的消息轉換基礎上,將需要自己處理的消息轉發給消息預處理器
+---static bool TranslateMessage(const LPMSG pMsg);
消息預處理器
1.消息預處理過濾(消息預處理過濾器集合對消息進行過濾處理)
2.檢查是否按下Tab鍵,設置下一個獲得焦點的控件
3.處理Alt+Shortcut Key按下後的控件獲得焦點和激活的設置
4.檢查是否有系統鍵消息,有則發送獲得焦點的控件的事件
+---bool PreMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes);



消息處理器(核心處理器)
1.消息過濾
2.檢查Custom消息並處理
3.檢查是否有WM_CLOSE消息並處理
4.處理WM_ERASEBKGND(不允許進行背景擦除,防止閃爍)
5.繪制處理(核心)
5.1做延遲繪圖判斷,當前是否有 窗體大小調整的操作,或者是否需要初始化窗體
5.2設置焦點控件
5.3如果開啟雙緩存繪圖,采用雙緩存方式繪圖,否則采用標準繪圖方式繪圖
5.4
6.處理客戶區的繪制WM_PRINTCLIENT
7.接到WM_GETMINMAXINFO消息後向系統提交該窗體可調整大小的最小和最大限制
8.窗體大小改變時,向焦點控件發送改變大小消息並設置窗體需要更新
9.處理定時器消息,向定時器集合中廣播定時消息
10.處理鼠標懸停
10.1向鼠標懸停的控件發送鼠標懸停消息
10.2如果當前控件有提示消息,創建消息提示窗體
11.處理鼠標離開事件,關閉消息提示框,發送鼠標離開消息,取消鼠標的追蹤
12.鼠標移動時,開始追蹤鼠標
12.1處理鼠標移動時,鼠標在控件上進入,移動,懸停和離開的消息
13.處理鼠標左鍵按下的消息設定活動的焦點的控件
14.鼠標雙擊事件處理,向需要接收鼠標雙擊事件的控件發送雙擊事件
15.鼠標左鍵擡起時,向上次接收到點擊消息的控件發送鼠標左鍵擡起的消息
16.鼠標右鍵按下時,向需要接收鼠標右鍵按下的控件發送右鍵按下消息
17.鼠標右鍵快捷菜單消息,將該消息通知給上次點擊過的按鈕
18.滾輪消息時,象鼠標所在的控件發送滾輪消息
19.WM_CHAR 消息時,向獲得焦點的控件發送該消息
20.鍵盤按下時,向焦點控件發送該鍵盤消息,並設定焦點控件為鍵盤消息控件
21.鍵盤按鍵擡起時,向事鍵盤消息控件發送該事件
22.設定鼠標光標消息時,獲得光標所在控件接收該消息
23.通知消息到來時,加OCM_BASE後發送通知消息
24.命令消息到來,加OCM_BASE後發送消息
25.WM_CTLCOLOREDIT,STATIC消息到來後,加OCM_BASE後發送消息
+---bool MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes);

三、DUiLib 源碼分析——第二篇UIBase
本篇分析一下源文件
UIBase.h/UIBase.cpp
UILib的基礎類的定義源文件
包括UI中常用宏的封裝、代碼調試宏、
繪圖常用的各種數據結構,以及UILib中的窗體類等

UI裏的宏
窗體樣式宏
+---UI_WNDSTYLE_CONTAINER 容器樣式,無任何樣式
+---UI_WNDSTYLE_FRAME UI標準框架窗體樣式(標題欄、邊框、圖標、標題、最大、最小按鈕、關閉按鈕)
+---UI_WNDSTYLE_CHILD UI窗體子控件樣式
+---UI_WNDSTYLE_DIALOG UI對話框窗體樣式
擴展窗體樣式宏
+---UI_WNDSTYLE_EX_FRAME 窗體客戶區凹陷樣式
+---UI_WNDSTYLE_EX_DIALOG 工具欄窗口樣式+模式對話框樣式
類樣式宏
+---UI_CLASSSTYLE_CONTAINER 類容器樣式
+---UI_CLASSSTYLE_FRAME 水平、垂直大小改變時繪制
+---UI_CLASSSTYLE_CHILD 水平、垂直大小改變時繪制、支持雙擊事件、保存窗體位圖
+---UI_CLASSSTYLE_DIALOG 水平、垂直大小改變時繪制、支持雙擊事件、保存窗體位圖

ASSERT(expr) 判斷表達式是否為NULL或FALSE
TRACE(LPSTSTR pstrFormat,...)
在Debug輸出窗口打印格式化字符串
TRACEMSG(UINT uMsg) 返回指定消息的16進制表示

基礎類
STRINGorID 用於構建資源名稱或資源ID號
x---LPCTSTR m_lpstr;
+---STRINGorID(LPCTSTR lpString)
+---STRINGorID(UINT nID)

CPoint 點的封裝類,支持LPARAM構建點
+---CPoint();
+---CPoint(const POINT& src);
+---CPoint(int x, int y);
+---CPoint(LPARAM lParam);

CSize 大小封裝
+---CSize();
+---CSize(const SIZE& src);
+---CSize(const RECT rc);
+---CSize(int cx, int cy);

CRect 區域封裝
+---CRect();
+---CRect(const RECT& src);
+---CRect(int iLeft, int iTop, int iRight, int iBottom);
+---int GetWidth() const 獲取寬度
+---int GetHeight() const 獲取高度
+---void Empty() 清空
+---bool IsNull() const 是否為Empty,IsEmpty
+---Join(const RECT& rc) 支持區域合並
+---Normalize() 正規化(使得left<right,top<bottom)
+---Offset(int cx, int cy) 區域偏移(移動)操作
+---Inflate(int cx, int cy) 區域膨脹
+---Deflate(int cx, int cy) 區域收縮
+---Union(CRect& rc) 區域並操作

CStdPtrArray 指針數組類
x---LPVOID* m_ppVoid 數據指針
x---int m_nCount 指針數量
x---int m_nAllocated 內存已分配大小

+---void Empty()                        清空記錄
+---void Resize(int iSize)              重新分配內存大小(註意:之前的記錄丟失)
+---bool IsEmpty() const                是否為空數組
+---int Find(LPVOID iIndex) const       查詢指定元素的索引號
+---bool Add(LPVOID pData)              在指針集合中添加新數據
+---bool SetAt(int iIndex, LPVOID pData)設置指定索引號處的新數據
+---bool InsertAt(int iIndex, LPVOID pData)在指定的索引號處插入數據
+---bool Remove(int iIndex)             移除指定索引號得數據
+---int GetSize() const                 獲取指針數量
+---LPVOID* GetData()                   獲取全部的數據
+---LPVOID GetAt(int iIndex) const      查詢索引號所對應的元素
+---LPVOID operator[] (int nIndex) const支持[]查找元素

CStdValArray 自定義數據長度數組類
x---LPBYTE m_pVoid 指針數據
x---int m_iElementSize 元素大小
x---int m_nCount 元素數量
x---int m_nAllocated 當前分配的可用容量


+---CStdValArray(int iElementSize, int iPreallocSize = 0)
                                        指定元素大小,預分配數量               
+---void Empty()                        清空數據
+---bool IsEmpty() const                是否為空數組
+---bool Add(LPCVOID pData)             追加數據
+---bool Remove(int iIndex)             移除指定索引號得數據
+---int GetSize() const                 獲取當前保存元素的個數
+---LPVOID GetData()                    獲取數據
+---LPVOID GetAt(int iIndex) const      獲取指定索引號處的數據
+---LPVOID operator[] (int nIndex) const支持[]查找元素

CStdString 字符串類
x---LPTSTR m_pstr; 字符指針
x---TCHAR m_szBuffer[MAX_LOCAL_STRING_LEN + 1];字符緩沖區


+---CStdString();                       初始化字符串類
+---CStdString(const TCHAR ch);         
+---CStdString(const CStdString& src);
+---CStdString(LPCTSTR lpsz, int nLen = -1);長度為-1由程序自己判斷長度
+---void Empty();                       清空字符串
+---int GetLength() const;              獲取字符串長度
+---bool IsEmpty() const;               字符串是否為空串
+---TCHAR GetAt(int nIndex) const;      獲取指定位置處的字符
+---void Append(LPCTSTR pstr);          字符串追加操作
+---void Assign(LPCTSTR pstr, int nLength = -1);分配內存賦值
+---LPCTSTR GetData();                  獲取字符串指針
+---void SetAt(int nIndex, TCHAR ch);   在指定索引處設置字符
+---int Compare(LPCTSTR pstr) const;    字符串比較
+---int CompareNoCase(LPCTSTR pstr) const;字符串忽略大小寫比較
+---void MakeUpper();                   字符串轉換為大小
+---void MakeLower();                   字符串轉換為小寫
+---CStdString Left(int nLength) const; 從左邊截取指定長度的子串
+---CStdString Mid(int iPos, int nLength = -1) const;
                                        截取中間字符串
+---CStdString Right(int nLength) const;從右開始截取指定長度的字符串

+---int Find(TCHAR ch, int iPos = 0) const;
                                        從指定位置開始尋找匹配字符的位置
+---int Find(LPCTSTR pstr, int iPos = 0) const;
                                        重指定位置開始尋找匹配字符串的位置
+---int ReverseFind(TCHAR ch) const;    反向查詢字符位置
+---int Replace(LPCTSTR pstrFrom, LPCTSTR pstrTo);
                                        將匹配的字符子串用指定字符串替換

+---int __cdecl Format(LPCTSTR pstrFormat, ...);
                                        最長63位的字符串格式化
+---int __cdecl SmallFormat(LPCTSTR pstrFormat, ...);
                                        一次格式化1024長度的字符串格式化

TITEM結構
o---CStdString Key 鍵
o---LPVOID Data 值
o---struct TITEM* pNext 下一個TITEM結構體指針

CStdStringPtrMap
x---TITEM** m_aT; TITEM雙指針
x---int m_nBuckets; 容器容量
+---CStdStringPtrMap(int nSize = 83); 構建字符串Map集合
+---void Resize(int nSize = 83); 重新分配集合大小
+---LPVOID Find(LPCTSTR key) const; 更具鍵查詢字符串指針
+---bool Insert(LPCTSTR key, LPVOID pData);插入數據
+---LPVOID Set(LPCTSTR key, LPVOID pData);設置指定鍵的數據
+---bool Remove(LPCTSTR key); 通過鍵移除數據
+---int GetSize() const; 獲取大小
+---LPCTSTR GetAt(int iIndex) const; 獲取指定索引處得字符串
+---LPCTSTR operator[] (int nIndex) const;通過下標獲取字符串

CWindowWnd
x---HWND m_hWnd 窗體句柄,初始化為NULL
x---WNDPROC m_OldWndProc Win32窗口過程,默認為DefWindowProc
x---bool m_bSubclassed 是否子類化,默認為false

            獲取窗口類名稱,子類必須實現該純虛函數
o---virtual LPCTSTR GetWindowClassName() const = 0;
            獲取父類名稱,用以子類化
o---virtual LPCTSTR GetSuperClassName() const;
            獲得類樣式
o---virtual UINT GetClassStyle() const;
            消息處理函數
o---virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
            窗體銷毀前最後的處理工作
o---virtual void OnFinalMessage(HWND hWnd);
            窗口過程回調函數
o---static LRESULT CALLBACK __WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
            控件過程回調函數
o---static LRESULT CALLBACK __ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
---------------------------------------------------------------------

+---CWindowWnd();
            獲取窗口句柄
+---HWND GetHWND() const;
            獲取窗口句柄
+---operator HWND() const;
            註冊窗口過程
            1.調用GetClassStyle獲取樣式信息
            2.調用繪圖管理器的靜態函數獲取實例CPaintManagerUI::GetInstance()
            3.調用GetWindowClassName()獲取要註冊的類名稱
+---bool RegisterWindowClass();
            通過已存在的窗體作為父類註冊窗口類
+---bool RegisterSuperclass();
            窗口創建
+---HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, const RECT rc, HMENU hMenu = NULL);
            創建窗口
            1.如果存在父類名,就用註冊父類來創建
            2.不存在父類名,進行正常的窗口註冊
            3.以上註冊成功後,創建窗口
+---HWND Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT, HMENU hMenu = NULL);
            窗口子類化
+---HWND Subclass(HWND hWnd);
            卸載窗口子類化
+---void Unsubclass();
            顯示窗口
+---void ShowWindow(bool bShow = true, bool bTakeFocus = true);
            顯示模式窗口
+---bool ShowModal();
            關閉窗口
+---void Close();
            窗口居中,如果為子窗口,則居於父窗口的中央
+---void CenterWindow();
            通過資源ID號設置圖標
+---void SetIcon(UINT nRes);
            發送UI同步消息
+---LRESULT SendMessage(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0L);
            投遞UI異步消息
+---LRESULT PostMessage(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0L);
            調整客戶區大小
+---void ResizeClient(int cx = -1, int cy = -1);

CWaitCursor 等待光標
x---HCURSOR m_hOrigCursor 替換前光標
+---CWaitCursor() 設置成等待光標
+---~CWaitCursor() 還原為之前的光標
四、DUILibxml配置

DUILibxml配置項
根節點 子類 屬性 類型
Window
--------Image 圖片信息
o------name string
o------restype string
o------mask unsigned long#
--------Font 字體信息
o------name string
o------size long
o------bold bool
o------underline bool
o------default bool
--------Default 默認Attribute屬性
             o------name                            string
             o------value                           string

root(Window屬性)
o--size 窗體初始化大小 SIZE(int cx, int cy)
o--sizebox 窗體區域 RECT(long left, long top, long right,long bottom)
o--caption 窗體標題欄區域 RECT(long left, long top, long right,long bottom)
o--roundcorner 圓角大小 SIZE(int cx, int cy)
o--mininfo 窗體最小大小 SIZE(int cx, int cy)
o--maxinfo 窗體最大大小 SIZE(int cx, int cy)
o--showdirty 窗體顯示 bool [true|false]
o--alpha 窗體透明度 int
o--bktrans 背景是否支持透明 bool [true|false]
o--disabledfontcolor 無效字體顏色 string #RRGGBBAA
o--defaultfontcolor 默認字體顏色 string #RRGGBBAA
o--linkfontcolor 鏈接正常字體色 string #RRGGBBAA
o--linkhoverfontcolor鏈接懸停字體色 string #RRGGBBAA
o--selectedcolor 字體被選後顏色 string #RRGGBBAA

公共資源
Image
|------o file/res string
|------o restype string
|------o dest RECT(long left, long top, long right,long bottom)
|------o source RECT(long left, long top, long right,long bottom)
|------o corner RECT(long left, long top, long right,long bottom)
|------o mask string #FFFFFFFF
|------o fade byte
|------o hole bool [true|false]
|------o xtiled bool [true|false]
|------o ytiled bool [true|false]
使用說明:
// 1、aaa.jpg
// 2、file=‘aaa.jpg‘ res=‘‘ restype=‘0‘ dest=‘0,0,0,0‘ source=‘0,0,0,0‘ corner=‘0,0,0,0‘
// mask=‘#FF0000‘ fade=‘255‘ hole=‘false‘ xtiled=‘false‘ ytiled=‘false‘

Font
Default

控件Control

控件名稱 類

控件基類
Control CControlUI
|------o pos RECT(long left, long top, long right,long bottom)
|------o relativepos (int nMoveXPercent, int nMoveYPercent,int nZoomXPercent,int nZoomYPercent)
|------o padding RECT(long left, long top, long right,long bottom)
|------o bkcolor/bkcolor1 string #RRGGBBAA
|------o bkcolor2 string #RRGGBBAA
|------o bkcolor3 string #RRGGBBAA
|------o bordercolor string #RRGGBBAA
|------o focusbordercolor string #RRGGBBAA
|------o bordersize int
|------o borderround SIZE(int x, int y)
|------o bkimage Image 屬性
|------o width int
|------o height int
|------o minwidth int
|------o minheight int
|------o maxwidth int
|------o maxheight int
|------o name string
|------o text string
|------o tooltip string
|------o userdata string
|------o enabled bool [true|false]
|------o mouse bool [true|false]
|------o visible bool [true|false]
|------o float bool [true|false]
|------o shortcut TCHAR
|------o menu bool [true|false]

容器
Container CContainerUI
|------o inset RECT(long left, long top, long right,long bottom)
|------o mousechild bool [true|false]
|------o vscrollbar bool [true|false]
|------o hscrollbar bool [true|false]
|------o childpadding int

布局管理器
VerticalLayout CVerticalLayoutUI : public CContainerUI
|------o sepheight int
|------o sepimm bool [true|false]
|------o CContainerUI::SetAttribute(pstrName, pstrValue)

HorizontalLayout CHorizontalLayoutUI : public CContainerUI
|------o sepwidth int
|------o sepimm bool [true|false]
|------o CContainerUI::SetAttribute(pstrName, pstrValue)

DialogLayout CDialogLayoutUI : public CContainerUI
|------o CContainerUI::SetAttribute(pstrName, pstrValue)

TileLayout CTitleLayoutUI : public CContainerUI
|------o columns int
|------o CContainerUI::SetAttribute(pstrName, pstrValue)

TabLayout CTabLayoutUI : public CContainerUI
|------o selectedid int
|------o CContainerUI::SetAttribute(pstrName, pstrValue)

Edit CEditUI : public CLabelUI
|------o readonly bool [true|false]
|------o password bool [true|false]
|------o maxchar int
|------o normalimage Image 屬性
|------o hotimage Image 屬性
|------o focusedimage Image 屬性
|------o disabledimage Image 屬性
|------o nativebkcolor string #RRGGBBAA
|------o CLabelUI::SetAttribute(pstrName, pstrValue)

List CListUI : public CVerticalLayoutUI, public IListUI
|------o header string bool [hidden|Show]
|------o headerbkimage string path
|------o scrollselect bool [true|false]
|------o multiexpanding bool [true|false]
|------o itemfont int Font列表的索引號
|------o itemalign string enum [left|center|right]
|------o itemendellipsis bool [true|false]
|------o itemtextpadding RECT(long left, long top, long right,long bottom)
|------o itemtextcolor string #RRGGBBAA
|------o itembkcolor string #RRGGBBAA
|------o itemimage string path
|------o itemselectedtextcolor string #RRGGBBAA
|------o itemselectedbkcolor string #RRGGBBAA
|------o itemselectedimage string path
|------o itemhottextcolor string #RRGGBBAA
|------o itemhotbkcolor string #RRGGBBAA
|------o itemhotimage Image 屬性
| |------o file string path
| |------o corner RECT(long left, long top, long right,long bottom)
|------o itemdisabledtextcolor string #RRGGBBAA
|------o itemdisabledbkcolor string #RRGGBBAA
|------o itemdisabledimage Image 屬性
|------o itemlinecolor string #RRGGBBAA
|------o itemshowhtml bool [true|false]
|------o CVerticalLayoutUI::SetAttribute(pstrName, pstrValue)

ListHeaderItem CListHeaderItemUI : public CControlUI
|------o dragable bool [true|false]
|------o sepwidth int
|------o align string enum [left|center|right]
|------o itemshowhtml bool [true|false]
|------o endellipsis bool [true|false]
|------o font int Font列表的索引號
|------o textcolor string #RRGGBBAA
|------o textpadding RECT(long left, long top, long right,long bottom)
|------o showhtml bool [true|false]
|------o normalimage Image 屬性
|------o hotimage Image 屬性
|------o pushedimage Image 屬性
|------o focusedimage Image 屬性
|------o sepimage Image 屬性

CListElementUI : public CControlUI, public IListItemUI
|------o selected value 有此屬性就選中
|------o CControlUI::SetAttribute(pstrName, pstrValue)

ListExpandElement CListExpandElementUI : public CListTextElementUI
|------o expander RECT(long left, long top, long right,long bottom)
|------o hideself bool [true|false]
|------o selected bool
|------o CListTextElementUI::SetAttribute(pstrName, pstrValue)

ListContainerElement CListContainerElementUI List容器
|------o selected value 有此屬性就選中

ListHeader CListHeaderUI

CListLabelElementUI : public CListElementUI

ListTextElement CListTextElementUI : public CListLabelElementUI

Label CLabelUI : public CControlUI
|------o align string enum [left|center|right]
|------o endellipsis bool [true|false]
|------o font int Font列表的索引號
|------o textcolor string #RRGGBBAA
|------o disabledtextcolor string #RRGGBBAA
|------o textpadding RECT(long left, long top, long right,long bottom)
|------o showhtml bool [true|false]
|------o CControlUI::SetAttribute( pstrName, pstrValue )

Text CTextUI : public CLabelUI

Combo CComboUI : public CContainerUI, public IListOwnerUI
|------o textpadding RECT(long left, long top, long right,long bottom)
|------o normalimage Image 屬性
|------o hotimage Image 屬性
|------o pushedimage Image 屬性
|------o focusedimage Image 屬性
|------o disabledimage Image 屬性
|------o dropbox string
|------o itemfont int Font列表的索引號
|------o itemalign string enum [left|center|right]
|------o itemtextpadding RECT(long left, long top, long right,long bottom)
|------o itemtextcolor string #RRGGBBAA
|------o itembkcolor string #RRGGBBAA
|------o itemimage Image 屬性
|------o itemselectedtextcolor string #RRGGBBAA
|------o itemselectedimage Image 屬性
|------o itemhottextcolor string #RRGGBBAA
|------o itemhotbkcolor string #RRGGBBAA
|------o itemhotimage Image 屬性
|------o itemdisabledtextcolor string #RRGGBBAA
|------o itemdisabledbkcolor string #RRGGBBAA
|------o itemdisabledimage Image 屬性
|------o itemlinecolor string #RRGGBBAA
|------o itemshowhtml bool [true|false]
|------o CContainerUI::SetAttribute(pstrName, pstrValue)

Button CButtonUI : public CLabelUI
|------o normalimage Image 屬性
|------o hotimage Image 屬性
|------o pushedimage Image 屬性
|------o focusedimage Image 屬性
|------o disabledimage Image 屬性
|------o hottextcolor string #RRGGBBAA
|------o pushedtextcolor string #RRGGBBAA
|------o focusedtextcolor string #RRGGBBAA
|------o CLabelUI::SetAttribute(pstrName, pstrValue)

Option COptionUI : public CButtonUI
|------o group string
|------o selected bool [true|false]
|------o selectedimage Image 屬性
|------o foreimage Image 屬性
|------o selectedtextcolor string #RRGGBBAA
|------o CButtonUI::SetAttribute(pstrName, pstrValue)

Progress CProgressUI : public CLabelUI
|------o fgimage Image 屬性
|------o hor bool
|------o min int
|------o max int
|------o value int
|------o CLabelUI::SetAttribute(pstrName, pstrValue)

Slider CSliderUI : public CProgressUI
|------o thumbimage Image 屬性
|------o thumbhotimage Image 屬性
|------o thumbpushedimage Image 屬性
|------o thumbsize SIZE(int x, int y)
|------o step int
|------o CProgressUI::SetAttribute(pstrName, pstrValue)

RichEdit CRichEditUI : public CContainerUI, public IMessageFilterUI
|------o vscrollbar bool [true|false]
|------o autovscroll bool [true|false]
|------o hscrollbar bool [true|false]
|------o autohscroll bool [true|false]
|------o wanttab bool [true|false]
|------o wantreturn bool [true|false]
|------o wantctrlreturn bool [true|false]
|------o rich bool [true|false]
|------o multiline bool [false|true]
|------o readonly bool [true|false]
|------o numberonly bool [true|false]
|------o password bool [true|false]
|------o align string enum [left|center|right]
|------o font int Font列表的索引號
|------o textcolor string #RRGGBBAA
|------o CContainerUI::SetAttribute(pstrName, pstrValue)

ActiveX CActiveXUI : public CControlUI
|------o clsid string
|------o modulename string
|------o delaycreate bool [true|false]
|------o CControlUI::SetAttribute(pstrName, pstrValue)

ScrollBar CScrollBarUI : public CControlUI
|------o button1normalimage Image 屬性
|------o button1hotimage Image 屬性
|------o button1pushedimage Image 屬性
|------o button1disabledimage Image 屬性
|------o button2normalimage Image 屬性
|------o button2hotimage Image 屬性
|------o button2pushedimage Image 屬性
|------o button2disabledimage Image 屬性
|------o thumbnormalimage Image 屬性
|------o thumbhotimage Image 屬性
|------o thumbpushedimage Image 屬性
|------o thumbdisabledimage Image 屬性
|------o railnormalimage Image 屬性
|------o railhotimage Image 屬性
|------o railpushedimage Image 屬性
|------o raildisabledimage Image 屬性
|------o bknormalimage Image 屬性
|------o bkhotimage Image 屬性
|------o bkpushedimage Image 屬性
|------o bkdisabledimage Image 屬性
|------o hor bool [true|false]
|------o linesize int
|------o range int
|------o value int
|------o showbutton1 bool [true|false]
|------o showbutton2 bool [true|false]
|------o CControlUI::SetAttribute(pstrName, pstrValue)

控件的通用屬性
stretch STRETCHMODE
o--------move_x
o--------move_y
o--------move_xy
o--------size_x
o--------size_y
o--------size_xy
o--------group
o--------line

考慮到在xml編輯器中使用<>符號不方便,可以使用{}符號代替
支持標簽嵌套(如<l><b>text</b></l>),但是交叉嵌套是應該避免的(如<l><b>text</l></b>)
The string formatter supports a kind of "mini-html" that consists of various short tags:

Bold: <b>text</b>
Color: <c #xxxxxx>text</c> where x = RGB in hex
Font: <f x>text</f> where x = font id
Italic: <i>text</i>
Image: <i x y z> where x = image name and y = imagelist num and z(optional) = imagelist id
Link: <a x>text</a> where x(optional) = link content, normal like app:notepad or http:www.xxx.com
NewLine <n>
Paragraph: <p x>text</p> where x = extra pixels indent in p
Raw Text: <r>text</r>
Selected: <s>text</s>
Underline: <u>text</u>
X Indent: <x i> where i = hor indent in pixels
Y Indent: <y i> where i = ver indent in pixels

五、duilib庫分析: 消息流程分析

看下CWindowWnd類與CPaintManagerUI類是咋進行消息分發的吧.

  1. 先看下CPaintManagerUI類的MessageLoop函數:

void CPaintManagerUI::MessageLoop()
{
MSG msg = { 0 };
while( ::GetMessage(&msg, NULL, 0, 0) ) {
if( !CPaintManagerUI::TranslateMessage(&msg) ) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
消息第一次會由CPaintManagerUI類的TranslateMessage消息接收到.

  1. 調用CWindowWnd::Create創建窗口. 完成以下操作:

1) 如果要子類下Window的控件(就是系統的控件, 而不是duilib的模擬控件), 就設置__ControlProc函數為消息回調函數.

2)不子類化, 就註冊窗口類. 此時設置__WndProc為窗口消息處理回調函數.

3)用CreateWindowEx API函數創建窗口.

這裏先不看子類化相關的, 我要先看明白標準的窗口創建過程. 這也操作後消息就會分發到__WndProc了,

  1. 看下__WndProc函數的定義:

LRESULT CALLBACK CWindowWnd::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd pThis = NULL;
if( uMsg == WM_NCCREATE ) {
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = static_cast<CWindowWnd
>(lpcs->lpCreateParams);
pThis->m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(pThis));
}
else {
pThis = reinterpret_cast<CWindowWnd*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
if( uMsg == WM_NCDESTROY && pThis != NULL ) {
LRESULT lRes = ::CallWindowProc(pThis->m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetWindowLongPtr(pThis->m_hWnd, GWLP_USERDATA, 0L);
if( pThis->m_bSubclassed ) pThis->Unsubclass();
pThis->m_hWnd = NULL;
pThis->OnFinalMessage(hWnd);
return lRes;
}
}
if( pThis != NULL ) {
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else {
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
消息第二次就由
WndProc接收到, 然後再傳到CWindowWnd類的HandlerMessage函數中.

  1. 看看CWindowWnd類的繼承類對於HandlerMessage虛函數的實現.

LRESULT CMainWnd::HandleMessage( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT lRes = 0;
BOOL bHandled = TRUE;
switch ( uMsg )
{
case WM_CREATE: lRes = OnInitResource( bHandled ); break;
default:
bHandled = FALSE;
}

if ( bHandled )  
{  
    return lRes;  
}  

if ( m_pm.MessageHandler( uMsg, wParam, lParam, lRes ) )      
{  
    return lRes;  
}  

return CWindowWnd::HandleMessage( uMsg, wParam, lParam );    

}

在這裏就是用戶要按消息進行具體的處理了. 之後要傳到CPaintManagerUI類對象的MessageHandler函數. 未處理的消息就要返回給CWindowWnd類的默認消息處理函數來處理了.

  1. CPaintManagerUI類的TranslateMessage, MessageHandler函數的內容.

BOOL CPaintManagerUI::TranslateMessage(const LPMSG pMsg)
{
HWND hwndParent = ::GetParent(pMsg->hwnd);
UINT uStyle = GetWindowStyle(pMsg->hwnd);
LRESULT lRes = 0;
for( int i = 0; i < m_aPreMessages.GetSize(); i++ ) {
CPaintManagerUI pT = static_cast<CPaintManagerUI>(m_aPreMessages[i]);
if( pMsg->hwnd == pT->GetPaintWindow()
|| (hwndParent == pT->GetPaintWindow() && ((uStyle & WS_CHILD) != 0)) )
{
if( pT->PreMessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lRes) ) return TRUE;
}
}
return FALSE;
}
m_aPreMessage為靜態成員變量, 在CPaintManagerUI::Init進行窗口與此類綁定時添加到此變量中.

  1. CPaintManagerUI::PreMessageHandler消息過濾函數.

BOOL CPaintManagerUI::PreMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& )
{

for( int i = 0; i < m_aPreMessageFilters.GetSize(); i++ )   
{  
    BOOL bHandled = FALSE;  
    LRESULT lResult = static_cast<IMessageFilterUI*>(m_aPreMessageFilters[i])->MessageHandler(uMsg, wParam, lParam, bHandled);  
    if( bHandled ) {  
        return TRUE;  
    }  
}  

}

  1. CPaintManagerUI::MessageHandler函數.

1) 遍歷m_aMessageFilters列表中的IMessageFilterUI接口, 並調用MessageHandler函數, 再次進行相關的消息過濾功能.(與上面的m_aPreMessageFilters類似)

2) 在此會處理窗口的WM_PAINT消息. 顯示所有控件的外觀與狀態.

3) 處理鼠標事件, 實現控件激活和相關事件.

4) 處理WM_TIMER消息, 所有控件要用CPaintManagerUI的SetTimer, KillTimer等函數實現計時器功能.

5) 處理CPaintManagerUI類的自定消息, WM_APP + 1與 +2,

WM_APP + 1是用於控件延遲銷毀控件對象

WM_APP + 2銷毀異步消息的處理.

( 異步控件消息用CPaintManagerUI::SendNotify函數, 把消息對象添加到m_aAsyncNotify列表中, 再PostMessage函數WM_APP + 2 )

5) 其它基本的窗口相關消息的處理.

CPaintManagerUI把DUILIB內部的事件都是用TEventUI結構的形式調用CControlUI類的Event函數來投遞的.

Duilib學習日記1