WPF 使用 Composition API 做高性能渲染

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 获取最新代码,并尝试编译运行。

打开

dotnetWPFHelloComposition

目录中的解决方案,确保使用 Visual Studio 2019 打开。

通过 NuGet 还原两个库:Microsoft.Windows.SDK.Contracts,这是一个包含桌面使用的 Windows Runtime API 的库,以及 System.Numerics.Vectors,用于支持向量计算。

HelloComposition 是一个最简单的项目,可以通过这个项目了解使用方法。

由于这个项目目前仍处于预览阶段,建议使用命令行进行编译。我在开始时发现这个项目使用的是旧版的 csproj 格式,并且无法直接在 Visual Studio 2019 中编译成功。因此,我将项目格式更新为新格式,通过命令行还原并编译后,就可以在 Visual Studio 2019 中进行调试。

修改方法是用以下代码替换 HelloComposition.csproj 文件,并删除

HelloCompositionPropertiesAssemblyInfo.cs

文件:

      WinExe    netcoreapp3.0    true              10.0.17763.144-preview              4.5.0      

如果不想自己修改 csproj 文件,可以下载我修改后的版本,并通过命令行进行还原和编译:

# 进入 HelloComposition.sln 所在的文件夹dotnet restore # 如果还原失败,可以参考我收集的各种公有 NuGet 源:https://walterlv.com/post/public-nuget-sources.htmldotnet build

如果编译成功,就可以在 Visual Studio 2019 中点击运行调试。如果编译失败,欢迎加入 .NET 职业技术学院交流群。

运行后可以看到以下图片:

WPF 使用 Composition API 做高性能渲染

项目主要代码是如何编写的呢?

主要代码集中在 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

方法中返回了 Compositor 字段,其使用方式与 UWP 相同。

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 文档。

预览代码中主要用到的类有三个:

CompositionHost:连接 WPF 的渲染和 UWP 的 Visual Layer,也是这个项目的主要代码。官方建议直接复制这个类中的代码,参考 Create an HwndHost derived class to host composition elements。CompositionHostControl:使用封装后的方法,简单介绍如何添加 Visual 和动画。主窗口:里面放了一个按钮和 CompositionHostControl,代码非常简单。

尽管可以在 WPF 中使用 Composition API 制作出美观的界面,但由于主要技术是通过 HwndHost 方法,这种方法尚未正式使用,因此存在以下不足:

特效依赖于 Win2d,但目前 Win2d 尚未支持桌面的 NuGet 库,需要编译源代码。不过很快就可以通过 NuGet 直接使用。如果需要交互命中测试,需要在代码中计算 Visual Layer 的 Bounds。与在 UWP 中通过 XAML 的方法简单绑定对应的命中测试相比,这并不简单。不过很快就会有封装的方法。目前的 Visual Layer 尚未支持渲染文本,但可以通过 SharpDX 的方法渲染,很快就可以原生支持。由于使用的是 Host 技术,不能在 DPI 修改时自动缩放,需要编写大量代码进行适配。

如果上述几个问题都可以解决,那么下面的问题就是原理上的问题。由于使用了 HwndHost 方法,使用了两种渲染方法,在使用 UWP 渲染方法的范围内,窗口的最上层将无法放置任何 WPF 的像素,同时也存在焦点等问题。

以上就是WPF 使用 Composition API 做高性能渲染的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/175594.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月1日 04:50:29
下一篇 2025年11月1日 04:52:29

