Duilib學習日記1
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皮膚庫的行列當中。分析難免有誤,見諒!
一、核心類
- CWindowWnd,窗口對象管理父類,主要作用:
1) 創建窗口。
2) 窗口消息過程處理。
3) 提供窗口子類化與超類化接口。
- CDialogBuilder,控件布局類,主要作用:
1) 讀取XML腳本,分析腳本,構建控件樹。
2) 創建控件對象。
- CPaintManagerUI,窗口消息及圖形繪制管理器類,與窗口綁定,主要作用:
1) 繪制控件。
2) 消息管理。
3) 事件通知。
- INotifyUI,事件通知抽象類,主要作用:
1) 重載Notify虛函數,處理事件通知。
二、控件類
- CControlUI,控件管理父類,主要作用:
1) 控件的通用基類,提供控件通用屬性管理。
-
CLabelUI,靜態標簽類,父類CControlUI。
-
CButtonUI,按鈕類,父類CLabelUI。
-
COptionUI,選擇按鈕類,父類CButtonUI。
-
CTextUI,靜態文本類,父類CLabelUI。
-
CProgressUI,進度條類,父類CLabelUI。
-
CSliderUI,父類CProgressUI。
-
CEditUI,編輯框類,父類CLabelUI。
- CListUI,列表框類,父類CVerticalLayoutUI、IListUI。
1) CListHeaderUI,父類CHorizontalLayoutUI。
2) CListHeaderItemUI,列表頭類,父類CControlUI。
3) CListTextElementUI,類表文本類,父類CListLabelElementUI。
4) CListLabelElementUI,父類CListElementUI。
-
CComboUI,組合框類,父類CContainerUI、IListOwnerUI。
-
CActiveXUI,ActiveX控件類,父類CControlUI、 IMessageFilterUI。
-
CContainerUI,容器類,父類CControlUI、IContainerUI。
-
CTabLayoutUI,選項頁布局類,父類CContainerUI。
-
CTileLayoutUI,父類CContainerUI。
-
CDialogLayoutUI,對話框布局類,父類CContainerUI。、
-
CVerticalLayoutUI,垂直布局類,父類CContainerUI。
-
CHorizontalLayoutUI,水平布局類,父類CContainerUI。
-
CListExpandElementUI,父類CListTextElementUI。
- CListContainerElementUI,父類CContainerUI、IListItemUI。
三、輔助類
- CStdPtrArray,指針數組。
-
CStdValArray,數據數組。
-
CStdString,字符串數組。
- 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類是咋進行消息分發的吧.
- 先看下CPaintManagerUI類的MessageLoop函數:
void CPaintManagerUI::MessageLoop()
{
MSG msg = { 0 };
while( ::GetMessage(&msg, NULL, 0, 0) ) {
if( !CPaintManagerUI::TranslateMessage(&msg) ) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
消息第一次會由CPaintManagerUI類的TranslateMessage消息接收到.
- 調用CWindowWnd::Create創建窗口. 完成以下操作:
1) 如果要子類下Window的控件(就是系統的控件, 而不是duilib的模擬控件), 就設置__ControlProc函數為消息回調函數.
2)不子類化, 就註冊窗口類. 此時設置__WndProc為窗口消息處理回調函數.
3)用CreateWindowEx API函數創建窗口.
這裏先不看子類化相關的, 我要先看明白標準的窗口創建過程. 這也操作後消息就會分發到__WndProc了,
- 看下__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函數中.
- 看看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類的默認消息處理函數來處理了.
- 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進行窗口與此類綁定時添加到此變量中.
- 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;
}
}
}
- 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