大家好,由于很多原因,我有很长一段时间没有在 CSDN 上分享我的学习成果了,如今终于可以回归分享之路了。
之前在做一个项目的时候,想在一个区域里绘制自己的图形,于是上网搜索资料,无意中找到了 InkCanvas ,但我们最终并没有在项目里使用它,不过它的强大确深深地印在了我的脑海中。之后学院年级会举办一个比赛,本来没打算参加,不过一觉醒来被告知室友已经给我报上名了,无奈之下只得借助 WPF 中的 InkCanvas 来赶出一个作品。
不过这次经历让我熟悉了 InkCanvas 的一些基本使用,之前在网上搜到的资料都不是很满意,于是这里给大家奉上我的学习成果。
首先来简单介绍一下什么是 InkCanvas 。顾名思义, InkCanvas 和 Canvas 有一定的联系,都是一种画布,我们可以在上面绘制我们的图形等等。
那么 InkCanvas 和 Canvas 有什么区别呢?那就是 InkCanvas 集成了一些很方便的功能,使我们不必再用代码去实现那些功能,下面将结合实例讲解如何使用这些功能。
现在先来创建一个 WPF 应用程序,然后创建一个 InkCanvas 标签。
- <Window x:Class="Blog_InkCanvas.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="MainWindow" Height="350" Width="525">
- <Grid>
- <InkCanvas x:Name="inkCanvas"/>
- </Grid>
- </Window>
运行程序并且按住鼠标左键即可自右绘制墨迹。
InkCanvas 提供的最基本的功能是*笔,我们这里称显示出来的图形为墨迹,而绘制出来的墨迹实际上是 Stroke 类型,所以我们可以用 Stroke 类型的 DrawingAttributes 属性进行墨迹的一些设置,例如颜色,粗细等等。
那么既然如此,我们就先来改变一下墨迹的颜色,将前面的 XAML 文件对应的后置代码文件的内容修改为如下所示:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- using System.Windows.Ink;
- namespace Blog_InkCanvas
- {
- /// <summary>
- /// MainWindow.xaml 的交互逻辑
- /// </summary>
- public partial class MainWindow : Window
- {
- //声明一个 DrawingAttributes 类型的变量
- DrawingAttributes drawingAttributes;
- public MainWindow()
- {
- InitializeComponent();
- //创建 DrawingAttributes 类的一个实例
- drawingAttributes = new DrawingAttributes();
- //将 InkCanvas 的 DefaultDrawingAttributes 属性的值赋成创建的 DrawingAttributes 类的对象的引用
- //InkCanvas 通过 DefaultDrawingAttributes 属性来获取墨迹的各种设置,该属性的类型为 DrawingAttributes 型
- inkCanvas.DefaultDrawingAttributes = drawingAttributes;
- //设置 DrawingAttributes 的 Color 属性设置颜色
- drawingAttributes.Color = Colors.Red;
- }
- }
- }
再次运行程序,会发现墨迹颜色变成了红色。
接下来我们同样是通过 DrawingAttributes 对象来改变墨迹的各项设置,在上面的代码后面添加如下代码:
- //利用 DrawingAttributes 的 Width 和 Height 属性来设置墨迹的宽度和高度
- //注意墨迹的宽度和高度是两个概念
- //宽度在垂直方向上能显现出来,而高度在水平方向上能显现出来
- drawingAttributes.Width = 20;
- drawingAttributes.Height = 10;
- //利用 DrawingAttributes 的StylusTip 属性可以设置墨迹触笔的形状,默认值是 StylusTip.Ellipse
- //将墨迹的宽度和高度都设置为稍大一些可以清楚的看到差别,如果较小则不太容易看出差别
- //这里宽度和高度都已经较大了,所以很容易看出差别,读者可以把下面一行代码反复注释或取消注释观察几次
- drawingAttributes.StylusTip = StylusTip.Rectangle;
继续运行程序。
InkCanvas 还提供了平滑处理功能。
- //将 FitToCurve 属性设置为 true 会在你绘制完一次墨迹后自动利用贝塞尔曲线来对你的墨迹进行平滑处理
- //为了使效果更明显,测试时请尽可能地使所绘制的墨迹显得杂乱无章,这样绘制完成后即可看到效果
- //这个就不截图演示了
- drawingAttributes.FitToCurve = true;
InkCanvas 还有两个属性,一个是 IsHeighlighter ,另一个是 IgnorePressure ,这两个属性都是布尔值,前者是判断墨迹是否有荧光笔效果,后者是判断墨迹的粗细是否随压力的增大而增大。
- //设置 IsHighlighter 属性为 true ,则墨迹显示的时候看上去像是荧光笔
- //官方文档上说这样做会使 Stroke 变的透明一些,可以显示覆盖住的墨迹,但是我感觉不太像透明,大家可以自己试试,也欢迎纠正
- drawingAttributes.IsHighlighter = false;
- //按照微软官方文档上的说法,设置 IgnorePressure 属性为 true墨迹粗细会随压力的增大而增大
- //但同时也说了 XAML 一般不使用此属性,我也实在找不到如何利用鼠标来进行压力的变化
- //所以这里我想大家做个了解应该就可以了
- drawingAttributes.IgnorePressure = true;
前面介绍了 InkCanvas 墨迹的一些属性,但是 InkCanvas 的强大远远不止这些,它还有几个非常好用的功能。请看如下代码:
- <Window x:Class="Blog_InkCanvas.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="MainWindow" Height="350" Width="525">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="9*"/>
- <RowDefinition/>
- </Grid.RowDefinitions>
- <InkCanvas x:Name="inkCanvas" Grid.Row="0"/>
- <Grid Grid.Row="1">
- <Grid.ColumnDefinitions>
- <ColumnDefinition/>
- <ColumnDefinition/>
- <ColumnDefinition/>
- <ColumnDefinition/>
- <ColumnDefinition/>
- </Grid.ColumnDefinitions>
- <RadioButton Click="RadioButton_Click" Grid.Column="0">绘制墨迹</RadioButton>
- <RadioButton Click="RadioButton_Click" Grid.Column="1">按点擦除</RadioButton>
- <RadioButton Click="RadioButton_Click" Grid.Column="2">按线擦除</RadioButton>
- <RadioButton Click="RadioButton_Click" Grid.Column="3">选中墨迹</RadioButton>
- <RadioButton Click="RadioButton_Click" Grid.Column="4">停止操作</RadioButton>
- </Grid>
- </Grid>
- </Window>
将主页面 XAML 代码修改如上面,并在原来的后置 .cs 文件的构造函数之后添加如下方法:
- //更改 InkCanvas 对象的 EditingMode 属性,可以改变要在 InkCanvas 上执行的操作
- //该属性的值是一个 InkCanvasEditingMode 枚举,常见功能如下
- private void RadioButton_Click(object sender, RoutedEventArgs e)
- {
- if((sender as RadioButton).Content.ToString() == "绘制墨迹")
- {
- //绘制墨迹
- inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
- }
- else if((sender as RadioButton).Content.ToString() == "按点擦除")
- {
- //使用橡皮擦按点擦除墨迹
- inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
- }
- else if ((sender as RadioButton).Content.ToString() == "按线擦除")
- {
- //使用橡皮擦按绘制的墨迹将某一笔墨迹擦除掉,注意是某一笔,如果多次绘制但是有交叉也是不可以的
- inkCanvas.EditingMode = InkCanvasEditingMode.EraseByStroke;
- }
- else if ((sender as RadioButton).Content.ToString() == "选中墨迹")
- {
- //选中某一笔墨迹,进行拖动和缩放以及按 Delete 键删除,注意是某一笔
- inkCanvas.EditingMode = InkCanvasEditingMode.Select;
- }
- else if ((sender as RadioButton).Content.ToString() == "停止操作")
- {
- //不做任何
- inkCanvas.EditingMode = InkCanvasEditingMode.None;
- }
- }
InkCanvas 的EditingMode 属性还有其他几个值,但是基本的就是这几个了,详细信息请参看 MSDN 。运行程序,并选择相应功能,即可看到效果。
利用 InkCanvas 不仅可以完成 Canvas 的功能,还可以非常方便地使用其他一些操作,对于绘图类功能开发来说非常好用。
另外有一点需要注意,在 InkCanvas 上绘制的 Stroke 墨迹并不是 InkCanvas 对象 Children 集合类型属性里的元素,所有用该属性的 Clear() 方法是不能清除已绘制上去的墨迹的。
本文就到此结束了,希望大家多多批评指正,谢谢!