且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)

更新时间:2022-09-17 10:13:19

原文:WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)

WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)


一、说明:上一次写的WPF 自定义图片剪切器 - 头像剪切。你懂得存在明显的缺陷,由于篇幅较长。重新写了一篇新的。

问题的原因:由于是对图片文件进行剪切处理,当图片加载后变形的话,处理起来明显的有错误!

解决办法:重新计算比例。但是有个问题就是在原来的基础上重新计算,计算量会相当复杂。因为整个截图区域就那么大,是固          定的,而图片可大可小,你要是想正确获取加载后的图片与截图区域的比例将会变得相当麻烦。


所以,本次采用一个最基本的设计技巧,就是 截图区域 = 图片加载后的区域 !将截图控件ImageDealerUnsafe按照大小可变化的情况封装在自定义控件ImageDealer里,通过自定义控件ImageDealer封装截图控件的调用接口,而ImageDealerUnsafe


二、关于截图控件(ImageDealerUnsafe)  用户不应调用该控件的任何方法、仅供ImageDealer调用

1、截图控件 ImageDealerUnsafe XAML

<UserControl x:Class="DialogEx.Controls.Unsafe.ImageDealerUnsafe"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" Background="Transparent"
             SnapsToDevicePixels="True" 
             PreviewMouseDown="UserControl_MouseDown" PreviewMouseUp="UserControl_MouseUp" MouseLeave="UserControl_MouseLeave" PreviewMouseMove="UserControl_MouseMove"
            
             >
    <Grid Name="MainGrid"  >
        <Image Name="SoureceImage" Stretch="Uniform"></Image>
        <Border Name="ImageArea"  BorderBrush="Red" BorderThickness="1,1,1,1" Panel.ZIndex="5" Margin="50" SizeChanged="ImageArea_SizeChanged">
            <Grid >
                <Rectangle Name="R_LeftUp"    Width="5" Height="5" Margin="-3" VerticalAlignment="Top"    HorizontalAlignment="Left"   Fill="White" Panel.ZIndex="0" Cursor="SizeNWSE"/>
                <Rectangle Name="R_Up"        Width="5" Height="5" Margin="-3" VerticalAlignment="Top"    HorizontalAlignment="Center" Fill="White" Panel.ZIndex="0" Cursor="SizeNS"/>
                <Rectangle Name="R_RightUp"   Width="5" Height="5" Margin="-3" VerticalAlignment="Top"    HorizontalAlignment="Right"  Fill="White" Panel.ZIndex="0" Cursor="SizeNESW"/>
                <Rectangle Name="R_Right"     Width="5" Height="5" Margin="-3" VerticalAlignment="Center" HorizontalAlignment="Right"  Fill="White" Panel.ZIndex="0" Cursor="SizeWE"/>
                <Rectangle Name="R_RightDown" Width="5" Height="5" Margin="-3" VerticalAlignment="Bottom" HorizontalAlignment="Right"  Fill="White" Panel.ZIndex="0" Cursor="SizeNWSE"/>
                <Rectangle Name="R_Down"      Width="5" Height="5" Margin="-3" VerticalAlignment="Bottom" HorizontalAlignment="Center" Fill="White" Panel.ZIndex="0" Cursor="SizeNS"/>
                <Rectangle Name="R_LeftDown"  Width="5" Height="5" Margin="-3" VerticalAlignment="Bottom" HorizontalAlignment="Left"   Fill="White" Panel.ZIndex="0" Cursor="SizeNESW"/>
                <Rectangle Name="R_Left"      Width="5" Height="5" Margin="-3" VerticalAlignment="Center" HorizontalAlignment="Left"   Fill="White" Panel.ZIndex="0" Cursor="SizeWE"/>
                <!--<GridSplitter Height="5" Width="5" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"></GridSplitter>-->
            </Grid>
        </Border>

    </Grid>
</UserControl>

2、截图控件ImageDealerUnsafeCS

