WPF 使用 Direct2D1 画图 绘制基本图形
原文:WPF 使用 Direct2D1 画图 绘制基本图形

版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问。如果当前博客图片看不到,请到 http://lindexi.gitee.io 访问博客。本文地址 https://blog.csdn.net/lindexi_gd/article/details/80007261

本文来告诉大家如何在 Direct2D1 绘制基本图形,包括线段、矩形、椭圆

本文是一个系列

  • WPF 使用 Direct2D1 画图入门

  • WPF 使用 Direct2D1 画图 绘制基本图形

  • WPF 使用 SharpDX

本文的组织参考Direct2D,对大神表示感谢。

在开始前先告诉大家为何需要使用 Direct2D ,虽然 WPF 也是基于 DX 进行渲染,但是 WPF 做了很多兼容处理,所以没有比直接使用 Direct2D 的性能高。经过测试,在使用下面的所有代码,占用 CPU 几乎都是 0% ,因为没有布局、透明和事件处理,所以速度是很快。

在 Direct2D 使用的 点是 Point2F ,传入的是两个 float ,和 Point 差不多。

Point2F 也是一个结构体,所以和 Point 类型差不多

线段

线段需要使用 DrawLine ,方法的签名

    public void DrawLine(Point2F firstPoint 起始点 , Point2F secondPoint 终点, Brush brush 笔刷, float strokeWidth 线段宽度)public unsafe void DrawLine(Point2F firstPoint, Point2F secondPoint, Brush brush, float strokeWidth, StrokeStyle strokeStyle 线段样式)

所以使用下面的方法就可以在 (10,10) (100,10) 画出一条宽度为 2 的红线

            _renderTarget.DrawLine(new D2D.Point2F(10, 10), new D2D.Point2F(100, 10),_renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1)), 2);

上面的代码运行在WPF 使用 Direct2D1 画图入门文章的 OnRendering 方法,为了让大家也可以试试下面的代码,建议大家先去看这篇博客。

关于笔刷会在后面说

StrokeStyle

可以看到上面线段的最后一个参数是 StrokeStyle 那么这个参数是如何创建?在 Direct2D 有很多类都不能直接直接创建需要使用 D2DFactory 或 RenderTarget 才能创建。StrokeStyle 就需要使用 D2DFactory 进行创建。

创建 StrokeStyle 需要参数 StrokeStyleProperties,这个类的构造有两个重载,一个是不需要参数,另一个是需要很多参数。代码请看下面。

public StrokeStyleProperties(CapStyle startCap, CapStyle endCap, CapStyle dashCap, LineJoin lineJoin, float miterLimit, DashStyle dashStyle, float dashOffset)

从代码的命名大概大家也可以知道 StrokeStyleProperties 参数的意思,下面先创建一个没有构造函数的来创建 StrokeStyle ,请看下面代码

            var strokeStyleProperties = new D2D.StrokeStyleProperties();var strokeStyle = d2DFactory.CreateStrokeStyle(strokeStyleProperties);_renderTarget.BeginDraw();_renderTarget.DrawLine(new D2D.Point2F(10,10),new D2D.Point2F(100,10), _renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1)),2, strokeStyle);_renderTarget.EndDraw();

需要注意,创建 strokeStyle 的工厂需要和创建 RenderTarget 一样,如果使用不一样的工厂就会出现下面异常。

Microsoft.WindowsAPICodePack.DirectX.Direct2D1.Direct2DException:“EndDraw has failed with error: 一起使用的对象必须创建自相同的工厂实例。 (异常来自 HRESULT:0x88990012) Tags=(0,0).”

所以需要修改WPF 使用 Direct2D1 画图入门文章的代码,把 D2DFactory 写为字段

   public MainWindow(){InitializeComponent();CompositionTarget.Rendering += OnRendering;Loaded += (s, e) =>{var d2DFactory = D2D.D2DFactory.CreateFactory(D2D.D2DFactoryType.Multithreaded);var windowHandle = new WindowInteropHelper(this).Handle;var renderTarget = d2DFactory.CreateHwndRenderTarget(new D2D.RenderTargetProperties(),new D2D.HwndRenderTargetProperties(windowHandle,new D2D.SizeU((uint) ActualWidth, (uint) ActualHeight),D2D.PresentOptions.RetainContents));_redBrush = renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1));_greenBrush = renderTarget.CreateSolidColorBrush(new D2D.ColorF(0, 1, 0, 1));_blueBrush = renderTarget.CreateSolidColorBrush(new D2D.ColorF(0, 0, 1, 1));_renderTarget = renderTarget;_d2DFactory = d2DFactory;};}

