WPF 互操作:“空域”和 Window 区域概述
更新:2007 年 11 月
“空域”是考虑互操作应用程序的两个部分如何共享公用顶级窗口内的呈现区域的一种概念方式。本主题说明“空域”概念如何影响演示设计以及关于 WPF 互操作应用程序的输入事项。
空域
在顶级窗口内,您可以形成这样的概念:每个包含互操作应用程序的技术之一的 HWND 都有自己的“空域”。窗口内的每个像素都只属于一个 HWND,这组成了该 HWND 的空域。(严格地说,如果有多个 WPF HWND,便会有多个 WPF 空域,但是,为了便于说明此概念,假定在本主题所给出的示例中只有一个空域。)空域概念暗含了这样一层含义:尝试在应用程序生存期内呈现于该像素之上的所有层或其他窗口都必须是同一呈现级技术的一部分。尝试在 Win32 之上呈现 WPF 像素会导致意外的结果,应当尽量在互操作 API 中禁止。
按示例说明空域
第一个示例说明了混合 Win32、DirectX 和 WPF 的应用程序。每一种技术都使用它自己单独的一组非重叠像素,因此没有空域问题。
但是假设您是从该应用程序开始,并创建由鼠标指针位置控制的动画,因此可以尝试呈现于上述三个区域中的任何一个区域之上。这样最终会侵犯空域。无论动画本身由哪一种技术负责,该技术都会侵犯其他两种技术的空域。下图对此进行了说明,其中绿色圆圈尝试在窗口中移动:
如果您尝试在不同的技术之间使用透明度/Alpha 混合,则也会发生空域冲突。在下图中,WPF 框侵犯了 Win32 和 DirectX 空域。因为该 WPF 框中的像素是半透明的,所以它们必须由 DirectX 和 WPF 联合拥有,但这是不可能的。因此这是另一种空域冲突的情况,不能生成:
前面三个示例使用矩形区域,但空域不一定是矩形。它可以是中空的矩形(例如,这里 Win32 空域是除 WPF 和 DirectX 空域之外的所有区域):
空域也可以根本不是矩形,或者是可通过 Win32 HRGN(区域)描绘的任何形状:
透明度和顶级窗口
窗口管理器进程(在 Windows Vista 和 Microsoft Windows XP 中)实际仅处理 Win32 HWND,因此每一个 WPF Window 都是一个 HWND。Window HWND 必须遵守适用于任何 HWND 的通用规则。在该 HWND 内,WPF 代码可以执行整个 WPF API 支持的任何操作。但是,对于与桌面上的其他 HWND 的交互,WPF 必须遵守 Win32 处理和呈现规则。WPF 通过使用 Win32 API 来支持非矩形窗口,HRGN 用于非矩形窗口,分层窗口用于每个像素的 Alpha。
不支持常量 Alpha 和颜色键。Win32 分层窗口的功能因平台而异。
分层窗口可以通过指定要应用于窗口中的每个像素的 Alpha 值来使整个窗口半透明。(Win32 实际上支持每个像素的 Alpha,但这在实际的程序中很难使用,因为在此模式下您需要自己绘制任何子 HWND,包括对话框和下拉菜单)。
WPF 支持 HRGN;但是,对于此功能,没有相应的托管 API。您可以使用平台调用和 HwndSource 来调用相关的 Win32 API。有关更多信息,请参见从托管代码调用本机函数
WPF 分层窗口在不同的操作系统上有不同的功能(这是因为 WPF 使用 DirectX 来呈现,而分层窗口主要设计用于 GDI 呈现,而不是用于 DirectX 呈现):
WPF 支持 Windows Vista 上的硬件加速分层窗口。Microsoft Windows XP 上的硬件加速分层窗口需要来自 Microsoft DirectX 的支持,因此功能将依赖于该计算机上的 Microsoft DirectX 版本。
WPF 不支持透明度颜色键,因为 WPF 无法保证准确地呈现您所请求的颜色,尤其在呈现采用了硬件加速时,更有可能产生颜色偏离。
如果运行在 Microsoft Windows XP 上,则 DirectX 图面之上的分层窗口会在 DirectX 应用程序呈现时闪烁。(实际的呈现序列是 Microsoft Windows 图形设备接口 (GDI) 隐藏分层窗口,然后 DirectX 进行绘制,之后 Microsoft Windows 图形设备接口 (GDI) 再重新显示分层窗口。)非 WPF 分层窗口也有此限制。