介紹
通過 Pointer 相關事件實現一個具有基本功能的塗鴉板
通過 InkManager 實現一個功能完善的塗鴉板
示例
1、演示如何通過 Pointer 相關事件實現一個只有基本功能的塗鴉板
Input/Ink/Simple.xaml
<Page
x:Class="XamlDemo.Input.Ink.Simple"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.Input.Ink"
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="120 0 0 0">
<Button Name="btnClear" Content="清除" Click="btnClear_Click_1" />
<Canvas Name="canvas" Background="Blue" Width="800" Height="480" HorizontalAlignment="Left" Margin="0 10 0 0" />
</StackPanel>
</Grid>
</Page>
Input/Ink/Simple.xaml.cs
/*
* 通過 Pointer 相關事件實現一個只有基本功能的塗鴉板
*/
using System;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
namespace XamlDemo.Input.Ink
{
public sealed partial class Simple : Page
{
// 用於保存觸摸點(PointerId - Point)
private Dictionary<uint, Point?> _dicPoint;
public Simple()
{
this.InitializeComponent();
canvas.PointerPressed += canvas_PointerPressed;
canvas.PointerMoved += canvas_PointerMoved;
canvas.PointerReleased += canvas_PointerReleased;
canvas.PointerExited += canvas_PointerExited;
_dicPoint = new Dictionary<uint, Point?>();
}
void canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// 指針按下後,保存此觸摸點
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
_dicPoint[pointerPoint.PointerId] = pointerPoint.Position;
}
void canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
if (_dicPoint.ContainsKey(pointerPoint.PointerId) && _dicPoint[pointerPoint.PointerId].HasValue)
{
Point currentPoint = pointerPoint.Position;
Point previousPoint = _dicPoint[pointerPoint.PointerId].Value;
// 如果指針移動過程中,兩個點間的距離超過 4 則在兩點間繪制一條直線,以完成塗鴉
if (ComputeDistance(currentPoint, previousPoint) > 4)
{
Line line = new Line()
{
X1 = previousPoint.X,
Y1 = previousPoint.Y,
X2 = currentPoint.X,
Y2 = currentPoint.Y,
StrokeThickness = 5,
Stroke = new SolidColorBrush(Colors.Orange),
StrokeEndLineCap = PenLineCap.Round
};
_dicPoint[pointerPoint.PointerId] = currentPoint;
canvas.Children.Add(line);
}
}
}
void canvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
// 指針釋放後,從字典中刪除此 PointerId 的數據
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
if (_dicPoint.ContainsKey(pointerPoint.PointerId))
_dicPoint.Remove(pointerPoint.PointerId);
}
void canvas_PointerExited(object sender, PointerRoutedEventArgs e)
{
// 指針離開相當於指針釋放
canvas_PointerReleased(sender, e);
}
// 清除塗鴉
private void btnClear_Click_1(object sender, RoutedEventArgs e)
{
canvas.Children.Clear();
_dicPoint.Clear();
}
// 計算兩個點(Point)之間的距離
private double ComputeDistance(Point point1, Point point2)
{
return Math.Sqrt(Math.Pow(point1.X - point2.X, 2) + Math.Pow(point1.Y - point2.Y, 2));
}
}
}
2、演示如何通過 InkManager 實現一個功能完善的塗鴉板
Input/Ink/InkRenderer.cs
/*
* 開發一個 InkRenderer 類,用於呈現 InkManager 中的內容
*
* 注:InkManager 用於 ink 的管理,但並不負責呈現
*
*
* InkStroke - ink 畫筆
* DrawingAttributes - 畫筆的相關屬性,一個 InkDrawingAttributes 類型的對象
* Color - 顏色
* FitToCurve - 使用貝塞爾曲線則為 true,使用直線則為 false,默認值為 true
* PenTip - 筆尖的形狀(Circle, Rectangle)
* Size - 筆尖的尺寸
* IgnorePressure - 是否忽略筆尖在觸摸屏上的壓力
* BoundingRect - ink 畫筆的邊界框
* Recognized - 該畫筆是否已被文字識別
* Selected - 該畫筆是否被選中
* Clone() - 克隆這個畫筆,並返回克隆後的新的 InkStroke 對象
* GetRenderingSegments() - 返回 ink 的線段集合,即 InkStrokeRenderingSegment 集合
*
* InkStrokeRenderingSegment - ink 的線段
* BezierControlPoint1 - 貝塞爾曲線的第一個控制點的位置
* BezierControlPoint2 - 貝塞爾曲線的第二個控制點的位置
* Position - 貝塞爾曲線的終點的位置
*/
using System.Collections.Generic;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Input.Inking;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
namespace XamlDemo.Input.Ink
{
public class InkRenderer
{
/// <summary>
/// 呈現 ink 的容器
/// </summary>
private readonly Panel _container = null;
/// <summary>
/// ink 的實時路徑(PointerId - Path)
/// </summary>
private readonly Dictionary<uint, Path> _dicLivePath = null;
/// <summary>
/// ink 的實時路徑中所包含的 PolyLineSegment(PointerId - PolyLineSegment)
/// </summary>
private readonly Dictionary<uint, PolyLineSegment> _dicLivePolyLine = null;
/// <summary>
/// InkStroke 所對應三次貝塞爾曲線,用於保存全部塗鴉曲線(包括未被選中的和被選中的)
/// </summary>
private readonly Dictionary<InkStroke, Path> _dicInkPath = null;
/// <summary>
/// InkStroke 所對應三次貝塞爾曲線,用於保存被選中的塗鴉曲線
/// </summary>
private readonly Dictionary<InkStroke, Path> _dicSelectionPath = null;
/// <summary>
/// 構造函數
/// </summary>
/// <param name="panel">用於呈現 ink 的容器</param>
public InkRenderer(Panel panel)
{
_container = panel;
_dicLivePath = new Dictionary<uint, Path>();
_dicLivePolyLine = new Dictionary<uint, PolyLineSegment>();
_dicInkPath = new Dictionary<InkStroke, Path>();
_dicSelectionPath = new Dictionary<InkStroke, Path>();
}
/// <summary>
/// 開始實時繪制 ink
/// </summary>
/// <param name="pointerPoint">當前的觸摸點</param>
/// <param name="inkDrawingAttributes">ink 的 InkDrawingAttributes 數據</param>
public void EnterLiveRendering(PointerPoint pointerPoint, InkDrawingAttributes inkDrawingAttributes)
{
uint pointerId = pointerPoint.PointerId;
var polyLine = new PolyLineSegment();
polyLine.Points.Add(pointerPoint.Position);
var figure = new PathFigure();
figure.StartPoint = pointerPoint.Position;
figure.Segments.Add(polyLine);
var geometry = new PathGeometry();
geometry.Figures.Add(figure);
var path = new Path();
path.Data = geometry;
path.Stroke = new SolidColorBrush(inkDrawingAttributes.Color);
path.StrokeThickness = inkDrawingAttributes.Size.Width;
path.StrokeLineJoin = PenLineJoin.Round;
path.StrokeStartLineCap = PenLineCap.Round;
_dicLivePolyLine.Add(pointerId, polyLine);
_dicLivePath.Add(pointerId, path);
_container.Children.Add(path);
}
/// <summary>
/// 更新 ink 的實時繪制
/// </summary>
/// <param name="pointerPoint"></param>
public void UpdateLiveRender(PointerPoint pointerPoint)
{
uint pointerId = pointerPoint.PointerId;
_dicLivePolyLine[pointerId].Points.Add(pointerPoint.Position);
}
/// <summary>
/// 停止此次 ink 的實時繪制
/// </summary>
/// <param name="pointerPoint">塗鴉的停止點</param>
public void ExitLiveRendering(PointerPoint pointerPoint)
{
uint pointerId = pointerPoint.PointerId;
_container.Children.Remove(_dicLivePath[pointerId]);
_dicLivePolyLine.Remove(pointerId);
_dicLivePath.Remove(pointerId);
}
/// <summary>
/// 將 InkStroke 繪制成一條三次貝塞爾曲線
/// </summary>
/// <param name="inkStroke">InkStroke 對象</param>
public void UpdateInkRender(InkStroke inkStroke)
{
Path bezierPath = InkStroke2BezierPath(inkStroke);
_dicInkPath.Add(inkStroke, bezierPath);
_container.Children.Add(bezierPath);
}
/// <summary>
/// 將每一個 InkStroke 都繪制成一條三次貝塞爾曲線
/// </summary>
/// <param name="inkStrokes">InkStroke 集合</param>
public void UpdateInkRender(IEnumerable<InkStroke> inkStrokes)
{
foreach (InkStroke inkStroke in inkStrokes)
{
UpdateInkRender(inkStroke);
}
}
/// <summary>
/// 將被選中的 InkStroke 以被選中的樣式繪制出來
/// </summary>
public void UpdateSelectionRender()
{
foreach (var inkPath in _dicInkPath)
{
Path selectionPath = null;
bool selectionPathExists = _dicSelectionPath.TryGetValue(inkPath.Key, out selectionPath);
// 如果 InkStroke 是被選中的狀態,但是並沒有呈現出選中狀態,則呈現這個選中狀態
if (inkPath.Key.Selected && !selectionPathExists)
{
inkPath.Value.StrokeThickness = inkPath.Key.DrawingAttributes.Size.Width + 2;
selectionPath = InkStroke2BezierPath(inkPath.Key);
selectionPath.Stroke = new SolidColorBrush(Colors.White);
selectionPath.StrokeThickness = inkPath.Key.DrawingAttributes.Size.Width;
_dicSelectionPath.Add(inkPath.Key, selectionPath);
_container.Children.Add(selectionPath);
}
// 如果 InkStroke 是未被選中的狀態,但是卻呈現出選中狀態,則去掉這個選中狀態的呈現
else if (selectionPathExists)
{
inkPath.Value.StrokeThickness = inkPath.Key.DrawingAttributes.Size.Width;
_dicSelectionPath.Remove(inkPath.Key);
_container.Children.Remove(selectionPath);
}
}
}
/// <summary>
/// 清除全部呈現
/// </summary>
public void Clear()
{
foreach (var path in _dicInkPath.Values)
{
_container.Children.Remove(path);
}
foreach (var path in _dicSelectionPath.Values)
{
_container.Children.Remove(path);
}
foreach (var path in _dicLivePath.Values)
{
_container.Children.Remove(path);
}
_dicInkPath.Clear();
_dicSelectionPath.Clear();
_dicLivePath.Clear();
_dicLivePolyLine.Clear();
}
/// <summary>
/// 如果 InkStroke 是一個貝塞爾曲線畫筆,則可將其轉換成 Path(一條貝塞爾曲線)
/// </summary>
/// <param name="inkStroke">InkStroke 對象</param>
/// <returns>轉換後的 Path 對象</returns>
public static Path InkStroke2BezierPath(InkStroke inkStroke)
{
var figure = new PathFigure();
var segments = inkStroke.GetRenderingSegments().GetEnumerator();
segments.MoveNext();
figure.StartPoint = segments.Current.Position;
while (segments.MoveNext())
{
var bs = new BezierSegment();
bs.Point1 = segments.Current.BezierControlPoint1;
bs.Point2 = segments.Current.BezierControlPoint2;
bs.Point3 = segments.Current.Position;
figure.Segments.Add(bs);
}
var geometry = new PathGeometry();
geometry.Figures.Add(figure);
var path = new Path();
path.Data = geometry;
path.Stroke = new SolidColorBrush(inkStroke.DrawingAttributes.Color);
path.StrokeThickness = inkStroke.DrawingAttributes.Size.Width;
path.StrokeLineJoin = PenLineJoin.Round;
path.StrokeStartLineCap = PenLineCap.Round;
return path;
}
}
}
Input/Ink/Demo.xaml
<Page
x:Class="XamlDemo.Input.Ink.Demo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.Input.Ink"
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="120 0 0 0">
<TextBlock Name="lblMsg" FontSize="14.667" />
<StackPanel Orientation="Horizontal" Margin="0 10 0 0">
<RadioButton Name="radInk" GroupName="mode" Content="塗鴉模式" Checked="radInk_Checked_1" IsChecked="True" />
<RadioButton Name="radSelect" GroupName="mode" Content="選擇模式" Checked="radSelect_Checked_1" Margin="10 0 0 0" />
<RadioButton Name="radErase" GroupName="mode" Content="刪除模式" Checked="radErase_Checked_1" Margin="10 0 0 0" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 10 0 0">
<Button Name="btnClearAll" Content="清除全部內容" Click="btnClearAll_Click_1" />
<Button Name="btnClearSelectedInk" Content="清除被選中的內容" Click="btnClearSelectedInk_Click_1" Margin="10 0 0 0" />
<Button Name="btnClearSelectedState" Content="清除選中狀態" Click="btnClearSelectedState_Click_1" Margin="10 0 0 0" />
<Button Name="btnMoveSelectedInk" Content="移動被選中的內容" Click="btnMoveSelectedInk_Click_1" Margin="10 0 0 0" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 10 0 0">
<Button Name="btnCut" Content="剪切" Click="btnCut_Click_1" />
<Button Name="btnCopy" Content="復制" Click="btnCopy_Click_1" Margin="10 0 0 0" />
<Button Name="btnPaste" Content="粘貼" Click="btnPaste_Click_1" Margin="10 0 0 0" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 10 0 0">
<Button Name="btnSave" Content="保存到文件" Click="btnSave_Click_1" />
<Button Name="btnLoad" Content="從文件加載" Click="btnLoad_Click_1" Margin="10 0 0 0" />
<Button Name="btnRecognize" Content="文字識別" Click="btnRecognize_Click_1" Margin="10 0 0 0" />
</StackPanel>
<Canvas x:Name="canvas" Background="Blue" Width="800" Height="360" Margin="0 10 0 0" HorizontalAlignment="Left"
PointerPressed="canvas_PointerPressed_1"
PointerMoved="canvas_PointerMoved_1"
PointerReleased="canvas_PointerReleased_1" />
</StackPanel>
</Grid>
</Page>
Input/Ink/Demo.xaml.cs
/*
* 通過 InkManager 實現一個功能完善的塗鴉板
*
* 注:InkManager 用於 ink 的管理,但並不負責呈現,需要自己開發呈現 ink 的類,請參見 InkRenderer.cs
*
*
* InkManager - ink 的管理類
* 包括 ink 的輸入模式,復制/粘貼,移動,保存到文件,從文件加載,文字識別等功能
* 詳細說明請參見本 Demo 中的相關代碼的注釋
*
* InkStroke - ink 畫筆
* DrawingAttributes - 畫筆的相關屬性,一個 InkDrawingAttributes 類型的對象
* Color - 顏色
* FitToCurve - 使用貝塞爾曲線則為 true,使用直線則為 false,默認值為 true
* PenTip - 筆尖的形狀(Circle, Rectangle)
* Size - 筆尖的尺寸
* IgnorePressure - 是否忽略筆尖在觸摸屏上的壓力
* BoundingRect - ink 畫筆的邊界框
* Recognized - 該畫筆是否已被文字識別
* Selected - 該畫筆是否被選中
* Clone() - 克隆這個畫筆,並返回克隆後的新的 InkStroke 對象
* GetRenderingSegments() - 返回 ink 的線段集合,即 InkStrokeRenderingSegment 集合
*
* InkStrokeRenderingSegment - ink 的線段
* BezierControlPoint1 - 貝塞爾曲線的第一個控制點的位置
* BezierControlPoint2 - 貝塞爾曲線的第二個控制點的位置
* Position - 貝塞爾曲線的終點的位置
*/
using System;
using System.Linq;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI;
using Windows.UI.Input;
using Windows.UI.Input.Inking;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using XamlDemo.Common;
namespace XamlDemo.Input.Ink
{
public sealed partial class Demo : Page
{
// 自己開發的用於呈現 ink 的類
private InkRenderer _renderer = null;
private InkManager _inkManager = null;
private InkDrawingAttributes _inkDrawingAttributes = null; // 塗鴉 ink 的樣式
private InkDrawingAttributes _inkDrawingAttributesForSelect = null; // 選擇模式時,用於呈現用戶的選擇路徑的 ink 的樣式
private int _pointerId = -1; // 當前指針的 pointerId
public Demo()
{
this.InitializeComponent();
_inkDrawingAttributes = new InkDrawingAttributes();
_inkDrawingAttributes.Color = Colors.Orange;
_inkDrawingAttributes.Size = new Size(5, 5);
_inkDrawingAttributes.IgnorePressure = true;
_inkDrawingAttributes.FitToCurve = true;
_inkDrawingAttributesForSelect = new InkDrawingAttributes();
_inkDrawingAttributesForSelect.Color = Colors.White;
_inkDrawingAttributesForSelect.Size = new Size(1, 1);
_inkDrawingAttributesForSelect.PenTip = PenTipShape.Circle;
_inkManager = new InkManager();
// InkManager 一共有三種模式:Inking - 塗鴉;Erasing - 擦除;Selecting - 選擇
_inkManager.Mode = InkManipulationMode.Inking;
// 設置 InkManager 的默認的畫筆屬性
_inkManager.SetDefaultDrawingAttributes(_inkDrawingAttributes);
// 獲取 InkManager 所支持的文字識別的種類
var inkRecognizers = _inkManager.GetRecognizers();
var inkRecognizer = inkRecognizers.SingleOrDefault(p => p.Name.Equals("Microsoft 中文(簡體)手寫識別器"));
if (inkRecognizer != null)
{
// 設置 InkManager 的默認的文字識別器為“Microsoft 中文(簡體)手寫識別器”
_inkManager.SetDefaultRecognizer(inkRecognizer);
}
_renderer = new InkRenderer(canvas);
}
private void canvas_PointerPressed_1(object sender, PointerRoutedEventArgs e)
{
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
_pointerId = (int)pointerPoint.PointerId;
switch (_inkManager.Mode)
{
case InkManipulationMode.Erasing: // 擦除模式
break;
case InkManipulationMode.Inking: // 塗鴉模式
_renderer.EnterLiveRendering(pointerPoint, _inkDrawingAttributes);
break;
case InkManipulationMode.Selecting: // 選擇模式
_renderer.EnterLiveRendering(pointerPoint, _inkDrawingAttributesForSelect);
break;
default:
break;
}
// 通知 InkManager 指針已按下
_inkManager.ProcessPointerDown(pointerPoint);
}
private void canvas_PointerMoved_1(object sender, PointerRoutedEventArgs e)
{
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
if (_pointerId == (int)pointerPoint.PointerId)
{
switch (_inkManager.Mode)
{
case InkManipulationMode.Erasing:
// 通知 InkManager 指針移動中,然後會返回一個 Rect 對象,其代表被 Erasing 的矩形范圍
var erasingRect = (Rect)_inkManager.ProcessPointerUpdate(e.GetCurrentPoint(canvas));
if (erasingRect.Height != 0 && erasingRect.Width != 0)
{
_renderer.Clear();
// 通過 InkManager.GetStrokes() 獲取 InkManager 包含的全部 InkStroke 對象集合
_renderer.UpdateInkRender(_inkManager.GetStrokes());
}
break;
case InkManipulationMode.Inking:
case InkManipulationMode.Selecting:
if (_inkManager.Mode == InkManipulationMode.Inking || _inkManager.Mode == InkManipulationMode.Selecting)
{
var intermediatePoints = e.GetIntermediatePoints(canvas);
for (int i = intermediatePoints.Count - 1; i >= 0; i--)
{
// 通知 InkManager 指針移動中
_inkManager.ProcessPointerUpdate(intermediatePoints[i]);
}
_renderer.UpdateLiveRender(pointerPoint);
}
break;
default:
break;
}
}
}
private void canvas_PointerReleased_1(object sender, PointerRoutedEventArgs e)
{
PointerPoint pointerPoint = e.GetCurrentPoint(canvas);
if (_pointerId == (int)pointerPoint.PointerId)
{
_pointerId = -1;
// 通知 InkManager 指針釋放了,返回值:當 Inking 或 Selecting 時返回值為用戶此次操作的矩形范圍;當 Erasing 時返回值為 0,0,0,0
var rect = _inkManager.ProcessPointerUp(pointerPoint);
// var inkManagerRect = _inkManager.BoundingRect; // InkManager 所管理 InkStroke 集合的矩形范圍(矩形邊框)
switch (_inkManager.Mode)
{
case InkManipulationMode.Inking:
_renderer.ExitLiveRendering(pointerPoint);
_renderer.UpdateInkRender(_inkManager.GetStrokes()[_inkManager.GetStrokes().Count - 1]);
break;
case InkManipulationMode.Selecting:
_renderer.ExitLiveRendering(pointerPoint);
_renderer.UpdateSelectionRender();
break;
default:
break;
}
}
}
private async void btnSave_Click_1(object sender, RoutedEventArgs e)
{
if (_inkManager.GetStrokes().Count > 0)
{
if (Helper.EnsureUnsnapped())
{
var savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
savePicker.FileTypeChoices.Add("GIF", new List<string> { ".gif" });
StorageFile file = await savePicker.PickSaveFileAsync();
if (null != file)
{
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
// 將 InkManager 中的 InkStroke 對象集合保存為文件
await _inkManager.SaveAsync(stream);
}
}
}
}
}
private async void btnLoad_Click_1(object sender, RoutedEventArgs e)
{
if (Helper.EnsureUnsnapped())
{
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
openPicker.FileTypeFilter.Add(".gif");
StorageFile file = await openPicker.PickSingleFileAsync();
if (null != file)
{
using (var stream = await file.OpenSequentialReadAsync())
{
// 加載一個文件,從中獲取 InkStroke 對象集合,並將其交由 InkManager 管理
await _inkManager.LoadAsync(stream);
}
_renderer.Clear();
_renderer.UpdateInkRender(_inkManager.GetStrokes());
}
}
}
private void radInk_Checked_1(object sender, RoutedEventArgs e)
{
if (_inkManager != null)
_inkManager.Mode = InkManipulationMode.Inking; // 塗鴉模式
}
private void radSelect_Checked_1(object sender, RoutedEventArgs e)
{
if (_inkManager != null)
_inkManager.Mode = InkManipulationMode.Selecting; // 選擇模式
}
private void radErase_Checked_1(object sender, RoutedEventArgs e)
{
if (_inkManager != null)
_inkManager.Mode = InkManipulationMode.Erasing; // 擦除模式
}
private void btnCut_Click_1(object sender, RoutedEventArgs e)
{
// 將 InkManager 中的被選中的 InkStroke 對象集合復制到剪切板
_inkManager.CopySelectedToClipboard();
// 將 InkManager 中的被選中的 InkStroke 對象集合刪除掉
_inkManager.DeleteSelected();
_renderer.Clear();
_renderer.UpdateInkRender(_inkManager.GetStrokes());
}
private void btnCopy_Click_1(object sender, RoutedEventArgs e)
{
// 將 InkManager 中的被選中的 InkStroke 對象集合復制到剪切板
_inkManager.CopySelectedToClipboard();
}
private void btnPaste_Click_1(object sender, RoutedEventArgs e)
{
// 剪切板中的數據是否是 InkStroke 對象集合
if (_inkManager.CanPasteFromClipboard())
{
// 將剪切板中的 InkStroke 對象集合粘貼到指定位置,並將此 InkStroke 對象集合交由 InkManager 管理
_inkManager.PasteFromClipboard(new Point(10, 10));
_renderer.Clear();
_renderer.UpdateInkRender(_inkManager.GetStrokes());
_renderer.UpdateSelectionRender();
}
}
private void btnClearAll_Click_1(object sender, RoutedEventArgs e)
{
// 通過 InkManager.GetStrokes() 獲取 InkManager 包含的全部 InkStroke 對象集合
foreach (var inkStroke in _inkManager.GetStrokes())
{
// InkStroke 是否被選中
inkStroke.Selected = true;
}
// 將 InkManager 中的被選中的 InkStroke 對象集合刪除掉
_inkManager.DeleteSelected();
_renderer.Clear();
}
private void btnClearSelectedInk_Click_1(object sender, RoutedEventArgs e)
{
// 將 InkManager 中的被選中的 InkStroke 對象集合刪除掉
_inkManager.DeleteSelected();
_renderer.Clear();
_renderer.UpdateInkRender(_inkManager.GetStrokes());
}
private void btnClearSelectedState_Click_1(object sender, RoutedEventArgs e)
{
foreach (var inkStroke in _inkManager.GetStrokes())
{
// InkStroke 是否被選中
inkStroke.Selected = false;
}
_renderer.Clear();
_renderer.UpdateInkRender(_inkManager.GetStrokes());
}
private void btnMoveSelectedInk_Click_1(object sender, RoutedEventArgs e)
{
// 將 InkManager 中的被選中的 InkStroke 對象集合移動指定的距離(本例為向下移動 5 個像素,向右移動 50 個像素)
_inkManager.MoveSelected(new Point(50, 5));
_renderer.Clear();
_renderer.UpdateInkRender(_inkManager.GetStrokes());
_renderer.UpdateSelectionRender();
}
private async void btnRecognize_Click_1(object sender, RoutedEventArgs e)
{
// 對 InkManager 中的內容做文字識別
// InkRecognitionTarget.All - 識別全部;
// InkRecognitionTarget.Selected - 識別選中的 InkStroke 集合;
// InkRecognitionTarget.Recent - 識別最近的 InkStroke
var recognitionResults = await _inkManager.RecognizeAsync(InkRecognitionTarget.All);
// 將文字識別的結果更新到 InkManager
_inkManager.UpdateRecognitionResults(recognitionResults);
// _inkManager.GetRecognitionResults(); 獲取 InkManager 中的文字識別的結果
string result = "文字識別的結果:";
foreach (InkRecognitionResult recognitionResult in recognitionResults)
{
// 獲取此文字識別的所有可能的結果集合,集合的第一條數據為最匹配的結果
result += " " + recognitionResult.GetTextCandidates()[0];
}
lblMsg.Text = result;
}
}
}
OK
[源碼下載]:http://files.cnblogs.com/webabcd/Windows8.rar