32.2 回调机制,无效化和渲染 WM可在有或无回调例程时使用。大多数情况下,最好使用回调。 STemWin为窗口和窗口对象 (小工具)提供回调机制的根本概念是一个事件驱动系统。因为在大多数窗口式系统中,其原理是控制流不仅仅是从用户程序到图形系统,而且还从用户程序到图形系统,然后再通过用户程序提供的回调例程返回用户程序。此机制通常称为 “好莱坞原则”(“不要打电话给我们,我们会给你打电话的!”),窗口管理器需要它的主要目的是触发窗口重绘。这与传统编程相反,但是它能利用窗口管理器的无效化逻辑。 32.2.1 不使用回调函数 回调例程不是必须使用的,但是如果这样做,WM会失去管理窗口重绘(更新)的能力。也可能混合使用,例如让有些窗口使用回调,有些不使用。当然,如果窗口不使用回调机制,则由应用程序负责更新其内容。
32.2.2 使用回调函数 要创建带回调的窗口,必须有一个回调例程。创建窗口(cb参数)时该例程用作 WM_CreateWindow()函数的一部分。 回调例程必须具有以下原型: 原型 void callback(WM_MESSAGE * pMsg); 回调函数执行的操作取决于其收到的消息类型。上述原型通常后跟一个switch语句,它使用一个 或多个case语句为不同消息定义不同的行为 (通常至少是WM_PAINT)。 处理WM_PAINT消息 窗口收到WM_PAINT消息时,应重绘自身。将此消息发送到窗口前,WM确保它已被选定。 非透明窗口 (默认!)必须重绘其整个无效区域。 最简单的方式是重新着色窗口的整个区域。WM的裁剪机制确保了仅重绘无效区域。为了加速绘制过程,仅重绘无效区域非常有用。本章稍后描述了如何获得无效区域 (信息是消息的一部分)。另一方面,透明窗口不必重绘整个无效区域;它可让窗口区域部分不受影响。此不受影响的区域然后会变成透明。WM发送WM_PAINT消息到透明窗口之前,以下区域已经重绘 (通过发送一条WM_PAINT消息到下面窗口)。 警示:处理WM_PAINT时,不得执行某些操作 处理WM_PAINT消息时,回调例程除了重绘窗口的内容外,不得执行其它操作。处理WM_PAINT事件时,下列函数不能调用:WM_SelectWindow()、WM_Paint()、WM_DeleteWindow() 和 WM_CreateWindow()。更改窗口属性的其他任何函数也不能调用:WM_Move()、WM_Resize()等。 示例 创建一个自动重绘窗口的回调例程: void WinHandler(WM_MESSAGE * pMsg) { switch (pMsg->MsgId) { case WM_PAINT: GUI_SetBkColor(0xFF00); GUI_Clear(); GUI_DispStringAt("Hello world",0,0); break; default: WM_DefaultProc(pMsg); } } 请注意,WM_PRE_PAINT和WM_POST_PAINT消息在WM_PAINT消息发送前和后立即处理。
32.2.3 背景窗口重绘和回调 初始化窗口管理器期间,会创建一个包含整个LCD 区域的窗口作为背景窗口。此窗口的句柄为 WM_HBKWIN。WM不会自动重绘背景窗口的区域,因为没有默认的背景颜色。也就是说如果创建了另一个窗口然后将其删除,则删除的窗口仍然可见。需要指定例程WM_SetDesktopColor()以便为重绘背景窗口设置颜色。也可设置回调函数来处理此问题。如果如前所述创建然后删除了一个窗口,则回调例程将触发WM来确认背景窗口不再有效,并自动重绘它。后面会专门的做个例子给大家讲解这个问题。
32.2.4 无效化 无效化窗口或窗口的一部分会告诉WM该窗口的无效区域在下次调用GUI_Exec()或GUI_Delay()时应重绘。emWin的无效化例程不会重绘窗口的无效部分,只管理窗口的无效区域。 窗口的无效区域 对于每个窗口,WM只使用一个矩形来存储包含整个无效区域的最小矩形。例如,如果左上角的一小部分和右下角的一小部分变为无效,则整个窗口即无效。 使用无效化的原因 使用窗口无效化而非立即重绘每个窗口的优点是只绘制窗口一次,即使其被无效化多次。例如,如果窗口的多个属性需要更改(如背景颜色、字体和窗口大小),与所有属性都更改后重绘一次窗口相比,每个属性更改后立即重绘窗口需要更多的次数。 重绘无效窗口 函数GUI_Exec()重绘所有无效窗口。这通过向每个无效窗口发送一条或多条WM_PAINT消息完成。 大家不要小看上面讲的这几个概念,非常重要
32.2.5 渲染透明窗口 如果需要绘制透明窗口,则WM会自动确保在透明窗口收到WM_PAINT消息前绘制窗口的背景。方法为,在向透明窗口发送WM_PAINT消息前,首先重绘透明窗口无效区域下面的所有窗口区域。为确保窗口管理器能执行透明窗口的重绘,有必要响应WM_PAINT消息并重绘窗口。否则,不能保证透明窗口的外观是正确的。使用透明窗口比使用不透明窗口需要更多消耗CPU。如果需要考虑性能问题,尝试避免使用透明窗口或许是一个选择。
32.2.6 自动使用存储设备 窗口管理器的默认特性是向每个需要重绘的窗口发送一条WM_PAINT。这会导致闪变效应。为抑制这些每个窗口的闪变效应,可为重绘操作自动使用存储设备。方法为,在创建窗口时设置标记WM_CF_MEMDEV、使用函数WM_SetCreateFlags()设置默认创建标记,或使用函数WM_EnableMemdev()。WM然后会将WM_PAINT消息输出重定向到存储设备中,再复制到显示器中。如果整个窗口的内存不够,会自动使用分段。存储设备只是临时使用,在绘制操作完成后会移除。
32.2.7 自动使用多缓冲帧 WM可自动使用多帧缓冲 (如果可用),这可通过函数WM_MULTIBUF_Enable()实现。启用后,在绘制无效窗口前,窗口管理器会将所有绘制函数的输出重定向到不可见的后置缓冲。绘制最后一个无效窗口后,WM使后置缓冲可见。请注意,仅在显示驱动支持多缓冲,并且有至少够2帧缓冲使用的足够RAM时,该功能才可用。
32.2.8 自动使用显示驱动缓存 WM自动使用显示驱动缓存 (如果可用)。如果可用,它会在开始绘制无效窗口前锁定缓冲。最后一个窗口绘制完成后,WM解锁缓存。
|