StrokeStyleProperties

关于 StrokeStyleProperties 需要说一下,就是各个参数。

从名字可以看到 StartCap 和 EndCap 就是线段的两端的图形,可以选的参数

  • Flat
  • Square
  • Round
  • Triangle

具体表示是什么,我会使用下面的例子

Flat

平的

            var strokeStyleProperties = new D2D.StrokeStyleProperties();strokeStyleProperties.StartCap = D2D.CapStyle.Flat;strokeStyleProperties.EndCap = D2D.CapStyle.Flat;var strokeStyle = _d2DFactory.CreateStrokeStyle(strokeStyleProperties);_renderTarget.BeginDraw();_renderTarget.DrawLine(new D2D.Point2F(10,10),new D2D.Point2F(100,10), _renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1)),2, strokeStyle);_renderTarget.EndDraw();

Round

圆的

       float h = 10;strokeStyleProperties.StartCap = D2D.CapStyle.Round;strokeStyleProperties.EndCap = D2D.CapStyle.Round;strokeStyle = _d2DFactory.CreateStrokeStyle(strokeStyleProperties);h += 20;_renderTarget.BeginDraw();_renderTarget.DrawLine(new D2D.Point2F(10, h), new D2D.Point2F(100, h), _renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1)), 5, strokeStyle);_renderTarget.EndDraw();

Square

方形

  strokeStyleProperties.StartCap = D2D.CapStyle.Square;strokeStyleProperties.EndCap = D2D.CapStyle.Square;strokeStyle = _d2DFactory.CreateStrokeStyle(strokeStyleProperties);h += 20;_renderTarget.BeginDraw();_renderTarget.DrawLine(new D2D.Point2F(10, h), new D2D.Point2F(100, h), _renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1)), 5, strokeStyle);_renderTarget.EndDraw();

Triangle

三角形

strokeStyleProperties.StartCap = D2D.CapStyle.Triangle;strokeStyleProperties.EndCap = D2D.CapStyle.Triangle;strokeStyle = _d2DFactory.CreateStrokeStyle(strokeStyleProperties);h += 20;_renderTarget.BeginDraw();_renderTarget.DrawLine(new D2D.Point2F(10, h), new D2D.Point2F(100, h), _renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1)), 5, strokeStyle);_renderTarget.EndDraw();

DashStyle

如果需要画虚线就可以使用 DashStyle ,虚线显示就是使用 CapStyle

strokeStyleProperties.DashStyle = D2D.DashStyle.DashDot;strokeStyleProperties.DashCap = D2D.CapStyle.Square;strokeStyleProperties.DashOffset = 2;h += 20;strokeStyle = _d2DFactory.CreateStrokeStyle(strokeStyleProperties);_renderTarget.BeginDraw();_renderTarget.DrawLine(new D2D.Point2F(10, h), new D2D.Point2F(100, h),_renderTarget.CreateSolidColorBrush(new D2D.ColorF(1, 0, 0, 1)), 5, strokeStyle);_renderTarget.EndDraw();

大家自己试一试就知道

里面还有属性 LineJoin 这个不是线段可以做的,是折线才可以使用,表示两个线段如何链接

矩形

画矩形使用 DrawRectangle ,参数需要传入 RectF 需要传入上下左右的浮点数。

            _renderTarget.DrawRectangle(new D2D.RectF(10, 10, 100, 100), brush, 10);

矩形有两个重载

    public void DrawRectangle(RectF rect, Brush brush, float strokeWidth)
    public unsafe void DrawRectangle(RectF rect, Brush brush, float strokeWidth, StrokeStyle strokeStyle)

