大學時就用過CEGUI,但是基本上就是用,沒有其他任何思考。現在做的東西多了,思考也多了。同事推薦看一本國人寫的《CEGUI深入解析》,一開始看了一些,但沒看進去,做了項目一個多月,有些實際的問題,再去看就有收穫了。此文章就收集一些使用CEGUI的心得,以便回顧或者協助他人。更多系統權威資料還請見CEGUI官網。
- Subscriber類對象之間不能直接賦值
我們有的時候想儲存一些Subsriber類對象,以供程式運行過程中調用設定回呼函數。但需要注意的是,SubScriber類中使用了new操作符,並且沒有合理的賦值操作符,所以不要輕易將一個Subscriber類對象複製給另外一個Subscriber類對象。除非你知道這個問題的存在,並且避免Subsriber類內new出來的對象被多次delete,那麼你可以讓Subsriber對象之間賦值。
- 子視窗可以顯示在父視窗之外
有時需要一些特殊的效果,如標籤頁在視窗外側,那麼我們就需要子視窗顯示在父視窗可視範圍之外。這個實現起來很簡單,直接使用setClippedByParent( false )即可。
- 子視窗的位置之謎
對於LookNFeel裡面的一個控制項內添加子控制項,我一直都很迷惑,子控制項的位置到底是怎麼算的?看下面的例子:
<Child type="TaharezLook/Titlebar" nameSuffix="__auto_titlebar__"> <Area> <Dim type="LeftEdge" ><AbsoluteDim value="10" /></Dim> <Dim type="TopEdge" ><AbsoluteDim value="10" /></Dim> <Dim type="Width" ><UnifiedDim scale="1" type="Width" /></Dim> <Dim type="Height" ><UnifiedDim scale="1" type="Height" /></Dim> </Area> <Property name="AlwaysOnTop" value="False" /></Child>
假如父視窗是一個FrameWindow,那麼這個子視窗的位置和大小到底是多少呢?當然你跑一下程式就知道了,但是為什麼是這樣呢?首先還是說一下正確結論:
- 子視窗的位置是以父視窗的InnerRect左上方為原點的。
- 子視窗的大小是根據子視窗的NonClient屬性來做不同判斷的。NonClient表明這個視窗是否屬於客戶區(客戶區即InnerRect),true表示不屬於(因為屬性名稱是NonClient)。false表明屬於客戶區。此屬性預設值為false。即一般子視窗不指定該屬性,在其位父視窗客戶區的。
判斷規則:如果子視窗NonClient是true,那麼CEGUI會根據父視窗的OuterRect(整個視窗大小)來計算,如果NonClient是false,那麼CEGUI會查看父視窗是否有InnerRect如果有根據InnerRect算,如果沒有只能根據OuterRect算。InnerRect的擷取又會牽扯到是否視窗有RenderingWindow(渲染視窗),如果有根據渲染視窗的函數來判斷。沒有渲染視窗則還是使用OuterRect。
具體代碼可以查閱一下CEGUI::Window::setArea,裡面計算baseSize的時候可以看出到底是根據誰來計算比例分量的。
//----------------------------------------------------------------------------//void Window::setArea(const UVector2& pos, const UVector2& size){ // Limit the value we set to something that's within the constraints // specified via the min and max size settings. // get size of 'base' - i.e. the size of the parent region. const Size base_sz((d_parent && !d_nonClientContent) ? d_parent->getUnclippedInnerRect().getSize() : getParentPixelSize()); UVector2 newsz(size); constrainUVector2ToMinSize(base_sz, newsz); constrainUVector2ToMaxSize(base_sz, newsz); setArea_impl(pos, newsz);}
視窗位置目前是聽同事說的根據視窗的InnerRect(視窗其實都會有InnerRect,主要是看是否和OuterRect一樣),像FrameWindow這樣的就會有一個和OuterRect不一樣的InnerRect。以後我會求證的!