using DialogEx.Class;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DialogEx.Controls.Unsafe
{
    /// <summary>
    /// ImageDealerUnsafe.xaml 的交互逻辑
    /// </summary>
    public partial class ImageDealerUnsafe : UserControl
    {
        
        #region 公共字段
        //截图回调
        public delegate void CutImageDelegate(BitmapSource bit);
        public CutImageDelegate OnCutImage;
        //图片原
        private BitmapImage _BitSource;
        public BitmapImage BitSource
        {
            get { return this._BitSource; }
            set 
            {
                this._BitSource = value;
                this.SoureceImage.Source = value;
            } 
        }
        #endregion

        #region 依赖属性

        /// <summary>
        /// 边距
        /// </summary>
        public double MaxMargin = 2;

        //public Brush BorderBrush;
        
        #endregion

        #region ==私有字段==
        /// <summary>
        /// 鼠标样式
        /// </summary>
        private Cursor MouseCursor = Cursors.Arrow;
        /// <summary>
        /// 鼠标位置
        /// </summary>
        private MouseLocationEnum MouseLocation = MouseLocationEnum.None;
        /// <summary>
        /// 鼠标行为
        /// </summary>
        private MouseActionEx Action { get; set; }
        /// <summary>
        /// 边框粗细
        /// </summary>
        private double BorderWidth = 1;
        /// <summary>
        /// 拖拽前鼠标按下位置
        /// </summary>
        private Point MouseDownPoint;
        /// <summary>
        /// 拖拽前控件位置
        /// </summary>
        private Point MouseDownLocate;

        #endregion

        #region ==方法==
        public ImageDealerUnsafe()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 计算区域圆点及宽高
        /// </summary>
        /// <param name="MouseButtonLocate">鼠标相对背景MainGrid位置</param>
        /// <param name="IsRectangle">是否正方形</param>
        /// <returns>NULL 或 具体值</returns>
        private RectangleAreaModel CalculatedArea(Point MouseButtonLocate, bool IsRectangle)
        {
            Point Locate = this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
            //边框宽度
            double BorderWidth = this.BorderWidth;
            //整体宽度
            double RectWidth = this.ImageArea.ActualWidth;
            //整体高度
            double RectHeight = this.ImageArea.ActualHeight;

            //裁剪区域
            Point OriginalPoint = new Point(0, 0);//圆点坐标
            Point TheoryPoint = new Point(0, 0);  //理论坐标
            double TheoryWidth = 0;   //理论宽度
            double TheoryHeight = 0;  //理论高度
            switch (MouseLocation)
            {
                case MouseLocationEnum.Left:
                    {
                        this.Cursor = Cursors.SizeWE;

                        OriginalPoint = new Point(Locate.X + RectWidth - BorderWidth / 2, Locate.Y + RectHeight / 2);//右中部位置
                        TheoryWidth = OriginalPoint.X - MouseButtonLocate.X + BorderWidth;
                        TheoryHeight = IsRectangle == true ? TheoryWidth : RectHeight;

                        TheoryPoint = new Point(OriginalPoint.X + BorderWidth / 2 - TheoryWidth, OriginalPoint.Y - TheoryHeight / 2);
                    }
                    break;
                case MouseLocationEnum.LeftUp:
                    {
                        this.Cursor = Cursors.SizeNWSE;

                        OriginalPoint = new Point(Locate.X + RectWidth - BorderWidth / 2, Locate.Y + RectHeight - BorderWidth / 2);//右下部位置
                        TheoryWidth = OriginalPoint.X - MouseButtonLocate.X + BorderWidth;
                        TheoryHeight = IsRectangle == true ? TheoryWidth : OriginalPoint.Y - MouseButtonLocate.Y + BorderWidth;

                        TheoryPoint = new Point(OriginalPoint.X + BorderWidth / 2 - TheoryWidth, OriginalPoint.Y + BorderWidth / 2 - TheoryHeight);
                    }
                    break;
                case MouseLocationEnum.Up:
                    {
                        this.Cursor = Cursors.SizeNS;

                        OriginalPoint = new Point(Locate.X + RectWidth / 2, Locate.Y + RectHeight - BorderWidth / 2);//下中部位置
                        TheoryHeight = OriginalPoint.Y - MouseButtonLocate.Y + BorderWidth;
                        TheoryWidth = IsRectangle == true ? TheoryHeight : RectWidth;

                        TheoryPoint = new Point(OriginalPoint.X - TheoryWidth / 2, OriginalPoint.Y + BorderWidth / 2 - TheoryHeight);
                    }
                    break;
                case MouseLocationEnum.RightUp:
                    {
                        this.Cursor = Cursors.SizeNESW;

                        OriginalPoint = new Point(Locate.X + BorderWidth / 2, Locate.Y + RectHeight - BorderWidth / 2);//左下部位置
                        TheoryWidth = MouseButtonLocate.X - OriginalPoint.X + BorderWidth;
                        TheoryHeight = IsRectangle == true ? TheoryWidth : MouseButtonLocate.Y - OriginalPoint.Y + BorderWidth;

                        TheoryPoint = new Point(OriginalPoint.X - BorderWidth / 2, OriginalPoint.Y + BorderWidth / 2 - TheoryHeight);
                    }
                    break;
                case MouseLocationEnum.Right:
                    {
                        this.Cursor = Cursors.SizeWE;

                        OriginalPoint = new Point(Locate.X + BorderWidth / 2, Locate.Y + RectHeight / 2);//左中部位置
                        TheoryWidth = MouseButtonLocate.X - OriginalPoint.X + BorderWidth;
                        TheoryHeight = IsRectangle == true ? TheoryWidth : RectHeight;

                        TheoryPoint = new Point(OriginalPoint.X - BorderWidth / 2, OriginalPoint.Y - TheoryHeight / 2);
                    }
                    break;
                case MouseLocationEnum.RightDown:
                    {
                        this.Cursor = Cursors.SizeNWSE;

                        OriginalPoint = new Point(Locate.X + BorderWidth / 2, Locate.Y + BorderWidth / 2);//左上部位置
                        TheoryWidth = MouseButtonLocate.X - OriginalPoint.X + BorderWidth;
                        TheoryHeight = IsRectangle == true ? TheoryWidth : MouseButtonLocate.Y - OriginalPoint.Y + BorderWidth;

                        TheoryPoint = new Point(OriginalPoint.X - BorderWidth / 2, OriginalPoint.Y - BorderWidth / 2);
                    }
                    break;
                case MouseLocationEnum.Down:
                    {
                        this.Cursor = Cursors.SizeNS;

                        OriginalPoint = new Point(Locate.X + RectWidth / 2, Locate.Y + BorderWidth / 2);//上中部位置
                        TheoryHeight = MouseButtonLocate.Y - OriginalPoint.Y + BorderWidth;
                        TheoryWidth = IsRectangle == true ? TheoryHeight : RectWidth;

                        TheoryPoint = new Point(OriginalPoint.X - TheoryWidth / 2, OriginalPoint.Y - BorderWidth / 2);
                    }
                    break;
                case MouseLocationEnum.LeftDown:
                    {
                        this.Cursor = Cursors.SizeNESW;

                        OriginalPoint = new Point(Locate.X + RectWidth - BorderWidth / 2, Locate.Y + BorderWidth / 2);//右上部位置
                        TheoryWidth = OriginalPoint.X - MouseButtonLocate.X + BorderWidth;
                        TheoryHeight = IsRectangle == true ? TheoryWidth : OriginalPoint.Y - MouseButtonLocate.Y + BorderWidth;

                        TheoryPoint = new Point(OriginalPoint.X + BorderWidth / 2 - TheoryWidth, OriginalPoint.Y - BorderWidth / 2);
                    }
                    break;
                default:
                    return null;
            }
            return new RectangleAreaModel()
            {
                X = TheoryPoint.X,
                Y = TheoryPoint.Y,
                Width = TheoryWidth,
                Height = TheoryHeight
            };
        }
        
        /// <summary>
        /// 图片剪切
        /// </summary>
        public void CutImage()
        {
            if (this.BitSource != null)
            {
                try
                {
                    double ImageAreaWidth = this.ImageArea.ActualWidth;
                    double ImageAreaHeight = this.ImageArea.ActualHeight;
                    double GridWidth = this.MainGrid.ActualWidth;
                    double GridHeight = this.MainGrid.ActualHeight;

                    BitmapSource source = (BitmapSource)this.BitSource;
                    //计算比例
                    Point Locate = this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
                    int dWidth = (int)((ImageAreaWidth * 1.0 / GridWidth) * source.PixelWidth);
                    int dHeight = (int)((ImageAreaHeight * 1.0 / GridHeight) * source.PixelHeight);
                    int dLeft = (int)((Locate.X * 1.0 / GridWidth) * source.PixelWidth);
                    int dTop = (int)((Locate.Y * 1.0 / GridHeight) * source.PixelHeight);
                    //像素区域
                    Int32Rect cutRect = new Int32Rect(dLeft, dTop, dWidth, dHeight);
                    //数组字节数
                    int stride = source.Format.BitsPerPixel * cutRect.Width / 8;
                    byte[] data = new byte[cutRect.Height * stride];
                    source.CopyPixels(cutRect, data, stride, 0);
                    //创建
                    BitmapSource bit = BitmapSource.Create(dWidth, dHeight, 0, 0, PixelFormats.Bgr32, null, data, stride);
                    //通知订阅
                    if (this.OnCutImage != null)
                    {
                        OnCutImage(bit);
                    }            
                }
                catch
                { 
                    
                }
            }
        }
        /// <summary>
        /// 视图转图片
        /// </summary>
        /// <param name="vsual"></param>
        /// <param name="nLeft"></param>
        /// <param name="nTop"></param>
        /// <param name="nWidth"></param>
        /// <param name="nHeight"></param>
        /// <returns></returns>
        private RenderTargetBitmap RenderVisaulToBitmap(Visual vsual,int nLeft, int nTop,int nWidth, int nHeight)
        {
            var rtb = new RenderTargetBitmap(nWidth, nHeight, nLeft, nTop, PixelFormats.Default);
            rtb.Render(vsual);

            return rtb;
        }
        /// <summary>
        /// Bitmap转图片
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        public BitmapSource ToBitmapSource(System.Drawing.Bitmap bmp)
        {
            BitmapSource returnSource;

            try
            {
                returnSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
            }
            catch
            {
                returnSource = null;
            }

            return returnSource;

        }
        #endregion
       
        #region ==事件==
        
        //按下鼠标
        private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.MouseLocation = Class.MouseLocationEnum.None;
            if (e.OriginalSource.GetType() == typeof(Rectangle))
            {
                Rectangle Act = e.OriginalSource as Rectangle;
                switch (Act.Name)
                {
                    case "R_Left": MouseLocation = Class.MouseLocationEnum.Left; break;
                    case "R_LeftUp": MouseLocation = Class.MouseLocationEnum.LeftUp; break;
                    case "R_Up": MouseLocation = Class.MouseLocationEnum.Up; break;
                    case "R_RightUp": MouseLocation = Class.MouseLocationEnum.RightUp; break;
                    case "R_Right": MouseLocation = Class.MouseLocationEnum.Right; break;
                    case "R_RightDown": MouseLocation = Class.MouseLocationEnum.RightDown; break;
                    case "R_Down": MouseLocation = Class.MouseLocationEnum.Down; break;
                    case "R_LeftDown": MouseLocation = Class.MouseLocationEnum.LeftDown; break;
                    default: MouseLocation = Class.MouseLocationEnum.None; break;
                }

                this.Action = MouseActionEx.Drag;
            }
            else
            {
                this.MouseDownPoint = Mouse.GetPosition(e.Source as FrameworkElement);//WPF方法
                this.MouseDownLocate = this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
                if ((this.MouseDownLocate.X < this.MouseDownPoint.X && this.MouseDownPoint.X < this.MouseDownLocate.X + this.ImageArea.ActualWidth) &&
                    (this.MouseDownLocate.Y < this.MouseDownPoint.Y && this.MouseDownPoint.Y < this.MouseDownLocate.Y + this.ImageArea.ActualHeight)
                    )
                {
                    this.Action = MouseActionEx.DragMove;
                }
            }

        }
        //弹起鼠标
        private void UserControl_MouseUp(object sender, MouseButtonEventArgs e)
        {
            this.Action = MouseActionEx.None;
            this.Cursor = Cursors.Arrow;
        }
        //移动鼠标
        private void UserControl_MouseMove(object sender, MouseEventArgs e)
        {
            //鼠标相对空间区域位置
            Point MousePoint = e.GetPosition((IInputElement)this.MainGrid);
            Point ImageLocate= this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
            if (ImageLocate.X <= MousePoint.X && MousePoint.X <= ImageLocate.X + this.ImageArea.ActualWidth &&
                ImageLocate.Y <= MousePoint.Y && MousePoint.Y <= ImageLocate.Y + this.ImageArea.ActualHeight)
            {
                this.Cursor = Cursors.Hand;
            }
            else
            {
                this.Cursor = Cursors.Arrow;
            }
            //边框拉伸
            if (this.Action == MouseActionEx.Drag)
            {
                this.Cursor = this.MouseCursor;
                //剪辑图片区域宽高
                double ImageAreaWidth = this.ImageArea.ActualWidth;
                double ImageAreaHeight = this.ImageArea.ActualHeight;

                //裁剪区域理论位置
                RectangleAreaModel Model = this.CalculatedArea(MousePoint, true);
                if (Model != null)
                {
                    //不能超出边界区域
                    if (Model.X + Model.Width + MaxMargin > this.ActualWidth ||
                        Model.Y + Model.Height + MaxMargin > this.ActualHeight ||
                        Model.X < MaxMargin ||
                        Model.Y < MaxMargin
                        )
                    {
                        this.Cursor = Cursors.Arrow;
                        this.Action = MouseActionEx.None;
                        return;
                    }
                    this.ImageArea.Width = Model.Width;
                    this.ImageArea.Height = Model.Height;

                    this.ImageArea.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Left);
                    this.ImageArea.SetValue(VerticalAlignmentProperty, VerticalAlignment.Top);
                    this.ImageArea.SetValue(MarginProperty, new Thickness(Model.X, Model.Y, 0, 0));

                    CutImage();
                }
            }
            else if (this.Action == MouseActionEx.DragMove)//拖动
            {
                double Left = this.MouseDownLocate.X + (MousePoint.X - MouseDownPoint.X);
                double Top = this.MouseDownLocate.Y + (MousePoint.Y - MouseDownPoint.Y);
                //不能超出边界区域
                if (Left < MaxMargin ||
                    Top < MaxMargin ||
                    (Left + this.ImageArea.ActualWidth + MaxMargin) > this.ActualWidth ||
                    (Top + this.ImageArea.ActualHeight + MaxMargin) > this.ActualHeight)
                {
                    this.Cursor = Cursors.Arrow;
                    this.Action = MouseActionEx.None;
                    return;
                }
                this.ImageArea.Width = this.ImageArea.ActualWidth;
                this.ImageArea.Height = this.ImageArea.ActualHeight;

                this.ImageArea.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Left);
                this.ImageArea.SetValue(VerticalAlignmentProperty, VerticalAlignment.Top);
                this.ImageArea.SetValue(MarginProperty, new Thickness(Left, Top, 0, 0));

                CutImage();
            }
            else
            {
                //this.Cursor = Cursors.Arrow;
            }
        }
        //鼠标离开
        private void UserControl_MouseLeave(object sender, MouseEventArgs e)
        {
            this.Action = MouseActionEx.None;

        }
        //加载完成后截图
        private void ImageArea_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            this.CutImage();
        }

        #endregion  
    }
}


