大家好,由于很多原因,我有很长一段时间没有在 CSDN 上分享我的学习成果了,如今终于可以回归分享之路了。

之前在做一个项目的时候,想在一个区域里绘制自己的图形,于是上网搜索资料,无意中找到了 InkCanvas ,但我们最终并没有在项目里使用它,不过它的强大确深深地印在了我的脑海中。之后学院年级会举办一个比赛,本来没打算参加,不过一觉醒来被告知室友已经给我报上名了,无奈之下只得借助 WPF 中的 InkCanvas 来赶出一个作品。

不过这次经历让我熟悉了 InkCanvas 的一些基本使用,之前在网上搜到的资料都不是很满意,于是这里给大家奉上我的学习成果。

首先来简单介绍一下什么是 InkCanvas 。顾名思义, InkCanvas 和 Canvas 有一定的联系,都是一种画布,我们可以在上面绘制我们的图形等等。

那么 InkCanvas 和 Canvas 有什么区别呢?那就是 InkCanvas 集成了一些很方便的功能,使我们不必再用代码去实现那些功能,下面将结合实例讲解如何使用这些功能。

现在先来创建一个 WPF 应用程序,然后创建一个 InkCanvas 标签。

  1. <Window x:Class="Blog_InkCanvas.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="MainWindow" Height="350" Width="525">
  5. <Grid>
  6. <InkCanvas x:Name="inkCanvas"/>
  7. </Grid>
  8. </Window>

运行程序并且按住鼠标左键即可自右绘制墨迹。

InkCanvas 提供的最基本的功能是自由笔,我们这里称显示出来的图形为墨迹,而绘制出来的墨迹实际上是 Stroke 类型,所以我们可以用 Stroke 类型的 DrawingAttributes 属性进行墨迹的一些设置,例如颜色,粗细等等。

那么既然如此,我们就先来改变一下墨迹的颜色,将前面的 XAML 文件对应的后置代码文件的内容修改为如下所示:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Documents;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Navigation;
  14. using System.Windows.Shapes;
  15. using System.Windows.Ink;
  16. namespace Blog_InkCanvas
  17. {
  18. /// <summary>
  19. /// MainWindow.xaml 的交互逻辑
  20. /// </summary>
  21. public partial class MainWindow : Window
  22. {
  23. //声明一个 DrawingAttributes 类型的变量
  24. DrawingAttributes drawingAttributes;
  25. public MainWindow()
  26. {
  27. InitializeComponent();
  28. //创建 DrawingAttributes 类的一个实例
  29. drawingAttributes = new DrawingAttributes();
  30. //将 InkCanvas 的 DefaultDrawingAttributes 属性的值赋成创建的 DrawingAttributes 类的对象的引用
  31. //InkCanvas 通过 DefaultDrawingAttributes 属性来获取墨迹的各种设置,该属性的类型为 DrawingAttributes 型
  32. inkCanvas.DefaultDrawingAttributes = drawingAttributes;
  33. //设置 DrawingAttributes 的 Color 属性设置颜色
  34. drawingAttributes.Color = Colors.Red;
  35. }
  36. }
  37. }

再次运行程序,会发现墨迹颜色变成了红色。

接下来我们同样是通过 DrawingAttributes 对象来改变墨迹的各项设置,在上面的代码后面添加如下代码:

  1. //利用 DrawingAttributes 的 Width 和 Height 属性来设置墨迹的宽度和高度
  2. //注意墨迹的宽度和高度是两个概念
  3. //宽度在垂直方向上能显现出来,而高度在水平方向上能显现出来
  4. drawingAttributes.Width = 20;
  5. drawingAttributes.Height = 10;
  6. //利用 DrawingAttributes 的StylusTip 属性可以设置墨迹触笔的形状,默认值是 StylusTip.Ellipse
  7. //将墨迹的宽度和高度都设置为稍大一些可以清楚的看到差别,如果较小则不太容易看出差别
  8. //这里宽度和高度都已经较大了,所以很容易看出差别,读者可以把下面一行代码反复注释或取消注释观察几次
  9. drawingAttributes.StylusTip = StylusTip.Rectangle;

继续运行程序。

InkCanvas 还提供了平滑处理功能。

  1. //将 FitToCurve 属性设置为 true 会在你绘制完一次墨迹后自动利用贝塞尔曲线来对你的墨迹进行平滑处理
  2. //为了使效果更明显,测试时请尽可能地使所绘制的墨迹显得杂乱无章,这样绘制完成后即可看到效果
  3. //这个就不截图演示了
  4. drawingAttributes.FitToCurve = true;

