本文来告诉大家一个新的技术DirectComposition,在 win7 之后(实际上是 vista),微软正在考虑一个新的渲染机制
在 Windows Vista 就引入了一个服务,桌面窗口管理器Desktop Window Manager,虽然从借助 C++ 进行 Windows 开发博客可以看到 DWM 不是一个好的方法,但是比之前好。
在 win8 的时候,微软提出了 DirectComposition ,这是一个新的方法。
在软件的渲染一直都是两个阵营,一个是使用直接渲染模式。直接渲染的例子是使用 Direct2D 和 Direct3D ,而直接通过 Dx api 的方式当然需要使用 C++ 和底层的 API ,这开发效率比较差。
在 1511 发布,微软告诉大家可以使用底层的 DirectComposition 接口,这样大家就可以通过 DirectComposition 做出好看的效果
在原来的 UWP 应用,大家很容易使用 xaml 来写一个界面,但是如果没有 xaml 那么如何创建一个界面。
我不会告诉大家去 new 一个控件,因为这样和使用之前的方法差不多。我会告诉大家如何从一个 Visual 开始画。
在 UWP 可以通过下面几个方式显示界面
通过 xaml 或者后台新建控件显示。这是最推荐的方法,本文下面的方法是不推荐的,但是可以让大家知道原理。使用 xaml 显示的元素一般都是继承 UIElement ,创建出来的元素可以带交互。
如果需要高性能的画图,通过 win2d 是一个很好的方法。大家也知道创建的win2d只是显示,不会有交互,如果需要交互需要自己写。虽然写一个交互很简单,但是如果没有使用框架,重复代码很多。
使用 DirectX APIs 来画 3d 的图片,但是现在需要一些 C++ 代码。
在 UWP 的显示,推荐使用 xaml 来写界面,原因是 xaml 是一个界面无关的代码,也就是无论是 C# 和 C++ 都可以使用。如果使用 C# 来写界面,那么代码就和 C# 合在一起,不能很好在 C++ 运行。而且使用xaml 写简单比使用C#更简单,在 vs 实时编译器可以看到界面效果。
也许大家会关系 fds 是如何做出来的,对于微软的设计,所有的 xaml 或者 win2d 的显示都是位图。这里的位图不是大家想的 bitmapImage 而是显示的一个说法,微软对所有的位图输出到 DirectComposition 。微软的 DirectComposition 在官方是这样说 “DirectComposition 组件使开发者能够进行高性能的位图合成,并附加变换、特效以及动画等各种效果,以此打造出更为复杂、生动、流畅的用户界面。DirectComposition 利用图形硬件的加速特性可以进行与 UI 线程无关的渲染处理,支持 2D 仿射变换、3D 透视变换等多种变换,以及剪切、不透明等基本特效”。
翻译参见 Windows Composition API 指南 - 认识 Composition API 感谢大神。
那么是不是可以通过Composition显示元素,自己来写 UWP 框架。
在开始告诉大家写 UWP 框架之前,先给大家一个简单的例子,如何应用 DirectComposition 。
例子
之前写的一个简单的动画是一个好看效果,请看 win10 uwp 进度条 WaveProgressControl
下面来通过删除所有 xaml 文件,从头自己写。
创建工程
首先创建一个 UWP 项目,注意选择比较高的目标。
如何写显示
现在创建项目,删除所有的 app 和 mainpage 类。重新创建一个类。
只要支持显示,那么就可以完成一半了,因为 UWP 的元素显示都是通过布局找到元素显示的位置。当然这里不会提到 Translate 等。然后元素通过调用DrawContex告诉显卡需要显然的图形。然后在加上用户的输入,就构成了框架。
虽然一个框架比上面说的复杂很多,但是在写 Avalonial 的时候,大神告诉我,实际上一个界面框架主要的就是显示和交互。本文不会告诉大家如何写交互,只是告诉大家如何显示。
删除了所有的自动生成的代码,现在创建一个类 View ,用来显示。
下面代码的意思请看 【Win 10 应用开发】UI Composition 札记(一):视图框架的实现 - 东邪独孤 - 博客园
using System.Numerics;
using Windows.ApplicationModel.Core;
using Windows.UI;
using Windows.UI.Composition;
using Windows.UI.Core;
namespace HmeucHsvv
{
internal class View : IFrameworkView, IFrameworkViewSource
{
public void SetWindow(CoreWindow window)
{
_compositor = new Compositor();
_compositionTarget = _compositor.CreateTargetForCurrentView();
// 创建一个容器,用来向他的 Children 添加 Visual 显示复杂的元素
var container = _compositor.CreateContainerVisual();
_compositionTarget.Root = container;
// 创建 SpriteVisual ,这个类不仅是一个容器,同时本身也是可以画出来
var visual = _compositor.CreateSpriteVisual();
// 告诉这个元素的大小和左上角,所以这个就是一个矩形,而且设置颜色
visual.Size = new Vector2(100, 100);
visual.Offset = new Vector3(10, 10, 0);
visual.B