矩形的 StrokeStyle 和线段一样。

椭圆

实际上画圆和椭圆是一样的,画圆的函数有两个重载

    public void DrawEllipse(Ellipse ellipse, Brush brush, float strokeWidth)
 public unsafe void DrawEllipse(Ellipse ellipse, Brush brush, float strokeWidth, StrokeStyle strokeStyle)

需要先创建 Ellipse 和笔刷。

创建 Ellipse 需要给圆心和两个轴,下面创建一个圆心在 (100,100) ,两个轴都是50的椭圆。实际上就是半径是50的圆形。

            var ellipse = new D2D.Ellipse(new D2D.Point2F(100, 100), 50, 50);

这就是绘制基本的图形。

那么如何填充图形?实际上所有 Draw 都有对应的 Fill 函数,除了线段。所以填充就是调用对应的 Fill 函数。

尝试运行程序,看看这时的 CPU ,实际上是几乎不会动,因为所有的计算都在 GPU 计算。不过程序里的代码包括创建图形,实际上是在 CPU 创建,但是因为速度很快,几乎不需要计算,所以需要的时间很短。

文字

最后就是告诉大家如何绘制文字。

绘制文字需要使用 DirectWrite ,需要先创建 DWriteFactory 然后才可以绘制文本。

绘制文本有多个方式,因为需要的很多参数都不能直接创建需要使用 DWriteFactory 创建,所以这里需要先使用下面代码

            var dWriteFactory = DWriteFactory.CreateFactory();

创建文字有多个方法

public void DrawText(string text, TextFormat textFormat, RectF layoutRect, Brush defaultForegroundBrush)public void DrawText(string text, TextFormat textFormat, RectF layoutRect, Brush defaultForegroundBrush, MeasuringMode measuringMode)public void DrawText(string text, TextFormat textFormat, RectF layoutRect, Brush defaultForegroundBrush, DrawTextOptions options)public unsafe void DrawText(string text, TextFormat textFormat, RectF layoutRect, Brush defaultForegroundBrush, DrawTextOptions options, MeasuringMode measuringMode)public unsafe void DrawTextLayout(Point2F origin, TextLayout textLayout, Brush defaultForegroundBrush)public unsafe void DrawTextLayout(Point2F origin, TextLayout textLayout, Brush defaultForegroundBrush, DrawTextOptions options)

因为有很多个参数,需要大家自己去试试

下面来写出简单文字

需要先创建 textFormat 需要告诉使用哪个字形,和字体大小

            var textFormat = dWriteFactory.CreateTextFormat("宋体", 20);

下面就是画出文字,文字换行可以使用\n,复杂的换行请使用文字重载方法,这里我就不说了

            _renderTarget.BeginDraw();_renderTarget.DrawText("lindexi 本文所有博客放在 lindexi.oschina.io \n欢迎大家来访问\n\n这是系列博客,告诉大家如何在 WPF 使用Direct2D1", textFormat, new D2D.RectF(10, 10, 1000, 1000), brush);_renderTarget.EndDraw();

需要说的是 Windows API Code Pack 1.1 已经很久没更新,而且有错误,所以建议使用 SharpDX

参见:Using Direct2D with WPF - CodeProject

https://jeremiahmorrill.wordpress.com/2011/02/14/a-critical-deep-dive-into-the-wpf-rendering-system/


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

posted on 2018-12-25 01:02 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/10171857.html

