当前位置: BOLT界面引擎 > 知识库文章 > 引擎里的坐标系简介

引擎里的坐标系简介

作者:李亚星 2012-03-16

引擎里的坐标系简介

 

         在界面开发中,坐标系统的设计是一项关键内容,影响到开发者如何对界面元素进行排版,如何在界面上放置图片、文字等内容。Bolt引擎是基于贴图的系统,所涉及到的坐标系都是基于像素的,也就是像素是最小的单位。目前在Bolt里面没有DPI的概念。

 

引擎里面的坐标系,根据层次,可以分为窗口坐标系、对象树坐标系和对象坐标系,此外由于窗口在屏幕上显示,还有最外层的屏幕坐标系,四个坐标系之间可以相互转换

 

一、       窗口坐标系(以窗口左上角为原点的坐标系)

Hostwnd层面的坐标系统,也是windows下面的窗口坐标系,可以用来改变窗口的位置、大小,以及监听相关的事件。窗口坐标系影响到窗口在屏幕上的位置。和窗口坐标系相关的接口有下面几个:

 

Move 移动窗口在屏幕上的位置

GetWndRect 获取窗口在屏幕上的位置

 

相关事件有下面几个:

OnSize 窗口的大小发生了改变

OnMove 窗口的位置发生了改变

 

上述接口和事件,所传参数都是屏幕坐标系,也就是窗口在屏幕上的位置

 

窗口坐标系和屏幕坐标系的转换接口:

l  窗口坐标转换到屏幕坐标:

HostWndPtToScreenPt  将窗口里面一个点转换到屏幕上一个点

    HostWndRectToScreenRect 将窗口里面一个矩形转换到屏幕上一个矩形

 

l  屏幕坐标转换到窗口坐标:

ScreenPtToHostWndPt 将屏幕上一个点转换到窗口上一个点

ScreenRectToHostWndRect 将屏幕上一个矩形转换到窗口上一个矩形

 

对象树坐标系(以根对象位置的0,0点为原点的坐标系)

 

对象树在坐标系统里面是一个关键层次,起到承上启下的作用,在下层和窗口hostwnd关联,上层又和对象关联。

 

对象树在绑定到窗口上的时候,可以指定绑定原点,也就是对象树的(0,0)坐标在窗口上的位置,接口如下:

 

Hostwnd:SetUITreeOrigin(x,y)

x,y HostWnd:GetUITreeOrigin

        

默认绑定原点是(0,0),一般情况下都不会改变绑定原点(绑定原点不在0,0位置,有 可能会导致出一些异常情况)。如果绑定原点是在(0,0),那么窗口坐标系就等同于对象树坐标系,两者之间不需要转换;假如绑定原点不是在(0,0),那么窗口坐标系和对象树坐标系之间就需要转换了,这点需要特别小心,hostwnd提供了专门的转换接口

 

窗口坐标系和对象树坐标系的转换接口:

l  窗口坐标转换到对象树坐标:

HostWndPtToTreePt将窗口里面一个点转换到对象树上一个点

    HostWndRectToTreeRect将窗口里面一个矩形转换到对象树上一个矩形

 

l  对象树坐标转换到窗口坐标:

TreePtToHostWndPt将对象树上一个点转换到窗口上一个点

TreeRectToHostWndRect将对象树上一个矩形转换到窗口上一个矩形

 

二、       对象坐标系(以对象位置的0,0点为原点的坐标系)

 

对象坐标系是最上层的坐标系,也是使用最多的坐标系,平时我们所说的对象的位置,就是对象在对象树上的坐标。

 

所有元对象都有两个核心参数:posabspos,其中

 

n  pos 对象的相对位置,也就是相对于父对象的坐标,可以通过GetObjPosSetObjPosSetObjPos2几个接口来查询和设置。如果是根对象,那么pos就是abspos

相对位置改变的事件是 OnPosChange

 

n  abspos 对象的绝对位置,也就是该对象在对象树坐标系里面的坐标,可以通过GetObjAbsPos来查询,但是不可以直接改变,每次对象的相对位置发生改变以后,绝对位置会及时更新。另外需要注意的是,当对象没有绑定到对象树上的时候,绝对位置是无效的。

绝对位置改变的事件是 OnAbsPosChange,但是这个事件在祖父对象位置发生改变时也会触发,所以触发频率很高,尽量少用

对象的绝对位置,就是由父对象的绝对位置+自己的相对位置计算而来,自底向上以此递归,直到根对象为止(刚才说了,根对象的posabspos相同)

 

对象坐标系和对象树坐标系的转换:

对于某个对象,其绝对位置abspos(a,b,c,d),自左向右依次为left,top,right,bottom,那么有

 

l  对象坐标转换到对象树坐标

假设对象坐标(x,y),那么转换到对象树坐标为(a+x, b+y),也就是对象坐标+对象绝对位置而来。

 

l  对象树坐标转换到对象坐标

假设对象树坐标(x,y),那么转换到对象坐标为(x-a,y-b),也就是对象树坐标-对象绝对位置而来。

 

三、       元对象的表达式

 

对象位置支持表达式,这个是整个引擎推荐的自动布局方法,子对象通过表达式,通过引用父对象的位置、大小,并且在父对象改变大小的时候,也可以自动跟随改变,极大的方便了对象之间排版,关于表达式的使用介绍,我们有专门的一篇文章介绍,大家可以参阅。这里只是简单说明一下注意事项:

 

1.         对象的位置pos是可以表达式,表达式经过计算后,会计算出来具体的坐标,这个时候才会更新到真正的posabspos

2.         由于整个坐标系统都是基于像素的,所以对象的位置和表达式计算的结果,最好不要出现小数,比如0.5,或者(10 + 11)/2这样的表达式,如果运算结果会有浮点数,我们的取正方法是向下取正,这样会导致对象排版出现空隙或者边缘覆盖等现象,需要格外小心

3.         表达式只可以引用直接父对象的位置

 

四、       各个坐标系的应用场合

在明确了几个坐标系,以及各个坐标系的相互转换后,下面举例说一下各个坐标系的应用场合:

 

l  元对象的鼠标事件,里面一般都附带了当前的鼠标位置(x,y),那么这个坐标就是属于对象坐标系的,也就是相对于对象的位置

l  元对象的拖放事件,里面附带了当前拖放到的位置,这个坐标是属于对象坐标系的

l  元对象的limitchild属性,假如父对象设置了limitchild,那么会限制子对象的区域超出父对象的区域,limitchild的都是在对象树坐标系的,也就是子对象abspos超出父对象abspos的区域会被剪裁掉

l  元对象的PushDirtyRect方法,需要指定一个脏矩形区域,那么该区域就是属于对象坐标系的

l  有些元对象里面可以设置一些表达式,比如FillObject的填充起始和结束,MaskObject的区域等,这些表达式关联的都是对象自身的pos,都是属于对象坐标系的

l  对象树的HitTest方法,需要指定想x,y坐标,那么该坐标就是属于对象树坐标系的

l  对象树的PushDirtyRect方法,需要指定一个脏矩形区域,那么该区域就是属于对象树坐标系的

 

从上面的例子,大家可以看到,一般情况下,几个坐标系的使用场景还是很明确的。大家不必刻意去区分就可以分辨出来怎么传递参数,怎么转换坐标等。如果在坐标转换这里遇到了问题,或者涉及到层次非常多的转换(比如从对象上一个点转换到所在屏幕上一个点),那么就需要小心处理一下了。

 

迅雷公司 版权所有 Copyright 2003-2010 Thunder Inc.All Rights Reserved. 意见反馈:xl7doc@xunlei.com