背水一战 Windows 10 (61) - 控件(媒体类): InkCanvas 涂鸦编辑
作者:webabcd
介绍
背水一战 Windows 10 之 控件(媒体类)
- InkCanvas 涂鸦编辑
示例
演示 InkCanvas 涂鸦板编辑相关的操作
Controls/MediaControl/InkCanvasDemo2.xaml
<Page
x:Class="Windows10.Controls.MediaControl.InkCanvasDemo2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.Controls.MediaControl"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="10 0 10 10"> <Grid Background="White" Width="480" Height="320" Margin="5" HorizontalAlignment="Left">
<!--
Canvas - 在本例中用于绘制选中框(本例中选中框通过右键绘制)
-->
<Canvas Name="selectionCanvas"/>
<!--
InkCanvas - 涂鸦板控件
-->
<InkCanvas Name="inkCanvas" />
</Grid> <Button Name="clear" Content="清除全部涂鸦" Margin="5" Click="clear_Click" />
<Button Name="cut" Content="剪切选中涂鸦到剪切板" Margin="5" Click="cut_Click" />
<Button Name="copy" Content="复制选中涂鸦到剪切板" Margin="5" Click="copy_Click" />
<Button Name="paste" Content="从剪切板粘贴涂鸦" Margin="5" Click="paste_Click" />
<Button Name="move" Content="移动选中涂鸦" Margin="5" Click="move_Click" />
<Button Name="cloneAll" Content="克隆全部涂鸦" Margin="5" Click="cloneAll_Click" />
<Button Name="selectAll" Content="选中全部涂鸦" Margin="5" Click="selectAll_Click" />
<Button Name="changeColor" Content="改变全部涂鸦的颜色" Margin="5" Click="changeColor_Click" /> </StackPanel>
</Grid>
</Page>
Controls/MediaControl/InkCanvasDemo2.xaml.cs
/*
* InkCanvas - 涂鸦板控件(继承自 FrameworkElement, 请参见 /Controls/BaseControl/FrameworkElementDemo/)
* InkPresenter - 获取 InkPresenter 对象
*
* InkPresenter - 涂鸦板
* StrokeContainer - 返回 InkStrokeContainer 类型的对象
* InputProcessingConfiguration.RightDragAction - 涂鸦的输入按键
* AllowProcessing - 所有按键均可用于涂鸦,比如鼠标的左键和右键均可用于涂鸦。默认值
* LeaveUnprocessed - 特殊按键不可用于涂鸦,比如鼠标的右键不可用于涂鸦
* UnprocessedInput - 用于监听指针的一些事件
* PointerEntered, PointerExited, PointerHovered, PointerLost, PointerMoved, PointerPressed, PointerReleased - 顾名思义的一些事件
* 注:当 InputProcessingConfiguration.RightDragAction 为 AllowProcessing 时,则只会触发 PointerEntered, PointerExited, PointerHovered 事件
* SetPredefinedConfiguration(InkPresenterPredefinedConfiguration value) - 设置涂鸦行为
* SimpleSinglePointer - 单接触点涂鸦
* SimpleMultiplePointer - 多接触点涂鸦,需要先调用 ActivateCustomDrying()
* StrokesCollected - 当一个或多个 InkStroke 被画进来时触发的事件
* StrokesErased - 当一个或多个 InkStroke 被擦除时触发的事件
* StrokeInput - 用于监听一些涂鸦事件
* StrokeStarted, StrokeEnded, StrokeContinued, StrokeCanceled - 顾名思义的一些事件
*
* InkStrokeContainer - 用于管理涂鸦
* GetStrokes() - 获取当前涂鸦板的所有 InkStroke 对象集合
* BoundingRect - 获取当前涂鸦板的所有 InkStroke 对象的 Rect 区域
* Clear() - 清除所有涂鸦
* SelectWithLine(Point from, Point to) - 返回指定对角线内的涂鸦所在的 Rect 区域
* SelectWithPolyLine(IEnumerable<Point> polyline) - 返回指定 Polyline 内的涂鸦所在的 Rect 区域
* CopySelectedToClipboard() - 复制选中的涂鸦到剪切板
* CanPasteFromClipboard() - 剪切板中是否有涂鸦数据
* PasteFromClipboard(Point position) - 从剪切板粘贴涂鸦到指定的位置,并返回粘贴涂鸦的 Rect 区域
* MoveSelected(Point translation) - 指定偏移量,并移动选中的涂鸦,返回的是移动后的涂鸦的 Rect 区域
* DeleteSelected() - 删除选中的涂鸦,并返回删除涂鸦的 Rect 区域
* AddStroke(InkStroke stroke) - 在涂鸦板上绘制指定的 InkStroke 对象
* AddStrokes(IEnumerable<InkStroke> strokes) - 在涂鸦板上绘制指定的 InkStroke 对象集合
*
* InkStroke - 涂鸦对象(这是一次的涂鸦对象,即鼠标按下后移动然后再抬起后所绘制出的涂鸦)
* BoundingRect - 获取当前 InkStroke 的 Rect 区域
* DrawingAttributes - 涂鸦笔尖属性(参见 InkCanvasDemo1.xaml.cs)
* PointTransform - 用于转换 InkStroke 的 Matrix3x2 仿射转换矩阵(Matrix3x2 提供了一些简便的方法:CreateRotation, CreateScale, CreateSkew, CreateTranslation 等)
* Selected - 是否被选中
* Clone() - 克隆一份,返回克隆后的 InkStroke 对象
* GetInkPoints(), GetRenderingSegments() - 用于获取组成 InkStroke 的一堆贝塞尔曲线的数据
*
*
* 注:在 InkCanvas 有湿(wet)和干(dry)的感念
* 所谓的湿就是指鼠标按下后移动,在鼠标抬起来之前绘制出的涂鸦
* 所谓的干就是指鼠标抬起后,真正显示在 InkCanvas 上的涂鸦(鼠标抬起后可以将 wet 做一些自定义处理,然后再 dry 到 InkCanvas 上)
* 如何在 wet 和 dry 之间做自定义处理呢?需要通过 InkPresenter 的 ActivateCustomDrying() 方法获取到 InkSynchronizer 对象来实现,具体的示例在之后介绍 Win2D 的时候再写
*/ using Windows.Foundation;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.Input.Inking;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
using System.Linq;
using System.Collections.Generic;
using System; namespace Windows10.Controls.MediaControl
{
public sealed partial class InkCanvasDemo2 : Page
{
// 右键轨迹(用于选择涂鸦)
private Polyline _polyline;
// 被选中的涂鸦所在的 Rect 区域
private Rect _rect; public InkCanvasDemo2()
{
this.InitializeComponent(); inkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Touch; InkDrawingAttributes drawingAttributes = inkCanvas.InkPresenter.CopyDefaultDrawingAttributes();
drawingAttributes.IgnorePressure = true;
drawingAttributes.Color = Colors.Red;
drawingAttributes.Size = new Size(, );
inkCanvas.InkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes); // 此设置用于禁用鼠标右键的涂鸦功能,从而在后面实现鼠标右键的选择涂鸦的功能
inkCanvas.InkPresenter.InputProcessingConfiguration.RightDragAction = InkInputRightDragAction.LeaveUnprocessed;
inkCanvas.InkPresenter.UnprocessedInput.PointerPressed += UnprocessedInput_PointerPressed;
inkCanvas.InkPresenter.UnprocessedInput.PointerMoved += UnprocessedInput_PointerMoved;
inkCanvas.InkPresenter.UnprocessedInput.PointerReleased += UnprocessedInput_PointerReleased; inkCanvas.InkPresenter.StrokeInput.StrokeStarted += StrokeInput_StrokeStarted;
inkCanvas.InkPresenter.StrokesErased += InkPresenter_StrokesErased;
} // 右键按下
private void UnprocessedInput_PointerPressed(InkUnprocessedInput sender, PointerEventArgs args)
{
// 右键轨迹
_polyline = new Polyline()
{
Stroke = new SolidColorBrush(Colors.Blue),
StrokeThickness = ,
StrokeDashArray = new DoubleCollection() { , },
};
_polyline.Points.Add(args.CurrentPoint.RawPosition); // 绘制右键轨迹
selectionCanvas.Children.Add(_polyline);
} // 右键按下后在 InkCanvas 中移动
private void UnprocessedInput_PointerMoved(InkUnprocessedInput sender, PointerEventArgs args)
{
// 更新右键轨迹
_polyline.Points.Add(args.CurrentPoint.RawPosition);
} // 右键抬起
private void UnprocessedInput_PointerReleased(InkUnprocessedInput sender, PointerEventArgs args)
{
// 更新右键轨迹
_polyline.Points.Add(args.CurrentPoint.RawPosition); // 获取右键圈起来的区域内的涂鸦所在的 Rect 区域
_rect = inkCanvas.InkPresenter.StrokeContainer.SelectWithPolyLine(_polyline.Points); DrawBoundingRect();
} // 绘制 _rect 区域(即被选中的涂鸦所在的 Rect 区域)
private void DrawBoundingRect()
{
selectionCanvas.Children.Clear(); if ((_rect.Width == ) || (_rect.Height == ) || _rect.IsEmpty)
{
return;
} var rectangle = new Rectangle()
{
Stroke = new SolidColorBrush(Colors.Blue),
StrokeThickness = ,
StrokeDashArray = new DoubleCollection() { , },
Width = _rect.Width,
Height = _rect.Height
}; Canvas.SetLeft(rectangle, _rect.X);
Canvas.SetTop(rectangle, _rect.Y); selectionCanvas.Children.Add(rectangle);
} // 开始此次涂鸦后
private void StrokeInput_StrokeStarted(InkStrokeInput sender, PointerEventArgs args)
{
ClearSelection();
} // 擦除某些涂鸦后
private void InkPresenter_StrokesErased(InkPresenter sender, InkStrokesErasedEventArgs args)
{
ClearSelection();
} // 清除涂鸦的选中状态,以及选中框
private void ClearSelection()
{
IReadOnlyList<InkStroke> strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
foreach (var stroke in strokes)
{
stroke.Selected = false;
}
ClearDrawnBoundingRect();
} // 清除涂鸦的选中框
private void ClearDrawnBoundingRect()
{
if (selectionCanvas.Children.Any())
{
selectionCanvas.Children.Clear();
_rect = Rect.Empty;
}
} // 清除全部涂鸦
private void clear_Click(object sender, RoutedEventArgs e)
{
ClearDrawnBoundingRect(); inkCanvas.InkPresenter.StrokeContainer.Clear();
} // 剪切选中涂鸦到剪切板
private void cut_Click(object sender, RoutedEventArgs e)
{
ClearDrawnBoundingRect(); inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
Rect rect = inkCanvas.InkPresenter.StrokeContainer.DeleteSelected();
} // 复制选中涂鸦到剪切板
private void copy_Click(object sender, RoutedEventArgs e)
{
inkCanvas.InkPresenter.StrokeContainer.CopySelectedToClipboard();
} // 从剪切板粘贴涂鸦
private void paste_Click(object sender, RoutedEventArgs e)
{
if (inkCanvas.InkPresenter.StrokeContainer.CanPasteFromClipboard())
{
Rect rect = inkCanvas.InkPresenter.StrokeContainer.PasteFromClipboard(new Point(, ));
}
} // 移动选中涂鸦
private void move_Click(object sender, RoutedEventArgs e)
{
Rect rect = inkCanvas.InkPresenter.StrokeContainer.MoveSelected(new Point(, )); _rect = rect;
DrawBoundingRect();
} // 克隆全部涂鸦
private void cloneAll_Click(object sender, RoutedEventArgs e)
{
Random random = new Random(); IReadOnlyList<InkStroke> oldStrokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
List<InkStroke> newStrokes = new List<InkStroke>();
foreach (InkStroke oldStroke in oldStrokes)
{
InkStroke newStroke = oldStroke.Clone();
newStroke.Selected = true;
newStrokes.Add(newStroke);
}
inkCanvas.InkPresenter.StrokeContainer.AddStrokes(newStrokes);
inkCanvas.InkPresenter.StrokeContainer.MoveSelected(new Point(random.Next(, ), random.Next(, ))); ClearSelection();
} // 选中全部涂鸦
private void selectAll_Click(object sender, RoutedEventArgs e)
{
Rect rect = inkCanvas.InkPresenter.StrokeContainer.BoundingRect;
_rect = rect; IReadOnlyList<InkStroke> strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
foreach (var stroke in strokes)
{
stroke.Selected = true;
} DrawBoundingRect();
} // 改变全部涂鸦的颜色
private void changeColor_Click(object sender, RoutedEventArgs e)
{
Random random = new Random();
Color color = Color.FromArgb(, (byte)random.Next(, ), (byte)random.Next(, ), (byte)random.Next(, )); IReadOnlyList<InkStroke> strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
foreach (var stroke in strokes)
{
InkDrawingAttributes drawingAttributes = stroke.DrawingAttributes;
drawingAttributes.Color = color;
stroke.DrawingAttributes = drawingAttributes;
}
}
}
}
OK
[源码下载]
背水一战 Windows 10 (61) - 控件(媒体类): InkCanvas 涂鸦编辑的更多相关文章
- 背水一战 Windows 10 (59) - 控件(媒体类): Image, MediaElement
[源码下载] 背水一战 Windows 10 (59) - 控件(媒体类): Image, MediaElement 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) Im ...
- 背水一战 Windows 10 (60) - 控件(媒体类): Pointer 涂鸦板, InkCanvas 涂鸦板
[源码下载] 背水一战 Windows 10 (60) - 控件(媒体类): Pointer 涂鸦板, InkCanvas 涂鸦板 作者:webabcd 介绍背水一战 Windows 10 之 控件( ...
- 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别
[源码下载] 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) ...
- 背水一战 Windows 10 (37) - 控件(弹出类): MessageDialog, ContentDialog
[源码下载] 背水一战 Windows 10 (37) - 控件(弹出类): MessageDialog, ContentDialog 作者:webabcd 介绍背水一战 Windows 10 之 控 ...
- 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu
[源码下载] 背水一战 Windows 10 (36) - 控件(弹出类): ToolTip, Popup, PopupMenu 作者:webabcd 介绍背水一战 Windows 10 之 控件(弹 ...
- 背水一战 Windows 10 (35) - 控件(弹出类): FlyoutBase, Flyout, MenuFlyout
[源码下载] 背水一战 Windows 10 (35) - 控件(弹出类): FlyoutBase, Flyout, MenuFlyout 作者:webabcd 介绍背水一战 Windows 10 之 ...
- 背水一战 Windows 10 (34) - 控件(进度类): RangeBase, Slider, ProgressBar, ProgressRing
[源码下载] 背水一战 Windows 10 (34) - 控件(进度类): RangeBase, Slider, ProgressBar, ProgressRing 作者:webabcd 介绍背水一 ...
- 背水一战 Windows 10 (33) - 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch
[源码下载] 背水一战 Windows 10 (33) - 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch 作者:webabcd 介绍背水一 ...
- 背水一战 Windows 10 (32) - 控件(选择类): Selector, ComboBox
[源码下载] 背水一战 Windows 10 (32) - 控件(选择类): Selector, ComboBox 作者:webabcd 介绍背水一战 Windows 10 之 控件(选择类) Sel ...
随机推荐
- Netsharp下微信菜单以及OAuth
一.OAuth介绍 在微信开发中,当打开一个页面是,业务场景一般会基于粉丝绑定用户信息,即页面需要基于粉丝和用户的身份处理业务逻辑. 在微信中打开一个页面有三个场景: 1.文本回复中直接包含url 2 ...
- 软件测试基础Ⅲ(osi7层协议,测试模型,LoadRunner组件,软件质量模型)
osi7层开放式系统互连网络模型 1.物理层:主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的 ...
- springMVC学习 七 视图解析器
在springMVC中,如果不配置视图解析器,会走默认的视图解析器,但是有时候配置视图解析器,还有一定的作用 <bean id="viewResolver" class=&q ...
- kbmmw ORM 对象定义语法简析
使用kbmmw 的ORM 一定先要了解ORM 的对象定义语法. 下面简单说一下 // kbmMW_Table - Define a table. 定义一个表 // Must be used on cl ...
- 【转】Linux 如何通过命令仅获取IP地址
一同事的朋友正在参加笔试,遇到这么一个问题让他帮忙解决,结果同事又找到我帮他搞定.真是感慨:通讯发达在某些方面来说,真不知是不是好事啊!题目大致如下所示,一般我们使用ifconfig查看网卡信息,请问 ...
- ios alloc init 和 new 的区别
1.在实际开发中很少会用到new,一般创建对象咱们看到的全是[[className alloc] init] 但是并不意味着你不会接触到new,在一些代码中还是会看到[className new], ...
- 2018.06.26 Dominator Tree--支配树
在学习支配树之前,请保证已经会写lca(tarian求法) 简介 支配树是什么?支配树能干什么? 对于一个DAG" role="presentation" style=& ...
- Laravel创建自定义 Artisan 控制台命令实例教程
来源:http://laravelacademy.org/post/1374.html 1.入门 Laravel通过Artisan提供了强大的控制台命令来处理非浏览器业务逻辑.要查看Laravel中所 ...
- PHP-CGI、FASTCGI和php-fpm的关系
首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. web server(比如说nginx)只是内容的分发者.比如,如果请求/index.h ...
- s5-13 RIP 为什么会 衰败
DV路由可能遇到的问题 路由环路( routing loop) 计数到无穷问题( Count to infinite) 收敛慢的问题( slow Convergence ) 相信错误的路由信息导致 好 ...