大学时就用过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。以后我会求证的!