窗口剪切域可看作是一系列不相交的矩形的集合,这些集合限制了窗口可以输出的范围。本质上说,剪切域是一系列矩形的集合,凡是位于这个集合内的矩形区域,都是可以输出的。但是不在这个集合内的区域,则不能输出,必须被裁剪掉,否则会影响到其他应用程序的外观。在一个窗口被创建的时候,其剪切域初始化为窗口矩形,客户区的剪切域也初始化为窗口矩形(需要注意,这里不是客户区矩形,窗口客户区的剪切域与窗口的剪切域是完全一致的)。与整个窗口不同的是,客户区的上下文,其限定范围(通过x,y,width和height四个参数限制的矩形)为窗口的客户区,而不是整个窗口。
__WINDOW_CLIP_ZONE对象,定义了窗口剪切域中的一个矩形元素(后面把这个对象称为窗口剪切域元素),如下:
这个对象实际上定义了一个矩形。与矩形对象(RECT)不同的是,该对象还维护了两个指针,这两个指针把窗口剪切域元素连接到一个双向链表中,这个双向链表构成了窗口剪切域。另外,其名字之所以是ZONE而不是RECT,是为将来扩展的考虑。剪切域最简单的形态是一系列矩形的集合,但是不排除包含其他非矩形形状,比如椭圆形、三角形等。以后可通过扩展剪切域的定义,来支持其他几何形状。
为了方便实现窗口剪切域元素的合并,在上述双向链表中,剪切域元素是按照x的大小进行排序的。这样在向窗口剪切域中增加一个元素(即扩大了窗口剪切域的大小)的时候,首先会把该元素按照顺序插入到链表中,然后从插入位置的上一个位置开始,尝试执行一个合并操作。
窗口刚开始被创建的时候,其剪切域对象初始化为窗口的整个矩形。需要注意的是,即使窗口的状态是不显示的,该窗口也是有剪切域的,而且剪切域的状态,与可显示窗口是一样的。对于不可显示窗口的输出禁止操作,是通过设置窗口上下文对象(整个窗口的上下文和客户区上下文)的width和height为0,来达到禁止显示的目的。
一个窗口,只有在下列情形下,才会更新其剪切域:
(1)该窗口的子窗口被创建。
(2)该窗口的子窗口被销毁(或关闭)。
(3)该窗口的子窗口被隐藏(不显示)。
(4)该窗口的子窗口被移动。
(5)该窗口的子窗口被改变大小。
(6)窗口本身被改变大小。
(7)窗口本身被移动。
上述任何一种情形,都会导致系统做出如下的函数调用,以更新对应窗口的剪切域:
其中hWnd是待更新的剪切域所归属的窗口句柄,而newRect,则是一个新的屏幕矩形。最后一个参数dwUpdateMode,指明窗口剪切域的更新方式,目前定义的几种见表11-3。
表11-3 剪切域更新模式及含义
其中宏定义的前面三个字母(CZU),是Clip Zone Update的缩写,用于指明上面表格中定义的几个模式,只用于窗口剪切域的更新例程中。
其中在第三种情形中(CZU_MODE_MOVE),窗口的大小没有改变,改变的只是窗口的位置。这时候,newRect对象指明了新的窗口位置和大小,只不过此时的窗口大小(width和height)与原有窗口一致而已。这种情况下的处理是最简单的。Update WndClipZone例程只需要遍历整个剪切域元素列表,更新每个元素的起始位置(x和y)即可。
对于窗口大小被改变的情形(CZU_MODE_SIZE),实际上可分解为两个CZU_MODE_ADD操作。改变大小后的窗口矩形,减去原有的窗口矩形,可得到两个矩形,如图11-9所示。(www.xing528.com)
图11-9 窗口大小改变的剪切操作
这时候只需在窗口剪切域中,执行两次ADD操作(加入上图中两个新增的矩形)即可。
因此,对窗口剪切域的更新,最终会抽象成两种操作:ADD(加法)和MINUS(减法)。
窗口剪切域的加法操作如下:
在向窗口剪切域中加入剪切域元素的时候,除了把元素加入列表中,还需要考虑剪切域的合并操作。下列两种情形下,需要对窗口剪切域元素进行合并,以减少窗口剪切域中的元素数量,降低内存使用率并缩短遍历整个链表的时间,如图11-10所示。
图11-10 剪切域的加法操作
上述任何一种情形,都需要对连续的两个矩形进行合并。合并操作可抽象为下列两步:
(1)从链表中把两个矩形删除。
(2)把两个矩形合并后的新矩形,重新插入到链表中。
在重新插入到链表中的时候,有可能又会引发一次合并,比如在图11-10中,一个新的矩形插入在两个等高的矩形中间,且刚好占据中间的位置。这样就必须进行另一次合并操作。这实际上是一个递归过程,因此在实现的时候,也是通过递归函数来实现的。
窗口剪切域的减法操作如下:
窗口剪切域的减法操作,实际上也是可以转化为窗口剪切域的加法操作来实现的。如图11-11所示。
图11-11 剪切域的减法操作
在图11-11中,待减去的矩形(阴影表示)把原有的矩形分成了四个部分(待减去部分、左右各一个小的矩形、下面的一个矩形)。这样在操作的时候,可抽象为下列几步:
(1)从剪切域中删除与待减去矩形有交集的矩形。
(2)从删除的矩形中,减去目标矩形,这可能会得到另外的多个矩形。
(3)把执行步骤2中所得到的几个矩形,增加到窗口剪切域中(加法操作)。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。