WPF InkCanvas 截图功能

 此功能用了WPF的InkCanvas,鼠标画矩形,沟是确定,后台多余的代码可以不看,可以取四个角的坐标

 1.MainWindow.xaml

<Window x:Class="WPF_InkCanvas.ROI_InkCanvas"
        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:WPF_InkCanvas"
        mc:Ignorable="d"
        Title="ROI_InkCanvas" Height="450" Width="800" KeyDown="Window_KeyDown" KeyUp="Window_KeyUp" Background="Transparent" >
    <Window.Resources>
       
        <Style x:Key="BaseButton" TargetType="{x:Type Button}" >
            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <Setter Property="FrameworkElement.OverridesDefaultStyle" Value="True" />
            <Setter Property="HorizontalContentAlignment" Value="Center" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="Padding" Value="20,10" />
            <Setter Property="Cursor" Value="Hand"/>
        </Style>
        <Style x:Key="PathButton" TargetType="{x:Type Button}" BasedOn="{StaticResource BaseButton}">
            <Setter Property="Padding" Value="8"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Border Background="Transparent">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          Margin="{TemplateBinding Padding}" 
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          x:Name="PART_ContentPresenter" Opacity=".8"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Opacity" TargetName="PART_ContentPresenter" Value="1"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid x:Name="grid"  KeyUp="Window_KeyUp" Background="#FF313030" MouseLeftButtonUp="inkCanvasMeasure_MouseLeftButtonUp">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Image Name="imgMeasure" HorizontalAlignment="Center" Stretch="Uniform" />
        <InkCanvas Name="inkCanvasMeasure" EditingMode="None" Background="Transparent" Strokes="{Binding InkStrokes, Mode=TwoWay}" HorizontalAlignment="Center" 
                   Width="{Binding ElementName=imgMeasure, Path=ActualWidth}" Height="{Binding ElementName=imgMeasure, Path=ActualHeight}"
                   MouseDown="InkCanvasMeasure_MouseDown" MouseMove="InkCanvasMeasure_MouseMove" MouseLeftButtonUp="inkCanvasMeasure_MouseLeftButtonUp">
            <StackPanel x:Name="sp" Background="White"  Width="50" Height="30" Visibility="Collapsed">
                <Button x:Name="PART_ButtonComplete"  Style="{DynamicResource PathButton}" ToolTip="完成" Margin="3,0" Click="PART_ButtonComplete_Click">
                    <Button.Content>
                        <Path Fill="#67C23A" Width="20" Height="15" Stretch="Fill" Data="M384 690l452-452 60 60-512 512-238-238 60-60z"/>
                    </Button.Content>
                </Button>
            </StackPanel>
            
        </InkCanvas>
        <StackPanel Grid.Row="1" Orientation="Horizontal" Name="st">
            <Button Content="OpenFile" Margin="5" HorizontalAlignment="Left" FontSize="20" Click="OpenFile_Click"/>
            <ToggleButton Name="btnSquare" Content="Draw Square" Margin="5" HorizontalAlignment="Left" FontSize="20" Click="DrawSquare_Click"/>
            <ToggleButton Name="btnEllipse" Content="Draw Ellipse" Margin="5" HorizontalAlignment="Left" FontSize="20" Click="DrawEllipse_Click"/>
          
        </StackPanel>
    </Grid>
</Window>

 2.MainWindow.xaml.cs

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Tend.UAC.Controls;

namespace WPF_InkCanvas
{
    /// <summary>
    /// ROI_InkCanvas.xaml 的交互逻辑
    /// </summary>
    public partial class ROI_InkCanvas : Window
    {
        private ViewModel viewModel;
        private System.Windows.Point iniP;
        private System.Windows.Point endP;

        public ROI_InkCanvas()
        {
            InitializeComponent();
            this.WindowStyle = WindowStyle.None;
            this.AllowsTransparency = true;
            //grid.Opacity = 0.7;
            imgMeasure.Opacity = 1;
            this.Background = new SolidColorBrush(Colors.Gray);// new SolidColorBrush(Colors.Transparent);
            grid.Background = new SolidColorBrush(Colors.Transparent);
            btnSquare.IsChecked = true;
            //设置画笔属性
            DrawingAttributes drawingAttributes = new DrawingAttributes
            {
                Color = Colors.LightGreen,
                Width = 1,
                Height = 1,
                StylusTip = StylusTip.Rectangle,//设置墨迹触笔的形状
                //FitToCurve = true,
                IsHighlighter = false,
                IgnorePressure = true,
             
            };
            inkCanvasMeasure.DefaultDrawingAttributes = drawingAttributes;
            inkCanvasMeasure.AllowDrop = true;

            viewModel = new ViewModel
            {
                //MeaInfo = "测试······",
                InkStrokes = new StrokeCollection(),
            };

            DataContext = viewModel;
        }

