介紹
通過 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