Duilib源碼分析(四)繪制管理器—CPaintManagerUI—(前期准備二)


  接下來,我們繼續分析UIlib.h文件中余下的文件,當然部分文件可能順序錯開分析,這樣便於從簡單到復雜的整個過程的里面,而避免一開始就出現各種不理解的地方。

  1. UIManager.h:UI管理器,暫時放在后面介紹;

  2. UIBase.h:UI窗口相關,包括常用的窗口風格、窗口類風格的宏定義,調試相關,以及基本窗口類;

    首先宏定義了幾個常用的窗口風格、窗口擴展風格和窗口類風格,以UI_WNDSTYLE_XXX和UI_CLASSSTYLE__XXX開頭的;

    ASSERT采用的是CRT的_ASSERTE、DUI__Trace、DUI__TraceMsg用以調試、跟蹤消息,不過注意DUI__Trace字符串長度不能超過300字節;

    CNotifyPump:通告消息泵,用以對消息分發、下發(主要是對繼承樹的各個添加到_messageEntries的消息映射遍歷分發,並執行相應的處理函數),數據成員:m_VirtualWndMap:

    虛擬窗口的集合,類型CStdStringPtrMap可以較為快速查找,此外可能增加了虛擬窗口,此時便先對虛擬窗口分發,若處理則直接返回,否則再遍歷主窗口,成員函數:AddVirtualWnd:

    添加虛擬窗口,參數strName、pObject分別為虛擬窗口名稱與該虛擬窗口的消息通告泵對象,RemoveVirtualWnd:移除指定名稱的虛擬窗口,NotifyPump:通告泵,實現真正的消息

    分發操作(先對虛擬窗口分發,再對主窗口遍歷分發),LoopDispatch:循環分發消息(對消息繼承樹和_messageEntries遍歷,並對應消息處理類型,調用執行相應的消息處理接口);

    CWindowWnd:窗口基類,將Win32的創建窗口的主要過程進行了封裝,一些控件可能會從它繼承實現;先從數據成員:m_hWnd:窗口句柄,m_OldWndProc:早期的窗口消息

    處理函數地址,m_bSubclassed:是否為子類化的窗口類,成員函數:構造函數CWindowWnd:其中m_OldWndProc初始化為默認窗口處理函數::DefWindowProc,GetHWND:

    獲取當前窗口句柄,同重載的運算符operator HWND(),RegisterWindowClass:注冊窗口類,暫時提供一個默認值的窗口類,重點關注其中的__WndProc的消息處理函數,可以發現

    很熟悉的操作,對是這樣的,他把本類對象保存在GWLP_USERDATA窗口關聯的用戶數據中了,便於下次可直接取出(但保證其他地方不再更新該GWLP_USERDATA的用戶數據),

    RegisterSuperclass:注冊子類化的窗口類,從一個已存在的窗口中獲取到WNDCLASSEX信息,此外其消息處理函數__ControlProc:內部處理方式不再是使用GWLP_USERDATA

    關聯,而是使用SetProp設置窗口屬性表項,來保存本來對象,便於下一次GetProp取出本類對象,調用本類的非靜態成員消息處理函數;Subclass:子類化窗口類,內部調用

    SubclassWindow實現窗口子類化(事實上內部調用的還是SetWindowLongPtr((hwnd), GWLP_WNDPROC, (LPARAM)(WNDPROC)(lpfn),這樣用__WndProc接管消息處理,此外

    還調用了SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(this))用來保存本類對象,便於后期消息處理,Unsubclass:卸載窗口子類化:使用原消息

    處理函數來接管消息處理;綜上,本類中子類化窗口的方式有:1. 通過GetSuperClassName獲取已注冊的父類窗口類名,再獲取WNDCLASSEX信息,並通過__ControlProc來處理消息;

    2. 使用Subclass,傳入已創建好的窗口句柄,這樣通過SubclassWindow和SetWindowLongPtr來達到hook消息的目的,多個版本的Create函數與CreateDuiWindow:創建窗口的過程:

    獲取超類類名,若已經給予,則調用RegisterSuperclass注冊新的窗口類(主要是為了繼承部分窗口類的屬性),若未給予超類類名,則調用RegisterWindowClass注冊一個默認值的窗口類,

    此后調用CreateWindowEx創建該窗口,ShowWindow:顯示或隱藏當前窗口,ShowModal:模擬MFC中的對話框DoModal函數的處理流程;可以看到將擁有者窗口變得不可用,並使得

    當前窗口顯示,此后內部使用自己的一套消息泵來從線程消息隊列中獲取消息,當內部消息泵收到本窗口消息WM_CLOSE或是WM_QUIT消息則會退出消息泵,並使得父窗口可用並獲取到焦點

    ,另外對於消息WM_QUIT消息,需要將該消息轉發給擁有者窗口(不一定是父窗口),使得擁有者窗口可被銷毀(因為能跳出內部的GetMessage並得到WM_QUIT消息,則為銷毀擁有者窗口);

    Close:關閉窗口,內部使用::PostMessage(WM_CLOSE)實現,發送消息到該線程的消息隊列中直接返回;另外SendMessage:內部使用SendMessage發送消息到消息對應處理函數處理

    並等待處理再返回;CenterWindow:居中顯示窗口,內部處理了多顯示器的情況,若存在擁有者窗口,則獲取擁有者窗口所在顯示器大小並使得該窗口居中顯示,SetIcon:設置當前窗口的

    大小圖標,內部調用LoadImage(舊用LoadIcon,被替代)加載資源ID:nRes,不過這里需要批評一下之前定義了STRINGorID類型,其實這里可以直接來用的,ResizeClient:調整窗口客戶

    區域大小,內部調用了AdjustWindowRectEx設置客戶區域大小並獲取調整后所得到的窗口區域大小,並通過SetWindowPos設置窗口大小;HandleMessage:成員消息處理函數,真實地

    接管消息處理不過內部目前只是調用CallWindowProc暫時使用m_OldWndProc來處理消息,此外一個比較有用的消息處理函數OnFinalMessage,專門用來在窗口銷毀后的最后一個消息

    WM_NCDESTROY中處理其他的資源銷毀的任務,這樣外部就可以無需顯示的調用當前窗口類的析構函數來銷毀內部內核資源或其他資源了,很方便的;最后該類基本完成了一個基本的窗口類

    其他需要特殊處理的窗口類可以繼承該類實現自己的操作,如后面介紹的WindowImplBase類。

  3. UIControl.h:UI控件基類,主要實現了控件相關如文本、圖形、位置、菜單等屬性設置

    FINDCONTROLPROC:聲明的控件查找函數,CControlUI* (CALLBACK* FINDCONTROLPROC)(CControlUI*, LPVOID),用在回調查找中;

    CControlUI:UI控件基類,大部分控件實現繼承於該類,因該類比較大,所以我們在分析的時候,建議先從成員函數開始;構造函數初始化了一系列的數據成員,暫不理會,后面涉及到相關數據成員

    時再回頭看看即可,析構函數~CControlUI:可以看到內部OnDestroy為我們之前分析的事件源,控件析構的時候需要處理的OnDestroy事件,此外調用了CPaintManagerUI管理的釋放該UI對象

    消息通告和計時器,這樣消息不會再發給當前已被釋放的UI對象,GetName/SetName:獲取/設置控件的名稱m_sName,GetClass:獲取控件類名稱"ControlUI",子類一般會重寫該函數,

    GetInterface:用以根據pstrName匹配獲取當前對象的繼承層次中的指針對象,GetControlFlags:獲取控件標記(取UIFLAG_TABSTOP、UIFLAG_SETCURSOR、UIFLAG_WANTRETURN)

    Activate:當前控件是否為激活的狀態(可見並可用),GetManager:獲取管理當前UI控件的CPaintManagerUI對象m_pManager,SetManager:設置管理該UI的m_pManager、父控件,此外若

    提供了需要初始化處理操作的事件源OnInit,再此將執行該事件源,GetParent:獲取當前控件的父控件,GetText/SetText:獲取/設置當前控件的文本並更新繼承控件樹控件大小,GetBkColor/

    GetBkColor2/GetBkColor3/SetBkColor/SetBkColor2/SetBkColor3/:設置背景色(提供三色,具體作用后面介紹),GetBkImage/SetBkImage:獲取/設置背景圖片,GetFocusBorderColor/

    SetFocusBorderColor:獲取/設置焦點時邊框顏色,IsColorHSL/SetColorHSL:獲取/設置是否開啟HSL色彩模式,GetBorderRound/SetBorderRound:獲取/設置邊框圓角大小,

    DrawImage:繪制圖像,參數hDC將要繪制到的控件或窗體畫刷句柄,pStrImage為圖形內容字符串(含文件名或資源名等),函數內部根據內容字符串解析並調用CRenderEngine渲染引擎繪制,具體

    操作過程后面分析,GetBorderSize/SetBorderSize:獲取/設置圓角邊框畫筆大小m_nBorderSize(命名也是醉了,含義不清與m_cxyBorderRound容易沖突),GetBorderColor/SetBorderColor:

    獲取/設置圓角邊框顏色,SetLeftBorderSize/SetTopBorderSize/SetRightBorderSize/SetBottomBorderSize:設置/獲取左邊框、上邊框、右邊框、下邊框畫筆大小,SetBorderStyle:設置邊框

    畫筆風格,SetPos/GetPos:設置/獲取控件位置,m_rcItem,GetWidth/GetHeight/GetX/GetY:獲取控件寬度、高度、左位置、上位置(左上位置),SetPadding/GetPadding:設置填充區域

    m_rcPadding,似乎內部未曾使用該變量,SetFixedXY/SetFixedWidth/SetFixedHeight:設置預設值控件的大小、寬度、高度,一般通過SetPos與GetPos獲取到實際的大小,此外SetMinXXX系列

    函數設置最小最大寬度、高度,SetRelativePos/SetRelativeParentSize:設置父控件、相對父控件的相對位置,SetToolTip/GetToolTip:設置信息提示,鼠標停留時的提示框信息,SetToolTipWidth:

    設置信息框寬度,SetShortcut/GetShortcut:設置控件快捷鍵key,SetContextMenuUsed:設置是否使用菜單上下文,SetUserData/GetUserData:設置/獲取用戶數據,SetTag/GetTag:設置/

    獲取標記數據,SetVisible:設置是否顯示,SetEnabled:設置是否可用,SetMouseEnabled:設置鼠標是否可用,SetKeyboardEnabled:設置鍵盤是否可用,SetFocus:設置是否為焦點,

    SetFloat:設置是否可停浮,FindControl:查找控件,並執行Proc回調函數,Invalidate:使無效,重繪,NeedUpdate/NeedParentUpdate:需要更新重繪或父控件繼承樹重繪,GetAdjustColor:

    獲取調整后的色彩,Init、DoInit:執行初始化操作,其中OnInit提供初始化事件源,Event、DoEvent:執行事件操作,其中OnEvent提供事件源,SetAttribute:設置控件屬性,ApplyAttributeList

    :設置屬性列表,內容包含各種可能的屬性字符串,解析並調用SetAttribute設置各屬性,EstimateSize:獲取預設值控件大小,DoPaint:繪制操作,主要執行背景顏色、背景圖、狀態圖、文本、邊框

    等,PaintBkColor/PaintBkImage/PaintStatusImage/PaintText/PaintBorder:分別為繪制背景色、背景圖片、狀態圖、文本、繪制邊框,DoPostPaint:繪制相應控件大小至HDC,布局中用到,

    SetVirtualWnd /GetVirtualWnd:設置/獲取虛擬窗口;目前大部分成員函數和成員數據說明,一部分函數用以外部調用接口,一部分用於內部繪制操作,此外也有部分參數未曾用到或是用以控制繪制,

    接下來說說數據成員:公有成員5個事件源:OnInit、OnDestroy、OnSize、OnEvent、OnNotify,分別為初始化源、釋放源、大小位置改變源、事件源、通告源,受保護成員:m_pManager:繪制

    管理器對象,m_pParent,父控件對象,m_sVirtualWnd:虛擬窗口,m_sName:控件名稱,m_bUpdateNeeded:是否需要更新控件,m_bMenuUsed:是否使用菜單上下文,m_rcItem:

    控件位置,m_rcPadding:控件填充大小,m_cXY:控件預設值位置大小,m_cxyFixed:控件固定大小,m_cxyMin、m_cxyMax:預設值最小、最大值,m_bVisible:是否可顯示,此外還有一個

    m_bInternVisible:內部使用的是否可顯示控件,用在某些繼承的控件實現中需要用到的,m_bEnabled:控件是否可用,m_bMouseEnabled:鼠標是否可用,m_bKeyboardEnabled:鍵盤是否

    可用,m_bFocused:是否獲取到焦點,m_bFloat:是否可停浮,m_bSetPos:是否在設置控件位置大小,m_tRelativePos:與父控件關聯位置,m_sText:設置文本,m_sToolTip:設置信息提示

    m_chShortcut:快捷鍵CHAR,m_sUserData:用戶保存的數據字符串,m_pTag:用戶保存的標記,m_dwBackColor:背景色,m_sBkImage:背景圖片,m_sForeImage:前景圖片,

    m_dwBorderColor:邊框顏色,m_dwFocusBorderColor:獲取到焦點時邊框顏色,m_bColorHSL:是否啟用HSL色彩模型,m_nBorderSize:邊框畫筆大小,m_nBorderStyle:邊框畫筆風格,

    m_nTooltipWidth:提示信息框寬度,m_cxyBorderRound:圓角邊框大小,m_rcPaint:繪制區域大小,m_rcBorderSize:邊框位置大小;

  基本上對整個類進行了概括性的說明,更為詳盡的比如:繪制場景、細節、布局等將在后期分析,目前我們只需要有個大概的概念即可。

    

    

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM