zoukankan      html  css  js  c++  java
  • 背水一战 Windows 10 (61)

    [源码下载]


    背水一战 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(4, 4);
                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 = 1,
                    StrokeDashArray = new DoubleCollection() { 5, 2 },
                };
                _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 == 0) || (_rect.Height == 0) || _rect.IsEmpty)
                {
                    return;
                }
    
                var rectangle = new Rectangle()
                {
                    Stroke = new SolidColorBrush(Colors.Blue),
                    StrokeThickness = 1,
                    StrokeDashArray = new DoubleCollection() { 5, 2 },
                    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(0, 0));
                }
            }
    
            // 移动选中涂鸦
            private void move_Click(object sender, RoutedEventArgs e)
            {
                Rect rect = inkCanvas.InkPresenter.StrokeContainer.MoveSelected(new Point(10, 10));
    
                _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(5, 30), random.Next(5, 30)));
    
                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(255, (byte)random.Next(0, 256), (byte)random.Next(0, 256), (byte)random.Next(0, 256));
    
                IReadOnlyList<InkStroke> strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
                foreach (var stroke in strokes)
                {
                    InkDrawingAttributes drawingAttributes = stroke.DrawingAttributes;
                    drawingAttributes.Color = color;
                    stroke.DrawingAttributes = drawingAttributes;
                }
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    为什么单个TCP连接很难占满带宽
    上传NUnit的单元测试结果和OpenCover的单元测试覆盖率到SonarQube服务中
    使用Visual Studio Code Coverage和nunit上传单元测试覆盖率和单元测试结果到SonarQube上
    java安装1.8的经验和Error: Registry key 'SoftwareJavaSoftJava Runtime Environment'CurrentVers问题处理
    NSubstitute.Analyzers检测NSubstitute用法冲突
    在TeamCity中执行gtest单元测试
    iOS OpenGL ES入门
    iOS 基础知识
    【内推】字节跳动-头条小说&番茄小说
    iOS开发小记(十四)
  • 原文地址:https://www.cnblogs.com/webabcd/p/7242825.html
Copyright © 2011-2022 走看看