相关推荐

  • Uniapp 中如何不拉伸不裁剪地展示图片?

    灵活展示图片:如何不拉伸不裁剪 在界面设计中,常常需要以原尺寸展示用户上传的图片。本文将介绍一种在 uniapp 框架中实现该功能的简单方法。 对于不同尺寸的图片,可以采用以下处理方式: 极端宽高比:撑满屏幕宽度或高度,再等比缩放居中。非极端宽高比:居中显示,若能撑满则撑满。 然而,如果需要不拉伸不…

    2025年12月24日
    400
  • 如何让小说网站控制台显示乱码,同时网页内容正常显示?

    如何在不影响用户界面的情况下实现控制台乱码? 当在小说网站上下载小说时,大家可能会遇到一个问题:网站上的文本在网页内正常显示,但是在控制台中却是乱码。如何实现此类操作,从而在不影响用户界面(UI)的情况下保持控制台乱码呢? 答案在于使用自定义字体。网站可以通过在服务器端配置自定义字体,并通过在客户端…

    2025年12月24日
    800
  • 如何在地图上轻松创建气泡信息框?

    地图上气泡信息框的巧妙生成 地图上气泡信息框是一种常用的交互功能,它简便易用,能够为用户提供额外信息。本文将探讨如何借助地图库的功能轻松创建这一功能。 利用地图库的原生功能 大多数地图库,如高德地图,都提供了现成的信息窗体和右键菜单功能。这些功能可以通过以下途径实现: 高德地图 JS API 参考文…

    2025年12月24日
    400
  • 如何使用 scroll-behavior 属性实现元素scrollLeft变化时的平滑动画?

    如何实现元素scrollleft变化时的平滑动画效果? 在许多网页应用中,滚动容器的水平滚动条(scrollleft)需要频繁使用。为了让滚动动作更加自然,你希望给scrollleft的变化添加动画效果。 解决方案:scroll-behavior 属性 要实现scrollleft变化时的平滑动画效果…

    2025年12月24日
    000
  • 如何为滚动元素添加平滑过渡,使滚动条滑动时更自然流畅?

    给滚动元素平滑过渡 如何在滚动条属性(scrollleft)发生改变时为元素添加平滑的过渡效果? 解决方案:scroll-behavior 属性 为滚动容器设置 scroll-behavior 属性可以实现平滑滚动。 html 代码: click the button to slide right!…

    2025年12月24日
    500
  • 如何选择元素个数不固定的指定类名子元素?

    灵活选择元素个数不固定的指定类名子元素 在网页布局中,有时需要选择特定类名的子元素,但这些元素的数量并不固定。例如,下面这段 html 代码中,activebar 和 item 元素的数量均不固定: *n *n 如果需要选择第一个 item元素,可以使用 css 选择器 :nth-child()。该…

    2025年12月24日
    200
  • 使用 SVG 如何实现自定义宽度、间距和半径的虚线边框?

    使用 svg 实现自定义虚线边框 如何实现一个具有自定义宽度、间距和半径的虚线边框是一个常见的前端开发问题。传统的解决方案通常涉及使用 border-image 引入切片图片,但是这种方法存在引入外部资源、性能低下的缺点。 为了避免上述问题,可以使用 svg(可缩放矢量图形)来创建纯代码实现。一种方…

    2025年12月24日
    100
  • 如何让“元素跟随文本高度,而不是撑高父容器?

    如何让 元素跟随文本高度,而不是撑高父容器 在页面布局中,经常遇到父容器高度被子元素撑开的问题。在图例所示的案例中,父容器被较高的图片撑开,而文本的高度没有被考虑。本问答将提供纯css解决方案,让图片跟随文本高度,确保父容器的高度不会被图片影响。 解决方法 为了解决这个问题,需要将图片从文档流中脱离…

    2025年12月24日
    000
  • CSS元素设置em和transition后,为何载入页面无放大效果?

    css元素设置em和transition后,为何载入无放大效果 很多开发者在设置了em和transition后,却发现元素载入页面时无放大效果。本文将解答这一问题。 原问题:在视频演示中,将元素设置如下,载入页面会有放大效果。然而,在个人尝试中,并未出现该效果。这是由于macos和windows系统…

    2025年12月24日
    200
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 如何利用 CSS 选中激活标签并影响相邻元素的样式?

    如何利用 css 选中激活标签并影响相邻元素? 为了实现激活标签影响相邻元素的样式需求,可以通过 :has 选择器来实现。以下是如何具体操作: 对于激活标签相邻后的元素,可以在 css 中使用以下代码进行设置: li:has(+li.active) { border-radius: 0 0 10px…

    2025年12月24日
    100
  • 如何模拟Windows 10 设置界面中的鼠标悬浮放大效果?

    win10设置界面的鼠标移动显示周边的样式(探照灯效果)的实现方式 在windows设置界面的鼠标悬浮效果中,光标周围会显示一个放大区域。在前端开发中,可以通过多种方式实现类似的效果。 使用css 使用css的transform和box-shadow属性。通过将transform: scale(1.…

    2025年12月24日
    200
  • 如何用HTML/JS实现Windows 10设置界面鼠标移动探照灯效果?

    Win10设置界面中的鼠标移动探照灯效果实现指南 想要在前端开发中实现类似于Windows 10设置界面的鼠标移动探照灯效果,有两种解决方案:CSS 和 HTML/JS 组合。 CSS 实现 不幸的是,仅使用CSS无法完全实现该效果。 立即学习“前端免费学习笔记(深入)”; HTML/JS 实现 要…

    2025年12月24日
    000
  • 为什么我的 Safari 自定义样式表在百度页面上失效了?

    为什么在 Safari 中自定义样式表未能正常工作? 在 Safari 的偏好设置中设置自定义样式表后,您对其进行测试却发现效果不同。在您自己的网页中,样式有效,而在百度页面中却失效。 造成这种情况的原因是,第一个访问的项目使用了文件协议,可以访问本地目录中的图片文件。而第二个访问的百度使用了 ht…

    2025年12月24日
    000
  • 如何用前端实现 Windows 10 设置界面的鼠标移动探照灯效果?

    如何在前端实现 Windows 10 设置界面中的鼠标移动探照灯效果 想要在前端开发中实现 Windows 10 设置界面中类似的鼠标移动探照灯效果,可以通过以下途径: CSS 解决方案 DEMO 1: Windows 10 网格悬停效果:https://codepen.io/tr4553r7/pe…

    2025年12月24日
    000
  • 如何用前端技术实现Windows 10 设置界面鼠标移动时的探照灯效果?

    探索在前端中实现 Windows 10 设置界面鼠标移动时的探照灯效果 在前端开发中,鼠标悬停在元素上时需要呈现类似于 Windows 10 设置界面所展示的探照灯效果,这其中涉及到了元素外围显示光圈效果的技术实现。 CSS 实现 虽然 CSS 无法直接实现探照灯效果,但可以通过以下技巧营造出类似效…

    2025年12月24日
    000
  • 使用CSS mask属性指定图片URL时,为什么浏览器无法加载图片?

    css mask属性未能加载图片的解决方法 使用css mask属性指定图片url时,如示例中所示: mask: url(“https://api.iconify.design/mdi:apple-icloud.svg”) center / contain no-repeat; 但是,在网络面板中却…

    2025年12月24日
    000
  • 如何用CSS Paint API为网页元素添加时尚的斑马线边框?

    为元素添加时尚的斑马线边框 在网页设计中,有时我们需要添加时尚的边框来提升元素的视觉效果。其中,斑马线边框是一种既醒目又别致的设计元素。 实现斜向斑马线边框 要实现斜向斑马线间隔圆环,我们可以使用css paint api。该api提供了强大的功能,可以让我们在元素上绘制复杂的图形。 立即学习“前端…

    2025年12月24日
    000
  • 图片如何不撑高父容器?

    如何让图片不撑高父容器? 当父容器包含不同高度的子元素时,父容器的高度通常会被最高元素撑开。如果你希望父容器的高度由文本内容撑开,避免图片对其产生影响,可以通过以下 css 解决方法: 绝对定位元素: .child-image { position: absolute; top: 0; left: …

    2025年12月24日
    000
  • CSS 帮助

    我正在尝试将文本附加到棕色框的左侧。我不能。我不知道代码有什么问题。请帮助我。 css .hero { position: relative; bottom: 80px; display: flex; justify-content: left; align-items: start; color:…

    2025年12月24日 好文分享
    200

发表回复

登录后才能评论
关注微信