三、封装的截图工具 ImageDealer


1、ImageDealer XAML

<UserControl x:Class="DialogEx.Controls.ImageDealer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" Background="Transparent"
             SnapsToDevicePixels="True" 
             Loaded="UserControl_Loaded"
             >
    <Grid Name="MainGrid" MinHeight="200" MinWidth="200" >
    </Grid>
</UserControl>

2、ImageDealer CS

using DialogEx.Class;
using DialogEx.Controls.Unsafe;
using System;
using System.Collections.Generic;
using System.Linq;
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.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DialogEx.Controls
{
     
    public partial class ImageDealer : UserControl
    {
        public static readonly RoutedEvent OnCutImagingEventHandler = EventManager.RegisterRoutedEvent("OnCutImaging", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ImageDealer));

        #region 私有字段
        /// <summary>
        /// 截图控件
        /// </summary>
        private ImageDealerUnsafe _ImageDealerControl = new ImageDealerUnsafe();
        /// <summary>
        /// 图片源
        /// </summary>
        private BitmapImage _BitSource;
        private int _ChangeMargin = 1;
        #endregion

        #region 公共字段
        
        /// <summary>
        /// 图片源
        /// </summary>
        public BitmapImage BitSource
        {
            get { return this._BitSource; }
            set
            {
                this._BitSource = value;
                this._ImageDealerControl.BitSource = value;
                LocateInit();
            }
        }

        /// <summary>
        /// 截图事件
        /// </summary>
        public event RoutedEventHandler OnCutImaging
        {
            add { base.AddHandler(OnCutImagingEventHandler, value); }
            remove { base.RemoveHandler(OnCutImagingEventHandler, value); }
        }

        #endregion

        #region ==方法==

        public ImageDealer()
        {
            InitializeComponent();
            this._ImageDealerControl.OnCutImage += this.OnCutImage;
        }
        //外部截图
        public void CutImage()
        {
            if (this.IsLoaded == true || this._ImageDealerControl == null)
            {
                this._ImageDealerControl.CutImage();
            }
            else
            {
                throw new Exception("尚未创建视图时无法截图!");
            }
        }
        //截图控件位置初始化
        private void LocateInit()
        {
            double Margin = 1;
            if (this._BitSource != null)
            {
                double percent = 1;
                //根据最小倍率放大截图控件
                percent = (this._BitSource.PixelHeight * 1.0 / this.ActualHeight);
                percent = percent < (this._BitSource.PixelWidth * 1.0 / this.ActualWidth) ? (this._BitSource.PixelWidth * 1.0 / this.ActualWidth) : percent;
                this._ImageDealerControl.Width = this._BitSource.PixelWidth * 1.0 / percent;
                this._ImageDealerControl.Height = this._BitSource.PixelHeight * 1.0 / percent;
                //初始化截图方块
                this._ImageDealerControl.ImageArea.Width = this._ImageDealerControl.ImageArea.Height = 100 +  _ChangeMargin ;
                _ChangeMargin = -_ChangeMargin;
                this._ImageDealerControl.ImageArea.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
                this._ImageDealerControl.ImageArea.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
                this._ImageDealerControl.ImageArea.SetValue(MarginProperty, new Thickness(0));
                //截图控件相对父控件Margin
                this._ImageDealerControl.Width -= 2 * Margin;
                this._ImageDealerControl.Height -= 2 * Margin;
                this._ImageDealerControl.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
                this._ImageDealerControl.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
                this._ImageDealerControl.SetValue(MarginProperty, new Thickness(0));
            }
        }

        #endregion
        
        #region ==事件==

        //截图回调
        private void OnCutImage(BitmapSource bit)
        {
            RaiseEvent(new RoutedEventArgs(OnCutImagingEventHandler, bit));
        }
        //加载完成
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (this.MainGrid.Children.Contains(this._ImageDealerControl) == false)
            {
                this.MainGrid.Children.Add(this._ImageDealerControl);
                this._ImageDealerControl.Width = this.ActualWidth;
                this._ImageDealerControl.Height = this.ActualHeight;
                this._ImageDealerControl.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
                this._ImageDealerControl.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
                this._ImageDealerControl.SetValue(MarginProperty, new Thickness(0));
            }
        } 

        #endregion

        
        
    }
}

