1. 程式人生 > >WPF實現點選穿透以及線擦的實時虛線

WPF實現點選穿透以及線擦的實時虛線

裡面的功能有:改變畫筆大小、改變畫筆顏色、改變橡皮擦的大小,線擦的區域擦除,修改滑鼠圖示以及點選穿透。 XAML:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Loaded="Window_Loaded"
        Title="MainWindow" Height="350" Width="525" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Grid x:Name="grid">
        <InkCanvas x:Name="inkCanvas"
                   Width="525" Height="350" MouseMove="MouseMove_Click" MouseLeftButtonDown="InkCanvas_MouseLeftButtonDown" MouseLeftButtonUp="InkCanvas_MouseLeftButtonUp">
            <InkCanvas.Background>
                <SolidColorBrush Color="White" Opacity="0.01"></SolidColorBrush>
            </InkCanvas.Background>
        </InkCanvas>
        <Canvas Width="60" HorizontalAlignment="Right">
            <RadioButton Click="RadioButton_Click0" Tag="5" Width="30" Height="20" Canvas.Top="20">5</RadioButton>
            <RadioButton Click="RadioButton_Click0" Tag="10" Width="30" Height="20" Canvas.Top="40">10</RadioButton>
            <RadioButton Click="RadioButton_Click0" Tag="15" Width="30" Height="20" Canvas.Top="60">15</RadioButton>
            <RadioButton Click="RadioButton_Click1" Tag="紅" Width="30" Height="20" Canvas.Top="100">紅</RadioButton>
            <RadioButton Click="RadioButton_Click1" Tag="綠" Width="30" Height="20" Canvas.Top="120">綠</RadioButton>
            <RadioButton Click="RadioButton_Click1" Tag="藍" Width="30" Height="20" Canvas.Top="140">藍</RadioButton>
            <RadioButton Click="RadioButton_Click" Tag="A" Width="55" Height="20" Canvas.Top="180">書寫</RadioButton>
            <RadioButton Click="RadioButton_Click" Tag="B" Width="55" Height="20" Canvas.Top="200">點擦小</RadioButton>
            <RadioButton Click="RadioButton_Click" Tag="C" Width="55" Height="20" Canvas.Top="220">點擦中</RadioButton>
            <RadioButton Click="RadioButton_Click" Tag="D" Width="55" Height="20" Canvas.Top="240">點擦大</RadioButton>
            <RadioButton Click="RadioButton_Click" Tag="E" Width="55" Height="20" Canvas.Top="260">線擦</RadioButton>
            <RadioButton Click="RadioButton_Click" Tag="F" Width="55" Height="20" Canvas.Top="280">清空</RadioButton>
            <RadioButton Click="RadioButton_Click" Tag="G" Width="55" Height="20" Canvas.Top="300">操作</RadioButton>
        </Canvas>
    </Grid>
</Window>

cs:

using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;