        private void OpenFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openDialog = new OpenFileDialog
            {
                Filter = "Image Files (*.bmp)|*.bmp|Image Files (*.jpg)|*.jpg|Image Files (*.png)|*.png",
                Title = "Open Image File"
            };
            if (openDialog.ShowDialog() == true)
            {
                BitmapImage image = new BitmapImage();
                image.BeginInit();
                image.UriSource = new Uri(openDialog.FileName, UriKind.RelativeOrAbsolute);
                image.EndInit();
                imgMeasure.Source = image;
                this.image = image;
            }
        }
        private BitmapImage image;
        private void DrawSquare_Click(object sender, RoutedEventArgs e)
        {
            if (btnSquare.IsChecked == true)
            {
                btnEllipse.IsChecked = false;
            }
        }
        public Byte[] ByteFromImage(System.Windows.Media.Imaging.BitmapImage imageSource)
        {
            Stream stream = imageSource.StreamSource;
            Byte[] imagebyte = null;
            if (stream != null && stream.Length > 0)
            {
                using (BinaryReader br = new BinaryReader(stream))
                {
                    imagebyte = br.ReadBytes((Int32)stream.Length);
                }
            }

            return imagebyte;
        }
        public byte[] getImgByte(System.Drawing.Image image) //调用方法转字节

        {
            MemoryStream ms = new MemoryStream();
            try
            {
                image.Save(ms, ImageFormat.Bmp);
                byte[] bt = ms.GetBuffer();
                return bt;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                ms.Close();
            }
        }
       
