使用 Win 2D 组件,就可以很轻松地绘制各种图形,哪怕你没有 D2D 相关基础,也不必写很复杂的 C++ 代码。

先来说说如何获取 Win 2D 组件。很简单,创建 UWP 应用项目后,你打开“解决方案资源管理器”窗口,然后在【引用】节点上右击,从快捷菜单中选择【管理 Nuget 程序包】命令,在打开的窗口中搜索“Win 2D”,然后安装带有 uwp 标识的那个就可以了。

顺便说一下,nuget 的包缓存在你的用户文件夹下,就是系统盘下的 \users\xxx,xxx是你登录系统的用户名,在文件夹下有个 .nuget 目录,\packages 子目录下就是缓存的包,大小取决你安装的组件,大的时候 4、5 个G也有的。

在你的应用项目中,VS 只是创建了一个 JSON 文件来描述你引用的组件,Win 2D 添加引用成功后,你的引用列表应该是这样的。

你如果看到 Win2D.uwp 这个项目,那就没问题了。

不过,你得注意,直接双击它是无法在“对象浏览器”中查看的,你可以这样:打开“对象浏览器”窗口,然后把浏览的子集改为“我的解决方案”,这样,你就能看到你当前项目中所有引用的组件的类型结构了。

现在,你就能看到 Win2D 库的基本内容了。

Microsoft.Graphics.Canvas 以及它的子命名空间都是 Win2D 组件中的类型。

其实,使用 Win2D 组件,你完全可以很简单地绘制各种玩意儿,因为在 Microsoft.Graphics.Canvas.UI.Xaml 命名空间下,直接就提供了一些控件,你可以直接用到 XAML 文档中,然后要画什么就用代码画就行了。比如,我介绍两个比较典型的。

* CanvasControl —— 可以绘制各种你想要的东东,它就相当于一块画布,用代码绘制时须处理 Draw 事件,然后就在事件处理代码中随便 draw。

* CanvasAnimatedControl —— 跟上面的那个家伙差不多,只是它可以在你绘制的内容上产生动画。

大伙会看到,这两个控件都有一个 CreateResources 事件,用来干什么鸟的呢?它的作用是这样的,你可以在处理这个事件的代码中实例化一些资源,这些资源一般在绘制过程不会频繁改动的,比如加载的某个图片,某个画刷等。

下面给大伙简单演示一下 CanvasControl 控件的用法。

在 XAML 文档中先要引入命名空间。

<Page
……
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
……
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"> </Page>

然后就可以用了。

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<canvas:CanvasControl Draw="OnDraw"/>
</Grid>

接着处理 Draw 事件,我们画上几笔试试手。要画东东,我们要用到 Microsoft.Graphics.Canvas 命名空间下的另一个类——CanvasDrawingSession,它公开了许多 Draw 和 Fill 方法,Draw 是画出某个东东,Fill 是填充一个区域。

        private void OnDraw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
{
using (CanvasDrawingSession dss = args.DrawingSession)
{
// 画线
dss.DrawLine(12f, 15f, 335f, 408f, Colors.DarkBlue, 5.5f);
// 画矩形
dss.DrawRectangle(55f, 190f, 465f, 369f, Colors.Gold, 8f);
// 画圆
dss.DrawEllipse(350f, 350f, 200f, 260f, Colors.Orange, 5f);
}
}

随便画几下,纯属鬼画符。效果如下图所示。

但是,我们今天的主题是跟 UI Composition 有关的,虽然上述绘图法很超逸,却不是咱们今天的主题。我们下面要做的,是使用 Composition API 来呈现自己绘制的内容。

大伙伴们可以思考一下,要在 Composition 组装的对象上画东西,需要什么?前面咱们说过,你得有个 Brush,在 Composition API 中,只有一个画刷可以呈现自己绘制的内容,那就是 CompositionSurfaceBrush。

要创建 CompositionSurfaceBrush 实例容易,调用一下 Compositor.CreateSurfaceBrush 方法就行了。但问题的核心不在此,而在于,CompositionSurfaceBrush 画刷创建后是空的,要能够呈现内容,还得需要给 Surface 属性赋个值,它是一个实现了 ICompositionSurface 接口的类型,在 Composition API 中,实现了该接口的只有一个类:CompositionDrawingSurface。然而,你看到了,这个类是没有构造函数公开的,它是由 CompositionGraphicsDevice 类的 CreateDrawingSurface 方法创建的。

好,现在我们可以理一下思路了。

1、你必须想方设法得到一个 CompositionGraphicsDevice 实例,可该类没公开的构造函数,咋办?所以才要使用 Win2D,稍后再说,Win2D 会有办法获得这个实例的。

2、调用 CompositionGraphicsDevice 实例的 CreateDrawingSurface 或 CreateDrawingSurface2 方法创建 CompositionDrawingSurface

实例。

3、在新创建的 CompositionDrawingSurface 实例上画东西。这个也要用到 Win2D。