namespace WpfApplication2
{
    /// <summary>
    /// MainWindow.xaml 的互動邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        DrawingAttributes drawingAttributes;//畫筆
        System.Windows.Media.Brush bg;//儲存點選穿透前的Brush
        bool isEraseByPoint = false;//是否選擇橡皮擦
        bool isEraseByPointStart = false;//是否開始使用橡皮擦功能
        System.Windows.Point mousePoint;//滑鼠位置
        double sizeX;//橡皮擦大小
        bool isEraseByStroke = false;
        bool isEraseByStrokeStart = false;
        //------線擦-----------
        List<System.Windows.Point> pointList = new List<System.Windows.Point>();
        StrokeCollection scTemp1 = new StrokeCollection();
        List<System.Windows.Point> xcPoint = new List<System.Windows.Point>();
        //---------------------
        public MainWindow()
        {
            InitializeComponent();

            drawingAttributes = new DrawingAttributes();
            inkCanvas.DefaultDrawingAttributes = drawingAttributes;
            drawingAttributes.Color = Colors.Red;//設定畫筆顏色
            drawingAttributes.Width = 5;
            drawingAttributes.Height = 5;
            drawingAttributes.FitToCurve = true;//曲線平滑
            bg = inkCanvas.Background;
            sizeX = 5;
            inkCanvas.AddHandler(InkCanvas.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.InkCanvas_MouseLeftButtonDown), true);
            Topmost = true;//在除錯的時候需要註釋該行才可以檢視變數的值
        }

        private void RadioButton_Click0(object sender, RoutedEventArgs e)
        {
            inkCanvas.UseCustomCursor = false;
            inkCanvas.Background = bg;
            isEraseByPoint = false;
            isEraseByStroke = false;
            inkCanvas.EditingMode = InkCanvasEditingMode.Ink;//書寫
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "5")
            {
                drawingAttributes.Width = 5;
                drawingAttributes.Height = 5;
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "10")
            {
                drawingAttributes.Width = 10;
                drawingAttributes.Height = 10;
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "15")
            {
                drawingAttributes.Width = 15;
                drawingAttributes.Height = 15;
            }
        }

        private void RadioButton_Click1(object sender, RoutedEventArgs e)
        {
            inkCanvas.UseCustomCursor = false;
            inkCanvas.Background = bg;
            isEraseByPoint = false;
            isEraseByStroke = false;
            inkCanvas.EditingMode = InkCanvasEditingMode.Ink;//書寫
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "紅")
            {
                drawingAttributes.Color = Colors.Red;
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "綠")
            {
                drawingAttributes.Color = Colors.Green;
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "藍")
            {
                drawingAttributes.Color = Colors.Blue;
            }
        }


        private void RadioButton_Click(object sender, RoutedEventArgs e)
        {
            inkCanvas.UseCustomCursor = false;
            inkCanvas.Background = bg;
            isEraseByPoint = false;
            isEraseByStroke = false;
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "A")
            {
                inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "B")
            {
                //方法一:
                isEraseByPoint = true;
                inkCanvas.EditingMode = InkCanvasEditingMode.None;
                sizeX = 5;
                inkCanvas.UseCustomCursor = true;//允許修改滑鼠圖示
                inkCanvas.Cursor = CreateCursor("Image/xpc.ico", 8, 8);//設定滑鼠圖示

                //方法二:
                //inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
                //inkCanvas.EraserShape = new RectangleStylusShape(20, 20);//改變橡皮擦大小
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "C")
            {
                isEraseByPoint = true;
                inkCanvas.EditingMode = InkCanvasEditingMode.None;
                sizeX = 10;
                inkCanvas.UseCustomCursor = true;
                inkCanvas.Cursor = CreateCursor("Image/xpc.ico", 14, 14);
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "D")
            {
                isEraseByPoint = true;
                inkCanvas.EditingMode = InkCanvasEditingMode.None;
                sizeX = 15;
                inkCanvas.UseCustomCursor = true;
                inkCanvas.Cursor = CreateCursor("Image/xpc.ico", 20, 20);
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "E")
            {
                inkCanvas.EditingMode = InkCanvasEditingMode.None;
                isEraseByStroke = true;
                inkCanvas.UseCustomCursor = true;
                inkCanvas.Cursor = CreateCursor("Image/Eraser.ico", 25, 25);
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "F")
            {
                inkCanvas.Strokes.Clear();
            }
            if (Convert.ToString(((System.Windows.Controls.RadioButton)sender).Tag) == "G")
            {
                inkCanvas.Background = null;
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //設定全屏
            this.WindowState = System.Windows.WindowState.Maximized;
            this.WindowStyle = System.Windows.WindowStyle.None;
            inkCanvas.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
            inkCanvas.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
        }
        //滑鼠單擊左鍵事件
        private void InkCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (isEraseByPoint)
            {
                isEraseByPointStart = true;
            }
            if (isEraseByStroke)
            {
                xcPoint.Clear();
                pointList.Clear();
                useNum = 0;
                isEraseByStrokeStart = true;
                mousePoint = Mouse.GetPosition(e.Source as FrameworkElement);
                pointList.Add(mousePoint);
                xcPoint.Add(mousePoint);
            }
        }


        //滑鼠鬆開左鍵事件
        private void InkCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (isEraseByPointStart)
            {
                isEraseByPointStart = false;
            }
            if (isEraseByStrokeStart)
            {
                isEraseByStrokeStart = false;
                #region
                StrokeCollection sc1 = inkCanvas.Strokes.HitTest(pointList, 1);
                inkCanvas.Strokes.Remove(sc1);
                try
                {
                    scTemp1.Clear();
                    foreach (Stroke stroke in inkCanvas.Strokes)
                    {
                        for (int i = 0; i < pointList.Count; i++)
                        {
                            if (stroke.HitTest(pointList[i]))
                            {
                                scTemp1.Add(stroke);
                                break;
                            }
                        }
                    }
                    if (scTemp1.Count != 0)
                    {
                        inkCanvas.Strokes.Remove(scTemp1);
                    }
                }
                catch
                {

                }
                #endregion
            }
        }

        double ABlength;
        int useNum = 0;
        System.Windows.Point pInsert = new System.Windows.Point();
        private void MouseMove_Click(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (isEraseByPointStart)
            {
                mousePoint = Mouse.GetPosition(e.Source as FrameworkElement);//獲取滑鼠的位置
                try
                {
                    foreach (Stroke stroke in inkCanvas.Strokes)
                    {
                        if (stroke.HitTest(mousePoint))
                        {
                            Rect rect = new Rect((mousePoint.X - sizeX / 2), (mousePoint.Y - sizeX / 2), sizeX, sizeX);//繪製矩形橡皮擦
                            StrokeCollection eraseResults = stroke.GetEraseResult(rect);
                            inkCanvas.Strokes.Replace(stroke, eraseResults);
                        }
                    }
                }
                catch
                {

                }
            }
            if (isEraseByStrokeStart)
            {
                mousePoint = Mouse.GetPosition(e.Source as FrameworkElement);
                pointList.Add(mousePoint);
                ABlength = Math.Sqrt(Math.Pow(mousePoint.X - xcPoint[xcPoint.Count - 1].X, 2) + Math.Pow(mousePoint.Y - xcPoint[xcPoint.Count - 1].Y, 2));//算出兩點的距離
                if (ABlength >= 5 && ABlength <= 6)
                {
                    xcPoint.Add(mousePoint);
                    if (xcPoint.Count >= 2)
                    {
                        if (useNum < xcPoint.Count - 1)
                        {
                            List<System.Windows.Point> p = new List<System.Windows.Point>();
                            p.Add(xcPoint[useNum]);
                            useNum++;
                            p.Add(xcPoint[useNum]);
                            useNum++;
                            StylusPointCollection point = new StylusPointCollection(p);
                            Stroke stroke = new Stroke(point);
                            stroke.DrawingAttributes.Color = Colors.BlueViolet;
                            inkCanvas.Strokes.Add(stroke);
                        }
                    }
                }
                else if (ABlength > 6)
                {
                    pInsert = new System.Windows.Point(mousePoint.X - ((mousePoint.X - xcPoint[xcPoint.Count - 1].X) / 2), mousePoint.Y - ((mousePoint.Y - xcPoint[xcPoint.Count - 1].Y) / 2));
                    xcPoint.Add(pInsert);
                    xcPoint.Add(mousePoint);
                    if (xcPoint.Count >= 2)
                    {
                        if (useNum < xcPoint.Count - 1)
                        {
                            List<System.Windows.Point> p = new List<System.Windows.Point>();
                            p.Add(xcPoint[useNum]);
                            useNum++;
                            p.Add(xcPoint[useNum]);
                            useNum++;
                            StylusPointCollection point = new StylusPointCollection(p);
                            Stroke stroke = new Stroke(point);
                            stroke.DrawingAttributes.Color = Colors.BlueViolet;
                            inkCanvas.Strokes.Add(stroke);
                        }
                    }
                }
            }
        }
        #region 建立滑鼠圖示
        public static System.Windows.Input.Cursor CreateCursor(String filePath, int xHotSpot = 0, int yHotSpot = 0)
        {
            System.Windows.Input.Cursor ret = null;

            if (string.IsNullOrWhiteSpace(filePath) || Directory.Exists(filePath) || !File.Exists(filePath))
            {
                return ret;
            }
            //首先嚐試通過預設方法建立  
            if (filePath.EndsWith(".ani") || filePath.EndsWith(".cur"))
            {
                try
                {
                    ret = new System.Windows.Input.Cursor(filePath);
                }
                catch (Exception)
                {
                    ret = null;
                }
            }
            //如果檔案不是正確的.ani或.cur檔案,則嘗試通過BitMap建立  
            if (ret == null)
            {
                Bitmap bmp = null;
                try
                {
                    bmp = new Bitmap(Bitmap.FromFile(filePath), new System.Drawing.Size(xHotSpot, xHotSpot));
                    if (bmp != null)
                    {
                        ret = CreateCursor(bmp, bmp.Width / 2, bmp.Height / 2);
                    }
                }
                catch (Exception)
                {
                    ret = null;
                }
            }
            return ret;
        }

        public static System.Windows.Input.Cursor CreateCursor(Bitmap bm, int xHotSpot = 0, int yHotSpot = 0)
        {
            System.Windows.Input.Cursor ret = null;

            if (bm == null)
            {
                return ret;
            }
            try
            {
                ret = InternalCreateCursor(bm, (uint)xHotSpot, (uint)yHotSpot);
            }
            catch (Exception)
            {
                ret = null;
            }
            return ret;
        }

        protected static System.Windows.Input.Cursor InternalCreateCursor(Bitmap bitmap, uint xHotSpot, uint yHotSpot)
        {
            var iconInfo = new NativeMethods.IconInfo();
            NativeMethods.GetIconInfo(bitmap.GetHicon(), ref iconInfo);
            iconInfo.xHotspot = xHotSpot;//焦點x軸座標  
            iconInfo.yHotspot = yHotSpot;//焦點y軸座標  
            iconInfo.fIcon = false;//設定滑鼠  
            SafeIconHandle cursorHandle = NativeMethods.CreateIconIndirect(ref iconInfo);
            return CursorInteropHelper.Create(cursorHandle);
        }

        protected static class NativeMethods
        {
            public struct IconInfo
            {
                public bool fIcon;
                public uint xHotspot;
                public uint yHotspot;
                public IntPtr hbmMask;
                public IntPtr hbmColor;
            }
            [DllImport("user32.dll")]
            public static extern SafeIconHandle CreateIconIndirect(ref IconInfo icon);
            [DllImport("user32.dll")]
            public static extern bool DestroyIcon(IntPtr hIcon);

            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
        }

        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
        protected class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            public SafeIconHandle()
                : base(true)
            {
            }
            /// <summary>  
            /// 釋放資源  
            /// </summary>  
            protected override bool ReleaseHandle()
            {
                return NativeMethods.DestroyIcon(handle);
            }
        }
        #endregion
    }
}