在 wpf 中,许多开发者会遇到渲染性能的问题。尽管 wpf 的渲染性能比浏览器渲染要高出不少,但仍然无法满足游戏级别的渲染需求。wpf 使用的 directx 版本仅优化到 9 级别,与 directx 9 的性能相当。鉴于开发者的需求,微软推出了现代渲染方法——composition api,这是一个 ui 应用的里程碑技术。
目前,这个技术还处于最小可用版本阶段,但已经可以尝试使用。
首先,需要将系统更新到 1803 或更高版本。如果您想成为 Windows 开发者,则需要确保系统是最新的。
接着,下载并安装 Visual Studio 2019 的最新版本,并安装 .NET Core 3.0 的预览版。
官方下载链接:Visual Studio 2019 和 .NET Core
下载运行代码,可以从 GitHub 官方仓库 https://www.php.cn/link/508cb643c0ea0e2f6451bba7aa5cfb64 获取最新代码,并尝试编译运行。
打开
dotnet\WPF\HelloComposition
通过 NuGet 还原两个库:Microsoft.Windows.SDK.Contracts,这是一个包含桌面使用的 Windows Runtime API 的库,以及 System.Numerics.Vectors,用于支持向量计算。
HelloComposition 是一个最简单的项目,可以通过这个项目了解使用方法。
由于这个项目目前仍处于预览阶段,建议使用命令行进行编译。我在开始时发现这个项目使用的是旧版的 csproj 格式,并且无法直接在 Visual Studio 2019 中编译成功。因此,我将项目格式更新为新格式,通过命令行还原并编译后,就可以在 Visual Studio 2019 中进行调试。
修改方法是用以下代码替换 HelloComposition.csproj 文件,并删除
HelloComposition\Properties\AssemblyInfo.cs
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.Contracts">
<Version>10.0.17763.144-preview</Version>
</PackageReference>
<PackageReference Include="System.Numerics.Vectors">
<Version>4.5.0</Version>
</PackageReference>
</ItemGroup>
</Project>如果不想自己修改 csproj 文件,可以下载我修改后的版本,并通过命令行进行还原和编译:
# 进入 HelloComposition.sln 所在的文件夹 dotnet restore # 如果还原失败,可以参考我收集的各种公有 NuGet 源:https://walterlv.com/post/public-nuget-sources.html dotnet build
如果编译成功,就可以在 Visual Studio 2019 中点击运行调试。如果编译失败,欢迎加入 .NET 职业技术学院交流群。
运行后可以看到以下图片:

项目主要代码是如何编写的呢?
主要代码集中在 CompositionHostControl 这个普通的 UserControl 控件中。在控件加载时,将其内容,即一个名为 CompositionHostElement 的 Border 的内容,修改为 CompositionHost 的方法。
CompositionHost 是一个自定义的 HwndHost 方法,通过 HwndHost 可以指定为 Host 一个句柄,从而让 WPF 使用两种不同的渲染方法。
在 CompositionHost 中创建了一个新窗口,并使用 HwndHost 将其显示在 WPF 窗口之上。因此,使用 CompositionHost 的控件将显示在其他任何 WPF 控件的上面,在 CompositionHost 控件的 Bounds 范围内,不能使用其他 WPF 控件。这与在 WPF 中使用其他渲染方法的窗口类似,也是在 WPF 中使用 WinForms 或 UWP 控件的技术。
CompositionHost 的主要代码是 InitComposition 方法,在这里通过黑科技方法创建了 Composition。由于我不了解这些黑科技,所以就跳过了。
跳过这个类后,其余代码非常简单,可以看到方法接口与 UWP 类似。在
CompositionHostControl_Loaded
private void CompositionHostControl_Loaded(object sender, RoutedEventArgs e)
{
// 如果用户更改了屏幕的 DPI 缩放设置,CompositionHostControl 将重新加载。
// 如果已经设置过,则不重复设置。
if (compositionHost is null)
{
currentDpi = VisualTreeHelper.GetDpi(this);
compositionHost = new CompositionHost(CompositionHostElement.ActualHeight, CompositionHostElement.ActualWidth);
// 手动高亮,下面的代码将 CompositionHostElement 这个 Border 的内容修改为 CompositionHost 这个 HwndHost,通过 Host 一个窗口的方法
CompositionHostElement.Child = compositionHost;
// 手动高亮,下面的代码返回 Compositor 字段
compositor = compositionHost.Compositor;
// 手动高亮,下面的代码返回 ContainerVisual 字段
containerVisual = compositor.CreateContainerVisual();
compositionHost.Child = containerVisual;
}
}在点击按钮时,创建一个 SpriteVisual 并加入到 ContainerVisual 中,然后进行 Vector3KeyFrameAnimation 动画。
这里的代码接口与 UWP 相同,因此不再详细介绍如何使用。
通过 HwndHost 方法获取一个窗口的句柄并不是直接在 WPF 中使用 Composition,而是在创建一个窗口时使用 Composition,因为 WPF 的渲染与 Composition 的渲染不同。
由于使用了这种技术,会存在一些问题,下面将详细介绍。
通过 COM 等方法调用额外的系统相关接口,如果只是创建一个空白窗口,是无法直接使用 Composition API 的,需要使用一些黑科技,这些代码都在
CompositionHost
如果想了解更多,请参考 Using the Visual Layer with WPF。
将 Visual Layer 的内容封装在 WPF 的用户控件中,CompositionHostControl 这个用户控件使用了封装的 Visual Layer,其内部代码与 UWP 相同。
如何使用可以参考 UWP 的 Visual Layer 文档。
预览代码中主要用到的类有三个:
尽管可以在 WPF 中使用 Composition API 制作出美观的界面,但由于主要技术是通过 HwndHost 方法,这种方法尚未正式使用,因此存在以下不足:
如果上述几个问题都可以解决,那么下面的问题就是原理上的问题。由于使用了 HwndHost 方法,使用了两种渲染方法,在使用 UWP 渲染方法的范围内,窗口的最上层将无法放置任何 WPF 的像素,同时也存在焦点等问题。
以上就是WPF 使用 Composition API 做高性能渲染的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号