四、用户调用

1、外部调用 Windows 的 XAML

xmlns:MyControls="clr-namespace:DialogEx.Controls;assembly=DialogEx"

<!--图片选择区域-->
<pre name="code" class="csharp" style="font-size: 14px;"><Grid Visibility="{Binding ImageVisible}">
   <MyControls:ImageDealer Panel.ZIndex="0" x:Name="ImageDealer" <span style="font-family: Arial, Helvetica, sans-serif;">OnCutImaging</span><span style="font-family: Arial, Helvetica, sans-serif;">="</span><span style="font-family: Arial, Helvetica, sans-serif;">OnCutImaging"></MyControls:ImageDealer></span>
</Grid>


2、Windows 的 CS

包含两个方法

1、获取截图控件的截取的图片(被动的接收通知、回调)

2、保存头像文件、加载头像的时候请使用缓存方式

 private BitmapSource CurBitMap;

<span style="white-space:pre">	</span>/// <summary>
<span style="white-space:pre">	</span>/// 截图中
<span style="white-space:pre">	</span>/// </summary>
<span style="white-space:pre">	</span>/// <param name="source"></param>
        public void OnCutImaging(object source)
        {
            if (source != null && source.GetType() == typeof(RoutedEventArgs))
            {
                // if (((RoutedEventArgs)source).OriginalSource.GetType() == typeof(CroppedBitmap))
                {
                    CurBitMap = (BitmapSource)((RoutedEventArgs)source).OriginalSource;
                }
            }
        }

<span style="white-space:pre">	</span>/// <summary>
        /// 保存头像
        /// </summary>
        public void btnCutPicture_Click()
        {
            string strFilePath = "F:\\1.png";
            //try
            {
                if (File.Exists(strFilePath) == true)
                {
                    File.Delete(strFilePath);
                }
                JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(this.CurBitMap));

                FileStream fileStream = new FileStream(strFilePath, FileMode.Create, FileAccess.ReadWrite);
                encoder.Save(fileStream);
                fileStream.Close();
            }
            //catch
            { 
            
            }
            
        }