WPF 自定义图片剪切器 - 头像剪切。你懂得

说废话,无卵用、代码可能有点乱


一、剪切器界面设计

<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" 
             PreviewMouseDown="UserControl_MouseDown" PreviewMouseUp="UserControl_MouseUp" MouseLeave="UserControl_MouseLeave" PreviewMouseMove="UserControl_MouseMove"
             >
    <Grid Name="MainGrid" MinHeight="200" MinWidth="200" >
            <Image Name="SoureceImage" Stretch="Fill"></Image>
            <Border Name="ImageArea"  BorderBrush="Red" BorderThickness="1,1,1,1" Panel.ZIndex="5" Margin="50"  Width="100" Height="100"> 
            <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>


二、剪辑器后台设计

using DialogEx.Class;
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
    {
        #region 公共字段

        public static readonly RoutedEvent OnCutImagingEventHandler = EventManager.RegisterRoutedEvent("OnCutImaging", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ImageDealer));
        public event RoutedEventHandler OnCutImaging
        {
            add { base.AddHandler(OnCutImagingEventHandler, value); }
            remove { base.RemoveHandler(OnCutImagingEventHandler, value); }
        }
        private BitmapImage _BitSource;
        public BitmapImage BitSource
        {
            get { return this._BitSource; }
            set 
            {
                this._BitSource = value;
                this.SoureceImage.Source = value;
                //CutImage();
            } 
        }
        #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 ImageDealer()
        {
            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)
            {
                BitmapSource source = (BitmapSource)this.BitSource;
                //计算比例
                Point Locate = this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
                int dWidth = (int)((this.ImageArea.ActualWidth * 1.0 / this.MainGrid.ActualWidth) * source.PixelWidth);
                int dHeight = (int)((this.ImageArea.ActualHeight * 1.0 / this.MainGrid.ActualHeight) * source.PixelHeight);
                int dLeft = (int)((Locate.X * 1.0 / this.MainGrid.ActualWidth) * source.PixelWidth);
                int dTop = (int)((Locate.Y * 1.0 / this.MainGrid.ActualHeight) * 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);
                //通知订阅
                RaiseEvent(new RoutedEventArgs(OnCutImagingEventHandler, bit));
            }
        }
        /// <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;

        }
        #endregion

        
    }
}


三、还需要一个蛋疼的辅助类


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DialogEx.Class
{
    /// <summary>
    /// 鼠标八大位置枚举
    /// </summary>
    public enum MouseLocationEnum
    {
        None,
        Left,
        Up,
        Right,
        Down,
        LeftUp,
        LeftDown,
        RightUp,
        RightDown
    }
    /// <summary>
    /// 
    /// </summary>
    public class RectangleAreaModel
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }
    }
    /// <summary>
    /// 鼠标状态
    /// </summary>
    public enum MouseActionEx
    {
        /// <summary>
        /// 无
        /// </summary>
        None,
        /// <summary>
        /// 拖拽
        /// </summary>
        Drag,
        /// <summary>
        /// 拖动
        /// </summary>
        DragMove
    }

    public enum SculptureAction
    {
        Nomal,
        Video,
        Image,
    }

}


四、使用方法 - 下面这个是框架下的事件请尝试改成普通事件。我比较懒 - 希望能看懂。

<pre name="code" class="csharp">界面使用
</pre><pre name="code" class="csharp">xmlns:MyControls="clr-namespace:DialogEx.Controls;assembly=DialogEx"
<MyControls:ImageDealer Panel.ZIndex="0" x:Name="ImageDealer" cal:Message.Attach="[Event OnCutImaging]=[Action OnCutImaging($EventArgs)]"></MyControls:ImageDealer>
 
/// <summary>  
/// 截图中 - 实时
<span style="white-space:pre">	</span>/// </summary>
        /// <param name="source"></param>
        public void OnCutImaging(object source)
        {
            if (source != null && source.GetType() == typeof(RoutedEventArgs))
            {
                // if (((RoutedEventArgs)source).OriginalSource.GetType() == typeof(CroppedBitmap))
                {
<pre name="code" class="csharp"><span style="white-space:pre">			</span>//得到了截图图片
                    BitmapSource CurBitMap = (BitmapSource)((RoutedEventArgs)source).OriginalSource;
                    
                    //下面就是对接到的图片处理了。建议将图片保存在Image控件<span style="font-family: Arial, Helvetica, sans-serif;">中。界面上用ContentPresenter。
<span style="white-space:pre">		</span>}
            }
        }
 
 

五、关于明明截图成功,更换了头像。结果界面上显示的头像仍是以前的头像。

那么你肯能碰到这个问题了

http://blog.csdn.net/lvguoshan/article/details/47172109



六、最近刚根据本篇缺陷写了个升级版。由于篇幅问题重新写了一篇新的

http://blog.csdn.net/lvguoshan/article/details/48627031




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值