4、使用 Compositor 的静态方法直接创建 CompositionSurfaceBrush 对象,并与上面画好的 CompositionDrawingSurface 关联。

5、把这个画刷(CompositionSurfaceBrush)与可视化元素关联,比如,SpriteVisual类就有一个 Brush 属性。

如此一来,我们找到了两个难点:a、如何创建 CompositionGraphicsDevice ; b、如何在 Surface 上画东西(此 Surface 非彼 Surface)。

借助 Win2D,可以解决以上两个难题。我们不讲理论的,下面用实例来说明。

首先,在 XAML 文档中随便声明一个元素,只要是 UIElement 的子类就行。

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas Name="myCvs"/>
</Grid>

记得分配一个名字,待会在代码中要访问。

随后,我们就可以开始作画了。

        void DrawSomething()
{
// 获取 XAML 元素上的 Visual
Visual canvasVisual = ElementCompositionPreview.GetElementVisual(myCvs);
// 获取 Compositor 对象
Compositor compos = canvasVisual.Compositor;
// 创建 GraphicsDevice
CompositionGraphicsDevice graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(compos, CanvasDevice.GetSharedDevice());
// 创建 Surface
// 画布的大小
SizeInt32 cvsize = new SizeInt32
{
Width = ,
Height =
};
CompositionDrawingSurface surface = graphicsDevice.CreateDrawingSurface2(cvsize, Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied);
// 开始绘画
using (CanvasDrawingSession dss = CanvasComposition.CreateDrawingSession(surface))
{
// 刷墙,把墙面刷成黑色
dss.Clear(Colors.Black);
// 画一个圆
dss.DrawEllipse(210f, 190f, 80f, 80f, Colors.Yellow, 4f);
// 再画一个椭圆
dss.DrawEllipse(230f, 200f, 160f, 95f, Colors.SkyBlue, 3.5f);
// 填充一块区域
dss.FillRectangle(400f, 250f, 150f, 100f, Colors.Pink);
}
// 创建 surface 画刷
CompositionSurfaceBrush sfbrush = compos.CreateSurfaceBrush(surface);
// 创建一个支持画刷的可视化对象
SpriteVisual newVisual = compos.CreateSpriteVisual();
// 设置画刷
newVisual.Brush = sfbrush;
// 注意要设置可视化对象的大小
ExpressionAnimation anim = compos.CreateExpressionAnimation();
anim.Expression = "parn.Size";
anim.SetReferenceParameter("parn", canvasVisual);
newVisual.StartAnimation("Size", anim);
// 最后别忘了把新的可视化对象插入对象树
ElementCompositionPreview.SetElementChildVisual(myCvs, newVisual);
}

我们上篇中讲过的,与 XAML 交互,使用 ElementCompositionPreview辅助类可以获得与 XAML 元素对应的 Visual 实例,这样我们也能得到相关的 Compositor 对象了。

注意创建 CompositionGraphicsDevice 实例要借助 Win2D 的 CanvasComposition 类(位于 Microsoft.Graphics.Canvas.UI.Composition 命名空间),在调用 CreateCompositionGraphicsDevice 方法时,你除了得提供关联的 Compositor 对象外,还得有一个兼容的 CanvasDevice 对象。这个 CanvasDevice 对象有个很TMD简单的获取方法,就是直接调用它的 GetSharedDevice 静态方法。

好了,有了 CompositionGraphicsDevice 实例,那创建 CompositionDrawingSurface对象就好办了,就像这样。

 CompositionDrawingSurface surface = graphicsDevice.CreateDrawingSurface2(cvsize, Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied);

CreateDrawingSurface 和 CreateDrawingSurface2 都可以,带“2”的是使用整数来表示像素值。

调用这个方法最麻烦的后面两个参数,它们都是枚举值,如果值设置不当会发生异常,所以,如果出错了,你就得调整了。一般来说,在屏幕上显示的东东,我们会选择 BGRA 的顺序,因为这个顺序呈现出来不会偏色,尤其是图像,如果用 RGBA 就会偏色。B8G8R8A8 表示都用8位的值,也就是一个字节,这个我们平时处理一般图形也够用了(即32位颜色)。

接下来就是用 CanvasDrawingSession 来画你想画的各种玩意儿,画完后要创建一个 CompositionSurfaceBrush 对象,并且要与刚刚画好的 surface 对象关联。

最后用这个画刷填充一个支持画刷的可视化对象即可,如 SpriteVisual。记住,一定要设置对象的 Size 属性,因为默认值是0,不然它不会显示出来的,这里呢,我直接用一个表达式动画,让它的大小跟随 Canvas 的大小。

这个方法封装好后,可以在适当的地方调用,以绘制内容,比如页面类的构造函数中。

        public MainPage()
{
this.InitializeComponent();
DrawSomething();
}

好了,看看效果吧。

OK,今天的内容就说到这里了。

