posts - 562, comments - 10438, trackbacks - 594, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

背水一战 Windows 10 (60) - 控件(媒体类): Pointer 涂鸦板, InkCanvas 涂鸦板

Posted on 2017-07-24 08:16 webabcd 阅读(...) 评论(...) 编辑 收藏

[源码下载]


背水一战 Windows 10 (60) - 控件(媒体类): Pointer 涂鸦板, InkCanvas 涂鸦板



作者:webabcd


介绍
背水一战 Windows 10 之 控件(媒体类)

  • 通过处理 Pointer 相关事件实现一个简单的涂鸦板
  • InkCanvas 基础知识



示例
1、演示如何通过 Pointer 相关事件的处理,来实现一个简单的涂鸦板
Controls/MediaControl/InkSimple.xaml

<Page
    x:Class="Windows10.Controls.MediaControl.InkSimple"
    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">

            <Button Name="btnClear" Content="清除" Click="btnClear_Click" Margin="5" />

            <Canvas Name="canvas" Background="Blue" Width="800" Height="480" HorizontalAlignment="Left" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Controls/MediaControl/InkSimple.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 Windows10.Controls.MediaControl
{
    public sealed partial class InkSimple : Page
    {
        // 用于保存触摸点(PointerId - Point)
        private Dictionary<uint, Point?> _dicPoint;

        public InkSimple()
        {
            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(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、演示 InkCanvas 基础知识
Controls/MediaControl/InkCanvasDemo1.xaml

<Page
    x:Class="Windows10.Controls.MediaControl.InkCanvasDemo1"
    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">

            <Border Background="White" Width="480" Height="320" Margin="5" HorizontalAlignment="Left">
                <!--
                    InkCanvas - 涂鸦板控件
                -->
                <InkCanvas Name="inkCanvas" />
            </Border>

            <ComboBox Name="drawingColor" Header="Color" SelectedIndex="0" SelectionChanged="UpdateDefaultDrawingAttributes_Handler" Margin="5">
                <x:String>Red</x:String>
                <x:String>Green</x:String>
                <x:String>Blue</x:String>
            </ComboBox>
            <Slider Name="drawingSize" Foreground="Orange" Background="Red" Style="{StaticResource MySliderStyle}" Header="Size" Minimum="1" Maximum="20" Value="5" ValueChanged="UpdateDefaultDrawingAttributes_Handler" Margin="5" />
            <CheckBox Name="drawingDrawAsHighlighter" Content="DrawAsHighlighter" IsChecked="False" Checked="UpdateDefaultDrawingAttributes_Handler" Unchecked="UpdateDefaultDrawingAttributes_Handler" Margin="5" />
            <CheckBox Name="drawingFitToCurve" Content="FitToCurve" IsChecked="True" Checked="UpdateDefaultDrawingAttributes_Handler" Unchecked="UpdateDefaultDrawingAttributes_Handler" Margin="5" />
            <ToggleSwitch Name="drawingPenTip" Style="{StaticResource MyToggleSwitchStyle}" OnContent="PenTipShape.Circle" OffContent="PenTipShape.Rectangle" IsOn="True" Toggled="UpdateDefaultDrawingAttributes_Handler" Margin="5" />
            <CheckBox Name="drawingPenTipTransform" Content="通过 PenTipTransform 转换 PenTip 来实现笔尖形状的自定义" IsChecked="False" Checked="UpdateDefaultDrawingAttributes_Handler" Unchecked="UpdateDefaultDrawingAttributes_Handler" Margin="5" />
            <CheckBox Name="chkErasing" Content="将输入指定为擦除模式" IsChecked="False" Checked="UpdateDefaultDrawingAttributes_Handler" Unchecked="UpdateDefaultDrawingAttributes_Handler" Margin="5" />
            <CheckBox Name="chkIsInputEnabled" Content="IsInputEnabled" IsChecked="True" Checked="UpdateDefaultDrawingAttributes_Handler" Unchecked="UpdateDefaultDrawingAttributes_Handler" Margin="5" />
            <Button Name="buttonClear" Content="全部清除"  Click="buttonClear_Click" />

        </StackPanel>
    </Grid>
</Page>

Controls/MediaControl/InkCanvasDemo1.xaml.cs

/*
 * InkCanvas - 涂鸦板控件(继承自 FrameworkElement, 请参见 /Controls/BaseControl/FrameworkElementDemo/)
 *     InkPresenter - 获取 InkPresenter 对象
 *        
 * InkPresenter - 涂鸦板
 *     IsInputEnabled - 是否启用涂鸦板
 *     InputDeviceTypes - 输入设备的类型(None, Touch, Pen, Mouse)
 *     InputProcessingConfiguration.Mode - 输入模式(None, Inking, Erasing)
 *     CopyDefaultDrawingAttributes() - 获取 InkDrawingAttributes 对象
 *     UpdateDefaultDrawingAttributes(InkDrawingAttributes value) - 设置 InkDrawingAttributes 对象
 *     
 * InkDrawingAttributes - 涂鸦笔尖属性
 *     IgnorePressure - 是否忽略触摸压力
 *     Color - 笔尖的颜色
 *     Size - 笔尖的尺寸(宽和高)
 *     DrawAsHighlighter - 覆盖之前的涂鸦时(false - 直接覆盖;true - 高亮显示覆盖区域)
 *     FitToCurve - 涂鸦时(true - 使用贝塞尔曲线生成涂鸦;false - 使用直线生成涂鸦)
 *     PenTip - 笔尖的形状(Circle, Rectangle)
 *     PenTipTransform - 用于转换 PenTip 的 Matrix3x2 仿射转换矩阵(Matrix3x2 提供了一些简便的方法:CreateRotation, CreateScale, CreateSkew, CreateTranslation 等)。通过它可以自定义笔尖的形状
 */

using System.Numerics;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Core;
using Windows.UI.Input.Inking;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace Windows10.Controls.MediaControl
{
    public sealed partial class InkCanvasDemo1 : Page
    {
        private InkPresenter _inkPresenter;

        public InkCanvasDemo1()
        {
            this.InitializeComponent();

            _inkPresenter = inkCanvas.InkPresenter;
            _inkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Touch;

            UpdateDefaultDrawingAttributes();
        }
        
        private void UpdateDefaultDrawingAttributes_Handler(object sender, RoutedEventArgs e)
        {
            UpdateDefaultDrawingAttributes();
        }

        private void buttonClear_Click(object sender, RoutedEventArgs e)
        {
            _inkPresenter.StrokeContainer.Clear();
        }

        private void UpdateDefaultDrawingAttributes()
        {
            if (_inkPresenter != null)
            {
                InkDrawingAttributes drawingAttributes = _inkPresenter.CopyDefaultDrawingAttributes();
                drawingAttributes.IgnorePressure = true;

                switch (drawingColor.SelectedValue.ToString())
                {
                    case "Red":
                        drawingAttributes.Color = Colors.Red;
                        break;
                    case "Green":
                        drawingAttributes.Color = Colors.Green;
                        break;
                    case "Blue":
                        drawingAttributes.Color = Colors.Blue;
                        break;
                }

                drawingAttributes.Size = new Size(drawingSize.Value, drawingSize.Value);
                drawingAttributes.DrawAsHighlighter = drawingDrawAsHighlighter.IsChecked.Value;
                drawingAttributes.FitToCurve = drawingFitToCurve.IsChecked.Value;
                drawingAttributes.PenTip = drawingPenTip.IsOn ? PenTipShape.Circle : PenTipShape.Rectangle;



                if (drawingPenTipTransform.IsChecked == true)
                    drawingAttributes.PenTipTransform = Matrix3x2.CreateSkew(4, 4);
                else
                    drawingAttributes.PenTipTransform = Matrix3x2.Identity;

                _inkPresenter.UpdateDefaultDrawingAttributes(drawingAttributes);



                if (chkErasing.IsChecked == true)
                    _inkPresenter.InputProcessingConfiguration.Mode = InkInputProcessingMode.Erasing;
                else
                    _inkPresenter.InputProcessingConfiguration.Mode = InkInputProcessingMode.Inking;



                _inkPresenter.IsInputEnabled = chkIsInputEnabled.IsChecked.Value;
            }
        }
    }
}



OK
[源码下载]