合成图面

注意

对于Windows 10上的应用,我们建议使用Windows。UI。合成 API 而不是 DirectComposition。 有关详细信息,请参阅 使用视觉对象层实现桌面应用的现代化

本主题介绍 Microsoft DirectComposition 支持的图面类型。

DirectComposition 逻辑图面

DirectComposition 公开 IDCompositionSurface 对象以表示逻辑组合图面。 DirectComposition 公开可用于创建、更新和删除这些逻辑图面的 API。 每个图面都可以与一个或多个视觉对象相关联。 应用程序负责管理逻辑图面的生存期。

更新逻辑图面

应用程序可以通过调用 BeginDraw 并在应用要更新的逻辑图面上指定矩形的大小和偏移量来更新逻辑图面。 DirectComposition 分配指定大小的矩形,然后返回应用程序绘制或更新所需的图面和相应的偏移量。 更新矩形的限制由图面大小绑定。 例如,40 到 100 像素图面的更新矩形最多可 (0,0,40,100 个) 。 此外,可更新区域由防护矩形强制实施。 由于一次只能有一个防护矩形,因此一次只能更新一个逻辑图面。 如果对 BeginDraw 的上一次调用后尚未调用 EndDrawSuspendDraw则 BeginDraw 将返回错误代码。 应用程序可以将提交调用 BeginDraw 添加到批处理,但在调用和提交 EndDraw 之前,它不会生效。

暂停对逻辑图面的更新

需要更新不同图面的应用程序可以在当前更新上调用 SuspendDraw ,然后调用 BeginDraw 以开始新的更新。 Microsoft DirectComposition 允许多个更新,但一次只能有一个更新处于活动状态。 这意味着需要在一个图面上调用 SuspendDrawEndDraw ,然后再在下一个图面上调用 BeginDraw 。 与 EndDraw 不同,提交的批处理可以包含处于 SuspendDraw 状态的图面,但在调用 EndDraw 之前,不会在屏幕上显示此类更新。

恢复逻辑图面的更新

应用程序可以通过调用 ResumeDraw 恢复对处于 SuspendDraw 状态的图面的更新。 此方法只能在挂起的图面上调用。

结束对逻辑图面的更新

调用 EndDrawCommit 是在屏幕上查看位图更新更改的唯一方法。 对 EndDraw 的每个调用都必须具有对 BeginDraw 的相应调用才能删除防护矩形。 逻辑图面将保留所有更新,直到调用 提交 。 还可以在处于 SuspendDraw 状态的图面上调用 EndDraw,因为 EndDraw 是隐式恢复/结束。 调用 EndDraw 后,更新的内容将呈现到屏幕并丢弃,以便可以重复使用更新的内存供以后更新使用。

使用逻辑图面的示例

以下示例描述了应用程序在创建由两个视觉对象组成的可视化树时需要执行的步骤,然后需要更新与视觉对象关联的两个逻辑图面的特定区域:

  1. 创建 DirectComposition 设备。
  2. 创建由根节点和视觉对象 1 和 2 组成的可视化树。
  3. 创建逻辑图面 1 和 2。
  4. 调用 SetContent 将逻辑图面与视觉对象 1 和 2 相关联。
  5. 在逻辑图面 1 的子矩形上调用 BeginDraw
  6. 在 DirectComposition 返回的偏移量处更新图面。
  7. 可选步骤:
    1. 在逻辑图面 1 上调用 SuspendDraw
    2. 在逻辑图面 2 的子分区上调用 BeginDraw
    3. 在 DirectComposition 返回的偏移量处更新图面。
    4. 在逻辑图面 2 上调用 EndDraw
    5. 在逻辑图面 1 上调用 ResumeDraw
  8. 在 DirectComposition 返回的偏移量处更新图面。
  9. 在逻辑图面 1 上调用 EndDraw
  10. 调用 提交

DirectComposition 虚拟图面

DirectComposition 公开 IDCompositionVirtualSurface 接口来表示虚拟图面,这是逻辑图面的集合, (磁贴) 以固定大小的磁贴排列在固定网格中。 应用程序指定创建时虚拟纹理的大小。 大小为虚拟图面建立边界。 图面可以与一个或多个视觉对象相关联。

初始化虚拟图面时,它不受实际分配的支持。 换句话说,它不保留任何位。 DirectComposition (分配磁贴,即应用程序开始更新图面后) 组合图面对象。 应用程序通过调用 BeginDraw 并指定与虚拟图面坐标相关的区域来更新虚拟图面。 然后,DirectComposition 分配必要的磁贴来保存更新,并返回要更新的合成图面和偏移量。

与逻辑图面一样,可以在虚拟图面上调用 BeginDrawSuspendDrawResumeDrawEndDraw 。 此外,DirectComposition 还公开可用于调整和剪裁现有虚拟图面的方法。

调整虚拟图面的大小

Resize 方法会更改虚拟图面的边界,这意味着任何新的更新或分配都必须属于由新大小设置的边界。 应用程序使用 Resize 告诉 DirectComposition,不再需要虚拟图面的特定区域,并且可以回收。 如果 Resize 收缩虚拟图面,则应用程序无法再更新新边界之外的区域。

下图显示了调整为 2-by-2 的 3 个虚拟图面。 红色区域表示作为调整大小操作的一部分丢弃的磁贴,内存由 DirectComposition 回收。 调整大小后,应用程序无法对红色区域进行更新,而无需再次调整虚拟图面的大小。

resizing a virtual surface

调整大小操作立即生效。 DirectComposition 不会等待应用程序调用 Commit 以进行重设大小更新。 例如,假设应用程序发出以下调用序列。

pVirtualSurface->Resize(0, 0);
pVirtualSurface->Resize(INT_MAX, INT_MAX);
pDevice->Commit();

在此示例中,应用程序在第一次调整大小时会丢失所有内容。 即使 在提交之前调用了第二个大小,第二个大小也不起作用。 在这种情况下,屏幕上没有显示任何内容。

剪裁虚拟图面

Trim 方法标识应用程序所需的虚拟图面区域。 它不会调整虚拟图面的边界大小,但它确实告诉 DirectComposition 当前需要分配哪些逻辑图面。

在下图中,绿色方块是应用程序的视区。 应用程序最初呈现到虚拟图面的前六个磁贴 (蓝色) , (视区中的浅灰色) 。 当虚拟图面所表示的页面滚动时,应用程序需要呈现最后六个磁贴。 应用程序调用 Trim 来指示最后六个磁贴定义的区域是内容所在的位置,而目前不需要其余部分。 然后,DirectComposition 可以选择回收最初表示前六个磁贴的逻辑图面, (深灰色) 。

trimming a virtual surface

DirectComposition 概念