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

简介: 原文:WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图) 一、说明:上一次写的”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
            { 
            
            }
            
        }


目录
相关文章
|
C# 虚拟化 索引
【WPF】UI虚拟化之------自定义VirtualizingWrapPanel
原文:【WPF】UI虚拟化之------自定义VirtualizingWrapPanel 前言 前几天QA报了一个关于OOM的bug,在排查的过程中发现,ListBox控件中被塞入了过多的Item,而ListBox又定义了两种样式的ItemsPanelTemplate。
2212 0
|
C# 数据安全/隐私保护
【WPF】右下角弹出自定义通知样式(Notification)——简单教程
原文:【WPF】右下角弹出自定义通知样式(Notification)——简单教程 1.先看效果 2.实现 1.主界面是MainWindow 上面就只摆放一个Button即可。
3059 1
|
3月前
|
开发框架 缓存 前端开发
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(11) -- 下拉列表的数据绑定以及自定义系统字典列表控件
|
3月前
|
C# 微服务 Windows
模块化革命:揭秘WPF与微服务架构的完美融合——从单一职责原则到事件聚合器模式,构建高度解耦与可扩展的应用程序
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中借鉴微服务架构思想,实现模块化设计。通过将WPF应用分解为独立的功能模块,并利用事件聚合器实现模块间解耦通信,可以有效提升开发效率和系统可维护性。文中还提供了具体示例代码,展示了如何使用事件聚合器进行模块间通信,以及如何利用依赖注入进一步提高模块解耦程度。此方法不仅有助于简化复杂度,还能使应用更加灵活易扩展。
105 0
|
3月前
|
C# Windows 监控
WPF应用跨界成长秘籍:深度揭秘如何与Windows服务完美交互,扩展功能无界限!
【8月更文挑战第31天】WPF(Windows Presentation Foundation)是 .NET 框架下的图形界面技术,具有丰富的界面设计和灵活的客户端功能。在某些场景下,WPF 应用需与 Windows 服务交互以实现后台任务处理、系统监控等功能。本文探讨了两者交互的方法,并通过示例代码展示了如何扩展 WPF 应用的功能。首先介绍了 Windows 服务的基础知识,然后阐述了创建 Windows 服务、设计通信接口及 WPF 客户端调用服务的具体步骤。通过合理的交互设计,WPF 应用可获得更强的后台处理能力和系统级操作权限,提升应用的整体性能。
109 0
|
3月前
|
开发框架 前端开发 JavaScript
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(3)--自定义用户控件
|
3月前
|
C#
WPF 自定义可拖动标题栏
WPF 自定义可拖动标题栏
51 0
|
3月前
|
开发框架 前端开发 C#
使用WPF开发自定义用户控件,以及实现相关自定义事件的处理
使用WPF开发自定义用户控件,以及实现相关自定义事件的处理
|
前端开发 C# 图形学
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了。用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架。依赖属性(DependencyProperty)是为用户控件提供可支持双向绑定的必备技巧之一,同样用处也非常广泛。
949 0
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
|
C# C++ 数据可视化
WPF Calendar 日历控件 样式自定义
原文:WPF Calendar 日历控件 样式自定义 粗略的在代码上做了些注释 blend 生成出来的模版 有的时候 会生成 跟 vs ui界面不兼容的代码 会导致可视化设计界面 报错崩溃掉 但是确不影响 程序的编译运行 这个样式表 在vs 里会提示动画不兼容 Foreground属性 报错 ...
1778 1