2019-7-3-WPF-使用-Composition-API-做高性能渲染
title | author | date | CreateTime | categories |
---|---|---|---|---|
WPF 使用 Composition API 做高性能渲染
|
lindexi
|
2019-07-03 10:30:57 +0800
|
2019-3-28 10:8:52 +0800
|
WPF 渲染
|
在 WPF 中很多小伙伴都会遇到渲染性能的问题,虽然 WPF 的渲染可以甩浏览器渲染几条街,但是还是支持不了游戏级的渲染。在 WPF 使用的 DX 只是优化等级为 9 和 DX 9 差不多的性能,微软在很多开发者的提议开放了现代渲染方法 Composition API 这是 UI 应用的里程碑的技术
现在这个技术只是最小可用版本,但是还是可以玩一下。
先更新自己的系统到1803或以上,如果是想成为 Windows 开发者,就需要自己的系统是最新的
然后下载安装 VS 2019 最新版本,安装 .NET Core 3.0 预览版
官方下载链接 VisualStudio 2019 .NET Core
下载运行代码
从 github 官方 https://github.com/Microsoft/Windows.UI.Composition-Win32-Samples 下载最新代码,尝试编译运行
打开 dotnet\WPF\HelloComposition
里面的解决方案,注意使用 VisualStudio 2019 打开
通过 Nuget 还原两个库,一个是 Microsoft.Windows.SDK.Contracts 这是一个包含在桌面使用的 Windows Runtime API 库和System.Numerics.Vectors 支持向量计算
这里的 HelloComposition 就是最简单的项目,可以通过这个项目了解使用方法
因为这个项目现在还是预览的,要做好使用命令行编译,在一开始发现了这个项目使用的是以前的 csproj 格式,同时也没法直接在 VisualStudio 2019 里面编译成功,于是我将这个项目格式修改为新的格式,通过命令行还原编译之后就可以在 VisualStudio 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
如果编译成功,那么就可以在 VisualStudio 2019 点击运行调试。如果编译失败,欢迎加入dotnet 职业技术学院交流
运行可以看到下面图片
项目主要代码
那么代码是如何写的?
可以看到主要的代码是 CompositionHostControl 这是一个很普通的 UserControl 控件,在这个控件的 Load 的时候,将自己的内容,也就是一个叫 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)
{
// If the user changes the DPI scale setting for the screen the app is on,
// the CompositionHostControl is reloaded. Don't redo this set up if it's
// already been done.
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 documentation
预览代码
主要用到类有三个
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 无法在这个范围放任何的像素,同时也存在焦点等问题
Using the Visual Layer with WPF
Windows.UI.Composition Namespace
特别感谢
- 蓝火火 告诉我通过 COM 方法不是通过 PInvoke 调用系统
2019-7-3-WPF-使用-Composition-API-做高性能渲染的更多相关文章
- WPF 使用 Composition API 做高性能渲染
在 WPF 中很多小伙伴都会遇到渲染性能的问题,虽然 WPF 的渲染可以甩浏览器渲染几条街,但是还是支持不了游戏级的渲染.在 WPF 使用的 DX 只是优化等级为 9 和 DX 9 差不多的性能,微软 ...
- Vue 3.0 Composition API - 中文翻译
Composition API 发布转载请附原文链接 https://www.cnblogs.com/zgh-blog/articles/composition_api.html 这两天初步了解了下 ...
- UWP Composition API - 锁定列的FlexGrid
需求是第一列锁定,那么怎么让锁定列不跟着滚动条向做移动呢? 其实很简单,让锁定列跟scrollviewer的滚动做反方向移动. 先看一下这个控件的模板,嗯,其实很简单,就是ListView的模板,不同 ...
- UWP Composition API - GroupListView(二)
还是先上效果图: 看完了上一篇UWP Composition API - GroupListView(一)的童鞋会问,这不是跟上一篇一样的吗??? 骗点击的?? No,No,其实相对上一个有更简单粗暴 ...
- UWP Composition API - GroupListView(一)
需求: 光看标题大家肯定不知道是什么东西,先上效果图: 这不就是ListView的Group效果吗?? 看上去是的.但是请听完需求.1.Group中的集合需要支持增量加载ISupportIncreme ...
- UWP Composition API - PullToRefresh
背景: 之前用ScrollViewer 来做过 PullToRefresh的控件,在项目一些特殊的条件下总有一些问题,比如ScrollViewer不会及时到达指定位置.于是便有了使用Compositi ...
- [UWP小白日记-12]使用新的Composition API来实现控件的阴影
前言 看了好久官方的Windows UI Dev Labs示例好久才有点心得,真是头大.(其实是英语幼儿园水平(⊙﹏⊙)b) 真的网上关于这个API的资料可以说几乎没有. 正文 首先用这东西的添加WI ...
- UWP Composition API - New FlexGrid 锁定行列
如果之前看了 UWP Jenkins + NuGet + MSBuild 手把手教你做自动UWP Build 和 App store包 这篇的童鞋,针对VS2017,需要对应更新一下配置,需要的童鞋点 ...
- UWP Composition API - RadialMenu
用Windows 8.1的童鞋应该知道OneNote里面有一个RadialMenu.如下图,下图是WIn10应用Drawboard PDF的RadialMenu,Win8.1的机器不好找了.哈哈,由于 ...
- Windows Composition API 指南 - 认识 Composition API
微软在 Windows 10中 面向通用 Windows 应用 (Universal Windows Apps, UWA) 新引入了一套用于用户界面合成的 API:Composition API.Co ...
随机推荐
- Jtopo使用中link中文字与link平行
修改源代码如下 //新增 a.translate(e ,f ); a.rotate(Math.atan((d.y-c.y)/(d.x-c.x))); //修改 a.fillText(this.text ...
- 菜鸟nginx源码剖析数据结构篇(三) 单向链表 ngx_list_t[转]
菜鸟nginx源码剖析数据结构篇(三) 单向链表 ngx_list_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csd ...
- python-爬免费ip并验证其可行性
前言 最近在重新温习python基础-正则,感觉正则很强大,不过有点枯燥,想着,就去应用正则,找点有趣的事玩玩 00xx01---代理IP 有好多免费的ip,不过一个一个保存太难了,也不可能,还是用我 ...
- ElasticSearch入门介绍之会当凌绝顶(一)
ElasticSearch也是一款非常优秀的开源的全文检索框架,以大名鼎鼎的Apache Lucene为基础,高度封装了更丰富,易用的API,同时与Apache Solr一样,提供了非常强大的分布式集 ...
- DOS批处理脚本
先概述一下批处理是个什么东东.批处理的定义,至今我也没能给出一个合适的----众多高手们也都没给出----反正我不知道----看了我也不一定信服----我是个菜鸟,当然就更不用说了:但我想总结出一个“ ...
- zip压缩工具类
java将有关zip压缩的内容都封装在java.util.zip宝中,用java实现zip压缩,不用考虑压缩算法,java已经将这些进行了封装 实际上用java实现zip压缩涉及的就是一个“输入输出流 ...
- 如何做系列(5)-james mail安装总结
安装james还是比较复杂的,我们在EC2上花费了差不多一天,发现不能发送邮件到外网,后续又陆续花了几天的时间,才成功搭建james邮件服务器. 现在愿意把我们的经历分享出来,让大家参考一下. 由于项 ...
- 程序员总数3W+,阿里巴巴首次公开2018代码数据报告
- javascript的Touch事件
js的touch事件,一般用于移动端的触屏滑动 $(function(){document.addEventListener("touchmove", _touch, false) ...
- (转载)My97 datepicker使用指南
这里先显示大家都可以看到的My97DatePicker的用法: WdatePicker日历控件使用方法(http://www.cnblogs.com/yuhanzhong/archive/2011/0 ...