InkCanvas 还有两个属性,一个是 IsHeighlighter ,另一个是 IgnorePressure ,这两个属性都是布尔值,前者是判断墨迹是否有荧光笔效果,后者是判断墨迹的粗细是否随压力的增大而增大。

  1. //设置 IsHighlighter 属性为 true ,则墨迹显示的时候看上去像是荧光笔
  2. //官方文档上说这样做会使 Stroke 变的透明一些,可以显示覆盖住的墨迹,但是我感觉不太像透明,大家可以自己试试,也欢迎纠正
  3. drawingAttributes.IsHighlighter = false;
  4. //按照微软官方文档上的说法,设置 IgnorePressure 属性为 true墨迹粗细会随压力的增大而增大
  5. //但同时也说了 XAML 一般不使用此属性,我也实在找不到如何利用鼠标来进行压力的变化
  6. //所以这里我想大家做个了解应该就可以了
  7. drawingAttributes.IgnorePressure = true;

前面介绍了 InkCanvas 墨迹的一些属性,但是 InkCanvas 的强大远远不止这些,它还有几个非常好用的功能。请看如下代码:

  1. <Window x:Class="Blog_InkCanvas.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="MainWindow" Height="350" Width="525">
  5. <Grid>
  6. <Grid.RowDefinitions>
  7. <RowDefinition Height="9*"/>
  8. <RowDefinition/>
  9. </Grid.RowDefinitions>
  10. <InkCanvas x:Name="inkCanvas" Grid.Row="0"/>
  11. <Grid Grid.Row="1">
  12. <Grid.ColumnDefinitions>
  13. <ColumnDefinition/>
  14. <ColumnDefinition/>
  15. <ColumnDefinition/>
  16. <ColumnDefinition/>
  17. <ColumnDefinition/>
  18. </Grid.ColumnDefinitions>
  19. <RadioButton Click="RadioButton_Click" Grid.Column="0">绘制墨迹</RadioButton>
  20. <RadioButton Click="RadioButton_Click" Grid.Column="1">按点擦除</RadioButton>
  21. <RadioButton Click="RadioButton_Click" Grid.Column="2">按线擦除</RadioButton>
  22. <RadioButton Click="RadioButton_Click" Grid.Column="3">选中墨迹</RadioButton>
  23. <RadioButton Click="RadioButton_Click" Grid.Column="4">停止操作</RadioButton>
  24. </Grid>
  25. </Grid>
  26. </Window>

将主页面 XAML 代码修改如上面,并在原来的后置 .cs 文件的构造函数之后添加如下方法:

  1. //更改 InkCanvas 对象的 EditingMode 属性,可以改变要在 InkCanvas 上执行的操作
  2. //该属性的值是一个 InkCanvasEditingMode 枚举,常见功能如下
  3. private void RadioButton_Click(object sender, RoutedEventArgs e)
  4. {
  5. if((sender as RadioButton).Content.ToString() == "绘制墨迹")
  6. {
  7. //绘制墨迹
  8. inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
  9. }
  10. else if((sender as RadioButton).Content.ToString() == "按点擦除")
  11. {
  12. //使用橡皮擦按点擦除墨迹
  13. inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
  14. }
  15. else if ((sender as RadioButton).Content.ToString() == "按线擦除")
  16. {
  17. //使用橡皮擦按绘制的墨迹将某一笔墨迹擦除掉,注意是某一笔,如果多次绘制但是有交叉也是不可以的
  18. inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
  19. }
  20. else if ((sender as RadioButton).Content.ToString() == "选中墨迹")
  21. {
  22. //选中某一笔墨迹,进行拖动和缩放以及按 Delete 键删除,注意是某一笔
  23. inkCanvas.EditingMode = InkCanvasEditingMode.Select;
  24. }
  25. else if ((sender as RadioButton).Content.ToString() == "停止操作")
  26. {
  27. //不做任何
  28. inkCanvas.EditingMode = InkCanvasEditingMode.None;
  29. }
  30. }

InkCanvas 的EditingMode 属性还有其他几个值,但是基本的就是这几个了,详细信息请参看 MSDN 。运行程序,并选择相应功能,即可看到效果。

利用 InkCanvas 不仅可以完成 Canvas 的功能,还可以非常方便地使用其他一些操作,对于绘图类功能开发来说非常好用。