WPF 使用 Direct2D1 画图 绘制基本图形相关推荐

  1. WPF 使用 Direct2D1 画图入门

    本文来告诉大家如何在 WPF 使用 D2D 画图. 本文是一个系列 WPF 使用 Direct2D1 画图入门 WPF 使用 Direct2D1 画图 绘制基本图形 WPF 使用 SharpDX WP ...

  2. 【Scratch考级99图】图35-等级考试scratch绘制复杂图形六边形花 少儿编程 scratch画图案例教程

    目录 一.图形介绍 二.案例分析 三.案例演示 四.流程分析 五.程序编写 六.总结 七.推荐资料 1.入门基础 2.蓝桥杯比赛 3.考级资料 4.视频课程 一.图形介绍 在舞台正中央绘制如下图形,要 ...

  3. python画图三维-Python使用matplotlib绘制三维图形示例

    本文实例讲述了Python使用matplotlib绘制三维图形.分享给大家供大家参考,具体如下: 用二维泡泡图表示三维数据 泡泡的坐标2维,泡泡的大小三维,使用到的函数 plt.scatter(P[: ...

  4. python画图三维标记_Python matplotlib绘图示例 - 绘制三维图形

    Python matplotlib模块是扩展的MATLAB的一个绘图工具库.它可以绘制各种图形,下面就学习了下Python中的matplotlib模块,如何绘制三维图形. 示例代码一: # codin ...

  5. WPF入门(三)-几何图形之不规则图形(PathGeometry) (2)

    WPF入门(三)->几何图形之不规则图形(PathGeometry) (2) 原文:WPF入门(三)->几何图形之不规则图形(PathGeometry) (2) 上一节我们介绍了PathG ...

  6. python绘制三维曲面图-Python中使用Matplotlib绘制3D图形示例

    原标题:Python中使用Matplotlib绘制3D图形示例 3D图形能给我们对数据带来更加深入地理解.python的matplotlib库就包含了丰富的3D绘图工具.3D图形在数据分析.数据建模. ...

  7. java 绘制长方形_Java入门:绘制简单图形

    在上一节,我们学习了如何使用swing和awt工具创建一个空的窗口,本节学习如何绘制简单图形. 基本绘图介绍 Java中绘制基本图形,可以使用Java类库中的Graphics类,此类位于java.aw ...

  8. 【Iphone 游戏开发之一】创建视图并绘制简单图形

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-object/401.html ...

  9. Android Studio 画笔功能绘制简单图形

    一 设置页面布局 设置activity_main.xml为帧布局便于画图时直接使用位置进行绘制 二 新建java类用于编写绘图代码 在mainactivity目录下新建myview类 三 继承原有vi ...

最新文章

  1. 算法笔记-递归算法、递归排序、递归的时间复杂度、master公式(也叫主方法)
  2. 十大经典算法排序总结对比
  3. 【Android 电量优化】电量优化 ( Battery Historian 环境要求 | 电量分析报告 | 电量优化三原则 | 电量优化注意事项 )
  4. 噩耗...............
  5. JavaScript:undefined And null差异
  6. 技术圈盛会!腾讯云+社区开发者大会免费报名!
  7. sqlserver 2014 删除主键约束
  8. 异常mongodb:Invalid BSON field name XXXXXX:YYYYY.zz
  9. Haproxy+多台MySQL从服务器(Slave) 实现负载均衡
  10. 近期资料分享汇总,还不快来看看你漏了哪份没拿?
  11. bzoj3442学习小组
  12. 【南邮操作系统实验】页面置换算法(FIFO、LRU、OPT) C++ 版
  13. CTreeCtrl::HitTest
  14. python sklearn 梯度下降法_Python- sklearn之梯度下降算法原理
  15. AS3.1.2配置gradle阿里云镜像(可用)
  16. Activities 四大组件之一
  17. 2020年度博客之星发榜了,第一次参加,第70名,感谢给我投票的老铁们,2021继续努力!
  18. idea配置tomcat热部署
  19. centos 20T硬盘(超过16T)分区和格式化
  20. 【游戏设计模式】之一 序言:架构,性能与游戏

热门文章

  1. Matlab多if语句(if,elseif,else)分段执行时遇到被上一个条件覆盖的问题及解决
  2. MySQL建表1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL
  3. ppp服务器连通状态 失败移动,某局点MSR路由器PPPOE拨号IPCP阶段协商失败处理案例...
  4. 常用颜色RGB、灰度值
  5. Innovus和ICC2中设置partial placement blockage的命令和区别
  6. 红米4a android 9 速度,雷军感叹科技进步速度太快!Redmi 9入门机性能已经相当于骁龙835...
  7. 如何应对项目范围变更管理
  8. 傻孩子菜单框架(转)
  9. 计算机视觉基础——3D空间坐标点的重建(三角测量)
  10. python_循环语句for_1.12