接下來,我們將繼續分析UIlib.h文件中其他的文件, UIContainer.h, UIRender.h, WinImplBase.h, UIManager.h,以及其他布局、控件等;
1. UIRender.h:UI渲染器,其中cpp文件中,定義的ZIP壓縮相關的數據結構,以及宏操作,與XUnzip.cpp中一樣的(個人認為可以提取出來作為共用的一部分),此外還有stbi_load_from_memory、
stbi_image_free,涉及到圖片加載操作,具體詳細細節可參考stb_image.c中開源庫JPEG/PNG圖片加載器stbi_image(支持的格式也比較多的)。
CRenderClip:渲染剪切區域類,數據成員:rcItem:渲染剪切區域大小,hDC:設備環境句柄 ,hRgn:標識被剪切的區域句柄,hOldRgn:保存早前剪切區域的句柄,靜態成員函數:GenerateClip:
生成剪切區域,參數rc:新的剪切區域大小,內部調用GetClipBox獲取到環境句柄的剪切區域大小,並調用CreateRectRgnIndirect創建剪切區域句柄,此外ExtSelectClipRgn將新的剪切區域與當前
環境句柄的剪切區域進行擴展、合並,GenerateRoundClip:生成圓角剪切區域,參數rcItem為圓角區域位置大小,width、height:圓角矩形的邏輯高度和寬度,內部通過CreateRoundRectRgn
創建一個圓角矩形區域句柄,並與當前區域合並,UseOldClipBegin:使用早期的矩形區域作為當前的剪切區域區域,UseOldClipEnd:使用當前區域作為設備環境剪切區域;
CRenderEngine:渲染引擎類,整個類中基本上均是靜態成員函數,AdjustColor:色彩調整,在分析如何處理色彩調整前,先分析靜態全局函數RGBtoHSL、HSLtoRGB分別為RGB顏色空間互轉為
HSL色彩空間,RGB和HSL屬於不同的色彩空間,此外在不同平台下,HSL表現不一樣,即范圍不一致,RGB的取值范圍在0~255之間,HSL的取值H為0~240,SL在0~1之間,需要對RGB和HSL顏色
空間有足夠的認識可查閱相關資料,算法處理(摘自網絡):
HSL與RGB轉換(偽代碼表示)
a) RGB→HSL的算法描述。
步驟1:把RGB值轉成【0,1】中數值。
步驟2:找出R,G和B中的最大值。
步驟3:設L=(maxcolor + mincolor)/2
步驟4:如果最大和最小的顏色值相同,即表示灰色,那么S定義為0,而H未定義並在程序中通常寫成0。
步驟5:否則,測試L:
If L<0.5, S=(maxcolor-mincolor)/(maxcolor + mincolor)
If L>=0.5, S=(maxcolor-mincolor)/(2.0-maxcolor-mincolor)
步驟6: If R==maxcolor, H=(G-B)/(maxcolor-mincolor)
If G==maxcolor, H=2.0+(B-R)/(maxcolor-mincolor)
If B==maxcolor, H=4.0+(R-G)/(maxcolor-mincolor)
步驟7:從第6步的計算看,H分成0~6區域。RGB顏色空間是一個立方體而HSL顏色空間是兩個六角形錐體,其中的L是RGB立方體的主對角線。因此,RGB立方體的頂點:紅、黃、綠、青、藍
和品紅就成為HSL六角形的頂點,而數值0~6就告訴我們H在哪個部分;H=H*60.0,如果H為負值,則加360。
b) HSL→RGB的算法描述。
步驟1:If S==0,表示灰色,定義R,G和B都為L.
步驟2:否則,測試L:
If L<0.5,temp2=L*(1.0+S)
If L>=0.5,temp2=L+S-L*S
步驟3:temp1=2.0*-temp2
步驟4:把H轉換到0~1。
步驟5:對於R,G,B,計算另外的臨時值temp3。方法如下:
for R, temp3=H+1.0/3.0
for G, temp3=H
for B, temp3=H-1.0/3.0
if temp3<0, temp3=temp3+1.0
if temp3>1, temp3=temp3-1.0
步驟6:對於R,G,B做如下測試:
If 6.0*temp3<1,color=temp1+(temp2-temp1)*6.0*temp3
else if 2.0*temp3<1,color=temp2
else if 3.0*temp3<2, color=temp1+(temp2-temp1)*((2.0/3.0)-temp3)*6.0
else color=temp1。
有興趣時可以仔細推導一下算法;
好啦,我們回到AdjustColor函數中,內部現通過獲取到指定顏色RGB值dwColor的HSL值並重新根據傳入的參數H、S、L修正HSL值,此后再轉化為RGB值;可以看到內部修正HSL值時,將S、L分別/100,
+= (H - 180)?事實上我們可以跟蹤發現CPaintManagerUI類中的m_H、m_S、m_L的值預設值為180、100、100;duilib中一般在繪制背景色PaintBkColor時會使用到;
LoadImage:從文件或可執行應用程序、資源DLL中加載圖片,參數bitmap為圖片資源ID或資源字符串,type為圖片類型或資源類型,mask為掩碼,內部實現為:若type為空,若CPaintManagerUI已有
資源ZIP文件,則從壓縮文件中獲取指定文件的內容,否則則直接從指定文件中獲取內容,若type不為空,則從可執行應用程序或資源DLL中獲取內容,得到內容后,再通過stbi_load_from_memory加載
解析得到pImage的圖片內容,此外因pImage與CreateDIBSection創建的BITMAP數據格式不一致,需要轉化;此后返回TImageInfo數據結構的內容,釋放pImage資源,TImageInfo結構后面會解析
,整個圖片加載,圖片格式因stbi-info支持格式,若需要支持其他格式或是其他處理可以更換圖片加載模塊,FreeImage:釋放加載的圖片資源(實時上主要是釋放通過LoadImage創建的BITMAP數據資源)
DrawImage:繪制圖片,參數hDC,控件或窗口上下文句柄,hBitmap為位圖句柄,rc為窗口區域大小,rcPaint為繪制區域大小,rcBmpPart為圖片源窗口區域大小,rcCorners為拐角區域大小,此外
alphaChannel釋放開啟了alpha通道,uFade為淡色值(透明度),hole、xtiled、ytiled分別為釋放開啟凹陷效果、X或Y方向平鋪效果;DrawImageString:繪制圖片(通過內容字符串解析繪制),內部調用
DrawImage實現,DrawColor:繪制顏色,參數hDC為上下文句柄,rc為繪制區域,color為繪制顏色值,內部通過創建單一顏色的32bpp的HBITMAP來繪制區域,DrawGradient:漸變繪制,用在繪制
背景色中,在dulib中提供了三個背景漸變色彩區域見CControlUI中m_dwBackColor、m_dwBackColor2,m_dwBackColor3,參數hDC為上下文句柄,rc為繪制區域,dwFirst、dwSecond為第一色
、第二色(即首尾色),bVertical為是否為垂直方向,否則為水平,nSteps指定漸變的步進值,函數內部通過雙緩存技術實現繪制通過計算step調整每Step各RGB色彩值創建CreateSolidBrush畫刷分區域
地FillRect填充實現繪圖,DrawLine:繪制線段,參數hDC為上下文句柄,rc為繪制區域(事實上繪制線段為該區域的左上角至右下角的對角線線段),nSize為畫筆寬度,dwPenColor為畫筆顏色,nStyle
為畫筆風格,DrawRect:繪制矩形,參數同DrawLine,少了畫筆風格的參數,內部調用Rectangle繪制,矩形內部不會被填充,DrawRoundRect:繪制圓角矩形,參數同DrawRect,此外內部調用了
RoundRect繪制圓角矩形,同樣內部不會被填充,DrawText:繪制文本,參數hDC上下文句柄,pManager為繪制管理對象,rc為繪制區域大小,pstrText為繪制文本字符串,dwTextColor為文本顏色,
iFont為字體索引,通過pManager中獲取其字體句柄,uStyle為繪制風格,函數內部調用DrawText實現繪制文本,DrawHtmlText:繪制HTML文本,GenerateBitmap:生成bitmap,參數pManager
獲取對應繪制管理器對象,pControl控件對象,rc為bitmap大小,使用繪制管理對象中繪制句柄對象繪制控件對象區域並返回該繪制后指定大小的bitmap大小;GetTextSize:獲取字符串大小(高、寬度)
參數hDC為上下文句柄,pManager為繪制管理對象提供當前應用於(hDC下的當前所選字體來計算字符串尺寸)該字符串上的字體,pstrText為字符串,iFont為字體索引,uStyle參數暫時未被用到,
內部使用GetTextExtentPoint32獲取到字符串高度和寬度信息。
2. UIContainer.h:控件容器,一般用在具有子控件的控件中,如:UIList、UICombox、UITreeView、以及布局控件;
IContainerUI:UI容器基類,提供了對元素項的索引查找和設置,控件添加和移除等操作的接口定義;GetItemAt:獲取指定索引的下的控件對象,GetItemIndex:獲取指定控件對應的索引值,此外對應
SetItemIndex:設置控件對象與索引對,對應早期索引下的Item將被移除,GetCount:獲取容器中控件數,Add:添加(追加)控件對象至容器,AddAt:在指定索引處添加控件,Remove:移除指定控件
對象,RemoveAt:移除指定索引下的控件對象,RemoveAll:移除所有容器下對象;
CContainerUI:繼承於IContainerUI、CControlUI,UI容器CContainerUI也為控件UI對象,因該類比較大,從成員函數開始,GetClass:獲取當前對象的類名,GetInterface:獲取參數pstrName指定
類名的控件對象指針,接下來的幾個函數繼承於IContainerUI,此處不再說明,需要說的是成員變量m_items:容納控件對象,即為控件容器,DoEvent:事件源處理函數,處理各種事件消息,SetVisible:
設置當前容器對象可見性並設置容器內各控件對象的可見性狀態,SetInternVisible:設置控件內部可見性狀態,SetMouseEnabled:設置鼠標是否可用,內部若存在垂直、水平滾動條則也被設置,GetInset
、SetInset:獲取/設置內邊距(即客戶區)m_rcInset,GetChildPadding/SetChildPadding:獲取/設置子對象內邊距m_iChildPadding(控件邊距),SetAutoDestroy/GetAutoDestroy:設置或查詢當前
容器內對象是否自動銷毀(事實上內部還有個延遲銷毀),SetDelayedDestroy/GetDelayedDestroy:設置/查詢是否延遲銷毀,SetMouseChildEnabled/GetMouseChildEnabled:設置或查詢本控件的子
控件是否可以響應用戶操作,FindSelectable:查找容器中下一個可用控件索引,SetPos:設置控件位置,若存在子控件則若子控件為浮動的,則調整該控件,否則則設置為當前控件區域的大小,DoPaint:
繪制操作,SetAttribute:設置控件相關的屬性,SetManager:設置控件管理器(繪制管理器UI、控件父窗口,是否初始化),FindControl:查找控件並執行相應提供的回調函數,參數pData一般為鼠標
點擊位置或其他的附加值,SetSubControlText/GetSubControlText:設置/獲取子控件文本,SetSubControlFixedHeight/GetSubControlFixedHeight/SetSubControlFixedWdith等分別為獲取或
設置子控件高度或寬度,SetSubControlUserData:設置子控件用戶數據,FindSubControl:查找子控件對象,GetScrollPos/SetScrollPos:獲取/設置滾動條位置,LineUp/LineDown、PageUp、
HomeUp、EndDown、LineLeft、LineRight、PageLeft、PageRight、HomeLeft、EndRight等均為對滾動條的控制,EnableScrollBar:是否啟用垂直滾動條和水平滾動條;GetVerticalScrollBar、
GetHorizontalScrollBar:獲取垂直滾動條、水平滾動條控件對象;SetFloatPos:設置指定容器元素浮動位置顯示,ProcessScrollBar:調整滾動條位置;