另外有一点需要注意,在 InkCanvas 上绘制的 Stroke 墨迹并不是 InkCanvas 对象 Children 集合类型属性里的元素,所有用该属性的 Clear() 方法是不能清除已绘制上去的墨迹的。

本文就到此结束了,希望大家多多批评指正,谢谢!

WPF InkCanvas 画图 基础使用教程的更多相关文章

  1. [WPF系列]从基础起步学习系列计划

    引言 WPF技术已经算不什么新技术,一搜一大把关于WPF基础甚至高级的内容.之前工作中一直使用winform所以一直没有深入学习WPF,这次因项目中使用了WPF技术来实现比较酷的展示界面.我在这里只是 ...

  2. WPF InkCanvas 毛笔效果

    原文:WPF InkCanvas 毛笔效果 1.先来看看InkCanvas的一般用法: <InkCanvas>     <InkCanvas.DefaultDrawingAttrib ...

  3. SOA体系结构基础培训教程-规范标准篇

    引子:本文是<SOA体系结构基础培训教程>第3章<SOA标准与规范>课件,版权所有,转载请注明出处. 随着SOA在业界的应用日益广泛,SOA的标准化问题也成为各界日益关注的焦点 ...

  4. [置顶] IOS 基础入门教程

    IOS 基础入门教程 教程列表: IOS 简介 IOS环境搭建 Objective C 基础知识 创建第一款iPhone应用程序 IOS操作(action)和输出口(Outlet) iOS - 委托( ...

  5. Python基础入门教程

    Python基础入门教程 Python基础教程 Python 简介 Python环境搭建 Python 基础语法 Python 变量类型 Python 运算符 Python 条件语句 Python 循 ...

  6. SOA体系结构基础培训教程

    SOA体系结构基础培训教程-规范标准篇 引子:本文是<SOA体系结构基础培训教程>第3章<SOA标准与规范>课件,版权所有,转载请注明出处. 随着SOA在业界的应用日益广泛,S ...

  7. Angularjs 2 绝对零基础的教程(1):从安装配置开始

    写在前面 适合人群: 1. 愿意未来从事前端工作,并以此开拓自己未来职业 2. 有任何一种编程语言基础 3. 喜欢简单粗暴学一门实用的技术,而不是做科研. Angular 2 比 Angular 1 ...

  8. React Native基础&入门教程:初步使用Flexbox布局

    在上篇中,笔者分享了部分安装并调试React Native应用过程里的一点经验,如果还没有看过的同学请点击<React Native基础&入门教程:调试React Native应用的一小 ...

  9. 【转】IAR Embedded Workbench for ARM 8.22.1 基础使用教程

    @2018-12-15 [小记] IAR Embedded Workbench for ARM 8.22.1 基础使用教程

随机推荐

  1. Lucene基础(2)

    上一篇:Lucene基础(1) 一.Lucene术语 Document, Field, Term, Query, Analyzer相信在其中大多数在之前已经理解了...对其中部分概念详细说明 Docu ...

  2. Gitlab命令行指令

    Git global setup git config --global user.name "lh" git config --global user.email "l ...

  3. Linux添加软件连接方法

    这是linux中一个非常重要命令,请大家一定要熟悉.它的功能是为某一个文件或目录在另外一个位置建立一个同步的链接,类似Windows下的超级链接. 这个命令最常用的参数是-s,具体用法是:sudo l ...

  4. jq 进度条插件

    /***进度条*/var ProgressScrollBar = function (model) { this.defaults = { isCanMove: true,//是否启用拖动 conta ...

  5. iOS动画编程

    IOS中的动画总结来说有五种:UIView<block>,CAAnimation<CABasicAnimation,CATransition,CAKeyframeAnimation& ...

  6. B - 瑶瑶带你玩激光坦克

    B - 瑶瑶带你玩激光坦克 Time Limit: 2000/1000MS (Java/Others)    Memory Limit: 256000/128000KB (Java/Others) S ...

  7. C -小晴天老师系列——竖式乘法

    C - 小晴天老师系列——竖式乘法 Time Limit: 4000/2000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Others ...

  8. 杭电15题 The Cow Lexicon

    Problem Description Few know that the cows have their own dictionary with W (1 ≤ W ≤ 600) words, eac ...

  9. git提交失败

    git push "提示:更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支."的解决办法 本地已存在项目,需要先获取远端更新并与本地合并,再git push具体操作如下: ...

  10. perl中的pack与unpack

    这个pack, unpack在 "perl语言编程" 有介绍 看起来很复杂 #把一个字符串转为十六进制格式 my $source = 'abcd'; unpack('H*', $s ...