【Win 10 应用开发】UI Composition 札记(四):绘制图形的更多相关文章

  1. iOS开发UI篇—Quartz2D使用(图形上下文栈)

    iOS开发UI篇—Quartz2D使用(图形上下文栈) 一.qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的? 说明: 新建一个项目,自定义一个view类和storyboard关联后, ...

  2. 【Win 10 应用开发】UI Composition 札记(三):与 XAML 集成

    除了 DirectX 游戏开发,我们一般很少单独使用 UI Composition ,因此,与 XAML 互动并集成是必然结果.这样能够把两者的优势混合使用,让UI布局能够更灵活. 说到与 XAML ...

  3. 【Win 10 应用开发】UI Composition 札记(一):视图框架的实现

    在开始今天的内容之前,老周先说一个问题,这个问题记得以前有人提过的. 设置 Windows.ApplicationModel.Core.CoreApplicationView.TitleBar.Ext ...

  4. 【Win 10 应用开发】UI Composition 札记(六):动画

    动画在 XAML 中也有,而且基本上与 WPF 中的用法一样.不过,在 UWP 中,动画还有一种表现方式—— 通过 UI Composition 来创建. 基于 UI Composition 的动画, ...

  5. 【Win 10 应用开发】UI Composition 札记(二):基本构件

    在上一篇中,老周用一个示例,演示了框架视图的创建过程,在本篇中,老周将给大伙伴们说一下 Composition 构建 UI 的一些“零件”. UI Composition 有一个核心类——对,就是 C ...

  6. 【Win 10 应用开发】UI Composition 札记(五):灯光

    UI Composition 除了能够为 UI 元素建立三维空间外,还有相当重要的一个部件——灯光.宇宙万物的精彩缤纷,皆源于光明,光,使我们看到各种东西,除了黑洞之外的世界都是五彩斑谰的.故而,真要 ...

  7. 【Win 10 应用开发】启动远程设备上的应用

    这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...

  8. 【Win 10应用开发】Adaptive磁贴模板的XML文档结构

    在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win ...

  9. 【Win 10应用开发】认识一下UAP项目

    Windows 10 SDK预览版需要10030以上版本号的Win 10预览版系统才能使用.之前我安装的9926的系统,然后安装VS 2015 CTP 6,再装Win 10 SDK,但是在新建项目后, ...

随机推荐

  1. Delphi10.2 VCL Forms Application 的构成

    Delphi10.2 项目的构成(File Extensions of Files Generated by RAD Studio) Step1.打开 Delphi10.2,选择[File | New ...

  2. JavaScript高级(01)

    前端开发工具 1.1. WebStorm介绍和下载 l  介绍 WebStorm是JetBrains 推出的一款强大的HTML5编辑工具,拥有丰富的代码快速编辑,可以智能的补全代码.代码格式化.htm ...

  3. Jmeter脚本录制方法(一)——分别使用Badboy录制和Jmeter自带的代理服务器录制

    Jmeter录制方式分三种,分别是:使用Badboy录制.Jmeter自带的代理服务器录制和手工录制,今天先介绍前两种录制方法. Badboy录制 Badboy是用C++开发的动态应用测试工具, 其拥 ...

  4. JavaScript 版数据结构与算法(一)栈

    今天,我们要讲的是数据结构与算法中的栈. 栈的简介 栈是什么?栈是一个后进先出(LIFO)的数据结构.栈有啥作用?栈可以模拟算法或生活中的一些后进先出的场景,比如: 十进制转二进制,你需要将余数倒序输 ...

  5. Linux下将Apache(httpd)新增为系统服务及开机自启动

    1. 查看一下/etc/init.d/下是否存在httpd这个服务 ls /etc/init.d/ | grep httpd 如果没有执行下一步 2.将自己安装目录下的apachect1复制到该目录下 ...

  6. localStorage存值取值以及存取JSON,以及基于html5 localStorage的购物车

    localStorage.setItem("key","value");//存储变量名为key,值为value的变量 localStorage.key = &q ...

  7. 关于SEO的一些见解---关键词的选取布局以及内外链的建设

    前言     SEO是英文 Search EngineOptimiation的缩写,中文翻译为"搜索引擎优化"简单地说, SEO就是从搜索引擎上获得流量的技术 . 搜索引掌优化的主 ...

  8. 接口自动化测试方案PHP + mysql

    接口测试在测试工作中是很常见的工作,但是在以往的接口测试工作中借助的一般是第三方插件.python开发的发送请求脚本.LR脚本.Jmeter脚本,之前也使用python开发了一套接口自动化测试系统,但 ...

  9. chromium源码阅读--进程的Message Loop

    上一篇总结了chromium进程的启动,接下来就看线程的消息处理,这里的线程包含进程的主进程. 消息处理是由base::MessageLoop中实现,消息中的任务和定时器都是异步事件的. 主要如下几点 ...

  10. OpenWRT添加模块 Makefile和Config.in

    添加模块编译 在网上找了一下,很多关于编译Openwrt系统的资料,不过这些事情芯片厂商提供的开发包都已经办得妥妥了,但是没有找到系统介绍的资料,添加一个包的介绍有不多,其中有两个很有参考价值: ht ...