        #region BitmapImage 转为byte[]
        /// <summary>
        /// BitmapImage 转为byte[]
        /// </summary>
        /// <param name="bitmapImage">BitmapImage 对象</param>
        /// <returns>byte[] 数组</returns>
        public  byte[] BitmapImageToByteArray(BitmapImage bitmapImage)
        {
            byte[] buffer = new byte[] { };
            try
            {
                Stream stream = bitmapImage.StreamSource;
                if (stream != null && stream.Length > 0)
                {
                    stream.Position = 0;
                    using (BinaryReader binary = new BinaryReader(stream))
                    {
                        buffer = binary.ReadBytes((int)stream.Length);
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return buffer;
        }
        #endregion
        private void DrawEllipse_Click(object sender, RoutedEventArgs e)
        {
            var r = "";
            System.Drawing.Bitmap b = new System.Drawing.Bitmap(image.UriSource.LocalPath);
            MemoryStream ms = new MemoryStream();
            b.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
            byte[] bytes = ms.GetBuffer();  //byte[]   bytes=   ms.ToArray(); 这两句都可以,至于区别么,下面有解释
            ms.Close();
            var w = new ImgCut(bytes);
            if (w.ShowDialog()==false) {
                MessageBox.Show(w.rate?.ToString());
            }
         
            //if (btnEllipse.IsChecked == true)
            //{
            //    btnSquare.IsChecked = false;
            //}
        }

        private List<System.Windows.Point> GenerateEclipseGeometry(System.Windows.Point st, System.Windows.Point ed)
        {
            double a = 0.5 * (ed.X - st.X);
            double b = 0.5 * (ed.Y - st.Y);
            List<System.Windows.Point> pointList = new List<System.Windows.Point>();
            for (double r = 0; r <= 2 * Math.PI; r = r + 0.01)
            {
                pointList.Add(new System.Windows.Point(0.5 * (st.X + ed.X) + a * Math.Cos(r), 0.5 * (st.Y + ed.Y) + b * Math.Sin(r)));
            }
            return pointList;
        }
        private void InkCanvasMeasure_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                iniP = e.GetPosition(inkCanvasMeasure);
            }
        }

        private void InkCanvasMeasure_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                // Draw square
                if (btnSquare.IsChecked == true)
                {
                    endP = e.GetPosition(inkCanvasMeasure);
                    List<System.Windows.Point> pointList = new List<System.Windows.Point>
                    {
                        new System.Windows.Point(iniP.X, iniP.Y),
                        new System.Windows.Point(iniP.X, endP.Y),
                        new System.Windows.Point(endP.X, endP.Y),
                        new System.Windows.Point(endP.X, iniP.Y),
                        new System.Windows.Point(iniP.X, iniP.Y),
                    };
                    StylusPointCollection point = new StylusPointCollection(pointList);
                    Stroke stroke = new Stroke(point)
                    {
                        DrawingAttributes = inkCanvasMeasure.DefaultDrawingAttributes.Clone()
                    };
                    viewModel.InkStrokes.Clear();
                    viewModel.InkStrokes.Add(stroke);
                }
                // Draw Eclipse
                else if (btnEllipse.IsChecked == true)
                {
                    endP = e.GetPosition(inkCanvasMeasure);
                    List<System.Windows.Point> pointList = GenerateEclipseGeometry(iniP, endP);
                    StylusPointCollection point = new StylusPointCollection(pointList);
                    Stroke stroke = new Stroke(point)
                    {
                        DrawingAttributes = inkCanvasMeasure.DefaultDrawingAttributes.Clone()
                    };
                    viewModel.InkStrokes.Clear();
                    viewModel.InkStrokes.Add(stroke);
                }
            }
        }
        public WindowState SaveWindowState { get; set; }
        public WindowStyle SaveWindowStyle { get; set; }
        public ResizeMode SaveResizeMode { get; set; }
        public bool SaveTopmost { get; set; }
        public double SaveLeft { get; set; }
        public double SaveTop { get; set; }
        public double SaveWidth { get; set; }
        public double SaveHeight { get; set; }
        private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            //记录当前窗口状态


            this.SaveWindowState = this.WindowState;


            this.SaveWindowStyle = this.WindowStyle;


            this.SaveResizeMode = this.ResizeMode;


            this.SaveTopmost = this.Topmost;


            this.SaveLeft = this.Left;


            this.SaveTop = this.Top;


            this.SaveWidth = this.Width;


            this.SaveHeight = this.Height;
            if (e.KeyboardDevice.Modifiers == ModifierKeys.Control && e.Key == Key.H)
            {
                st.Visibility = Visibility.Collapsed;
                //同时按下了Ctrl + H键(H要最后按,因为判断了此次事件的e.Key)
                //修饰键只能按下Ctrl,如果还同时按下了其他修饰键,则不会进入
                // 设置全屏
                this.WindowState = System.Windows.WindowState.Normal;//还原窗口(非最小化和最大化)
                this.WindowStyle = System.Windows.WindowStyle.None;//仅工作区可见,不显示标题栏和边框
                this.ResizeMode = System.Windows.ResizeMode.NoResize;//不显示最大化和最小化按钮
                //this.Topmost = true;
                this.Left = 0.0;
                this.Top = 0.0;
                this.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
                this.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
            }
            else if (e.Key == Key.Escape)
            {
                st.Visibility = Visibility.Visible;

                this.WindowState = this.SaveWindowState;


                this.WindowStyle = this.SaveWindowStyle;


                this.ResizeMode = this.SaveResizeMode;


                this.Topmost = this.SaveTopmost;


                this.Left = this.SaveLeft;


                this.Top = this.SaveTop;


                this.Width = this.SaveWidth;


                this.Height = this.SaveHeight;
            }
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.WindowState = System.Windows.WindowState.Normal;//还原窗口(非最小化和最大化)
            this.WindowStyle = System.Windows.WindowStyle.None; //仅工作区可见,不显示标题栏和边框
            this.ResizeMode = System.Windows.ResizeMode.NoResize;//不显示最大化和最小化按钮
            this.Topmost = true;    //窗口在最前

            this.Left = 0.0;
            this.Top = 0.0;
            this.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
            this.Height = System.Windows.SystemParameters.PrimaryScreenHeight;
        }

        private void Window_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                st.Visibility = Visibility.Visible;

                this.WindowState = this.SaveWindowState;


                this.WindowStyle = this.SaveWindowStyle;


                this.ResizeMode = this.SaveResizeMode;


                this.Topmost = this.SaveTopmost;


                this.Left = this.SaveLeft;


                this.Top = this.SaveTop;


                this.Width = this.SaveWidth;


                this.Height = this.SaveHeight;
            }
        }

        private void inkCanvasMeasure_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Point zs;//左上点
            Point yx;//右下点
            if (endP.X > iniP.X)
            {
                zs = iniP;
                yx = endP;
            }
            else
            {
                zs = endP;
                yx = iniP;
            }
            var pw = imgMeasure.ActualWidth;//图片宽
            var ph = imgMeasure.ActualHeight; //图片高 
            if (yx.Y + 34 < ph)
                sp.Margin = new Thickness(yx.X - 50, yx.Y + 4, 0, 0);
            else
                sp.Margin = new Thickness(yx.X - 50, ph - 34, 0, 0);

            sp.Visibility = Visibility.Visible;
        }

        private void PART_ButtonComplete_Click(object sender, RoutedEventArgs e)
        {
            Point zs;//左上点
            Point yx;//右下点
            if (endP.X > iniP.X)
            {
                zs = iniP;
                yx = endP;
            }
            else
            {
                zs = endP;
                yx = iniP;
            }
            var pw = imgMeasure.ActualWidth;//图片宽
            var ph = imgMeasure.ActualHeight; //图片高 
            MessageBox.Show(Math.Round(zs.X / pw, 4) + "," + Math.Round(zs.Y / ph, 4) + "," + Math.Round(yx.X / pw, 4) + "," + Math.Round(yx.Y / ph, 4));
        }

    }
}

3.ViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Ink;

namespace WPF_InkCanvas
{
    class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName = null)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private string meaInfo;
        public string MeaInfo
        {
            get => meaInfo;
            set
            {
                meaInfo = value;
                OnPropertyChanged("MeaInfo");
            }
        }

        private StrokeCollection inkStrokes;
        public StrokeCollection InkStrokes
        {
            get { return inkStrokes; }
            set
            {
                inkStrokes = value;
                OnPropertyChanged("InkStrokes");
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值