重新想象 Windows 8 Store Apps (51) - 输入: 涂鸦板

原文: 重新想象 Windows 8 Store Apps (51) - 输入: 涂鸦板

[源码下载]


重新想象 Windows 8 Store Apps (51) - 输入: 涂鸦板



作者:webabcd


介绍
重新想象 Windows 8 Store Apps 之 涂鸦板

  • 通过 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
[源码下载]

你可能感兴趣的:(windows)