使用 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. 【HIVE】sql语句转换成mapreduce

    1.hive是什么? 2.MapReduce框架实现SQL基本操作的原理是什么? 3.Hive怎样实现SQL的词法和语法解析? 连接:http://www.aboutyun.com/thread-20 ...

  2. 【maven插件】maven-shade-plugin

    概述 该插件提供了将artifact打包到一个本地jar包的能力,包括其依赖关系以及一些参数如 shade -rename重命名依赖关系的包. 目标 shade:shade 绑定到建生命周期中的pac ...

  3. Football 概率DP poj3071

                                                                                                 Footbal ...

  4. Iframe刷新页面

    window.parent.frames["name"].location="url";

  5. PHP MYSQL 搜索周边坐标,并计算两个点之间的距离

    搜索附近地点,例如,坐标(39.91, 116.37)附近500米内的人,首先算出“给定坐标附近500米”这个范围的坐标范围. 虽然它是个圆,但我们可以先求出该圆的外接正方形,然后拿正方形的经纬度范围 ...

  6. Echarts数据可视化dataZoom,开发全解+完美注释

    全栈工程师开发手册 (作者:栾鹏) Echarts数据可视化开发代码注释全解 Echarts数据可视化开发参数配置全解 6大公共组件详解(点击进入): title详解. tooltip详解.toolb ...

  7. 全面解读JavaScript入门到进阶,100%基础知识掌握!

    一.JavaScript 简介 1.JavaScript 是 Web 的编程语言,是前端开发必须掌握的三门语言之一,即: HTML   定义了网页的内容 CSS      描述了网页的布局 JavaS ...

  8. cocos2dx - tmx地图分层移动处理

    接上一节内容:cocos2dx - 节点管理 瓦片地图(Tiled Map) 在cocos2dx文档中有简单的介绍及使用.详情可以看:http://www.cocos2d-x.org/docs/man ...

  9. 【完美解决】2017打开MVC 4项目,cshtml页面提示‘当前上下文不存在名称model’

    时间:2017/10/19 背景:领导让再之前的MVC 4老项目上新增功能,从GIT上拉取下来,使用VS2017打开之后,cshtml界面所有和Razor相关的代码均被提示‘当前上下文不存在名称XXX ...

  10. PHP中header的作用

    1.跳转: //若等待时间为0,则与header("location:")等效.  //Header("Location:http://localhost//sessio ...