(1)无效化一个区域
首先,使用一个 Invalidate()函数来使将要绘制的区域无效。记住窗口服务器跟踪每个窗口上的所有无效区域,并将绘图剪裁到整个无效区域。因此在进行应用程序发起的重绘之前,必须使将要重绘的区域无效,否则不会出现任何东西(除非该区域因为别的原因碰巧是无效的)。
(2)激活图形上下文
无效化绘制区域后,必须激活CONE系统的图形上下文。CCoeControl::ActivateGc()的代码如下所示。
通常情况下,仅仅是在控件的窗口上执行 gc.Activate(),告诉窗口服务器客户端接口使用CONE 的图形上下文来开始向它绘制。该函数也重置窗口图形上下文为默认设置。以后在第 17.7节,当讨论控件上下文时将解释其他情况。
(3)开始和结束重绘 在绘图之前,告诉窗口服务器将开始重绘某特定的区域。紧接着重绘之后,告诉窗口服务器已经完成重绘。当窗口服务器执行BeginRedraw()函数时,它有两个效果:
窗口服务器将剪裁区域设置为无效区域与屏幕上可见窗口区域的相交区域,无效区域即为传给BeginRedraw()的矩形(如果没有矩形传入,则为整个窗口);
然后服务器将BeginRedraw()指定的区域标记为有效(或者更精确地说,从它当前的无效区域中去掉传入BeginRedraw()的区域)。
此时,应用程序绘制代码必须覆盖BeginRedraw()所指定区域的每个像素。如果应用程序绘制代码包含对SetClippingRegion()的显式调用,如此指定的区域与在BeginRedraw()中计算的剪裁区域相交。当应用程序完成重绘时,调用EndRedraw()。这使窗口服务器能够删除在BeginRedraw()处理期间分配的区域对象。
(4)并发 你可能想知道为什么窗口服务器在BeginRedraw()而不是EndRedraw()内将区域标记为有效。原因是,Symbian 操作系统是一个多任务操作系统。如下所述的理论事件序列说明了为什么需要这个协议:
应用程序A发出开始重绘命令。受影响区域在A的窗口被标记为有效;
A开始绘制;
应用程序B来到前台,并且它的窗口覆盖A的窗口;
B终止,这时A的窗口再次显露;
无疑,A的窗口现在无效。窗口服务器同样将它标记成无效;
A继续重绘,并发出结束重绘命令。(任何绘制都将不显示在屏幕上。)
在这个事件序列的最后,被重新显露的A窗口的区域覆盖的屏幕区域处于一种任意状态。如果窗口服务器在EndRedraw()内将A的窗口标记为有效,窗口服务器将不会知道它仍然需要重绘。相反,如果窗口服务器在 BeginRedraw() 内将 A 的窗口标记为有效,那么在类似序列的末尾,窗口正确地标记为无效,因而能够被重绘。
你可能认为这种事件序列会不常见,但这的确有可能出现,因此系统必须正确处理。
【责任编辑:
董书 TEL:(010)68476606】