• WPF 矩形框8个控制点伸缩及拖拽


               最近在研发图片控件矩形框8个控制点进行控制边框的大小、位置等信息,之前查阅了相关的信息,比如别人整合的类:ControlResizer 这个类虽然是好,但是很大程度上是有限制,换句话说,它需要你二次更改代码和调整成适应你的代码结构,否则很多边框拖拉的时候无法使用,这也是当时使用的时候很头疼的事情,废话不多说,先上效果图:

           

    如上图所示,分析下:有四个层,第一层是主窗体,第二层是传入的图片控件,第三层是遮罩、第四层也就是控制层(图中显示的可操作的蓝色区域,以下称为裁剪区),注意实现的效果是:

          1、直接拖拽移动裁剪区,不能跑到图片外面,并且在裁剪区之外的所有区域需要实时重新蒙上遮罩。

          2、拖拉图中的8个裁剪区蓝色控制条,要实现控制条相关方向上的任意拖拉实现伸缩,并且有最小裁剪区域。

          3、能根据传入的图片控件信息(图中的包括宽-高-角度(30°),位置信息)进行定位和裁剪。

    下面提供个人的方案进行参考,不一定是最佳方案,不过比对了很多人的控制点方案,我觉得这个可移植性比较高,适用于轻量级的操作,网上的都是各种类与类引用,然后一堆的与Windows自带的东西结合比如Thumb类。相对复杂。不利于学习研究之用,总之我们只要掌握了原理,接下来解决问题就是比较容易。

        解决方案步骤:

         一:创建构造函数(模拟图片控件信息,实际项目中可自行传入信息仅供参考)。

         示例:

         /// <summary>
            /// 构造一个图片控件函数包含位置、角度等信息
            /// </summary>
            public class StructureSource
            {
                public Point Images_Point { get; set; }
                public double ImageAngle;
                public double ImageHeight;
                public double ImageWidth;
                public BitmapImage ImageSource;
    
    
                public StructureSource()
                {
                    Images_Point = new Point(200, 100);
                    ImageAngle = 30.0;
                    ImageSource = new BitmapImage(new Uri("C:\Users\Administrator\Desktop\CompanyLogo\XXX.PNG"));
                    ImageHeight = ImageSource.Height;
                    ImageWidth = ImageSource.Width;
                }
            }

         二:准备主窗体,主窗体需要准备好结构,前面提到了这种伸缩性的功能,它需要放在Canvas容器中进行操作,所以一定要注意它的结构性。

         三:准备好一个用户控件(在图中是蓝色控制条部分)。

         四:初始化主窗体,包含根据图片信息定位,角度等,遮罩,进行裁剪。

        示例:

    this.Loaded += (sender, ex) =>
                 {
                     ImageItem = new StructureSource();
                     this._Images.Source = ImageItem.ImageSource;
                     this._Images.Height = ImageItem.ImageHeight;
                     this._Images.Width = ImageItem.ImageWidth;
                     //定位+旋转角度
                     Matrix m = this._Images.RenderTransform.Value;
                     m.OffsetX = ImageItem.Images_Point.X;
                     m.OffsetY = ImageItem.Images_Point.Y;
                     m.RotateAt(ImageItem.ImageAngle, ImageItem.Images_Point.X, ImageItem.Images_Point.Y);
                     this._Images.RenderTransform = new MatrixTransform(m);
                     //设置背景为黑色
                     _GridBackGround.Background = Brushes.Black;
                     //添加内容
                     _ContentObject = new CuttingControl();
                     _Content.Children.Add(_ContentObject);
                     _ContentObject.SizeChanged += _ContentObject_SizeChanged;
                     _ContentObject.BackGroundDrag += _ContentObject_BackGroundDrag;
                     _Content.Height = ImageItem.ImageHeight;
                     _Content.Width = ImageItem.ImageWidth;
                     //定位+翻转角度
                     Matrix m2 = this._Content.RenderTransform.Value;
                     m2.OffsetX = ImageItem.Images_Point.X;
                     m2.OffsetY = ImageItem.Images_Point.Y;
                     m2.RotateAt(ImageItem.ImageAngle, m2.OffsetX, m2.OffsetY);
                     this._Content.RenderTransform = new MatrixTransform(m2);
    
                     //对选定的区域进行裁剪
    
                     CroppedRegionMethod(this._Content.RenderTransform);
                 };

             五:核心功能代码。拖拽部分(采用矩阵拖拽)

              

     /// <summary>
            /// 移动具体方法
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void TryToMoveForward(object sender, MouseEventArgs e)
            {
                CroppedRegionEndPoint = e.GetPosition((UIElement)this.Parent);
                var MatrixCroppedRegion = this.RenderTransform.Value;
    
                var offsetX = CroppedRegionEndPoint.X - CroppedRegionStartPoint.X;
                var OffsetY = CroppedRegionEndPoint.Y - CroppedRegionStartPoint.Y;
                if (offsetX <= 0)
                {
                    offsetX = 0;
                }
                else
                {
                    if (offsetX + this.ActualWidth >= ((UIElement)this.Parent as FrameworkElement).Width)
                    {
                        offsetX = ((UIElement)this.Parent as FrameworkElement).Width - this.ActualWidth;
                    }
                }
                if (OffsetY <= 0)
                {
                    OffsetY = 0;
                }
                else
                {
                    if (OffsetY + this.ActualHeight >= ((UIElement)this.Parent as FrameworkElement).Height)
                    {
                        OffsetY = ((UIElement)this.Parent as FrameworkElement).Height - this.ActualHeight;
                    }
                }
    
                MatrixCroppedRegion.OffsetX = offsetX;
                MatrixCroppedRegion.OffsetY = OffsetY;
    
                this.RenderTransform = new MatrixTransform(MatrixCroppedRegion);
    
                ClippedRegionChanged(this.RenderTransform, e);
            }

               六:核心代码(控制条拖拉、伸缩)

              示例:

    /// <summary>
            /// 尝试拖拽边框
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void TryToMoveBoarder(object sender, MouseEventArgs e)
            {
                CroppedBoarderEndPoint = e.GetPosition((UIElement)this.Parent);
    
                //控制裁剪区域大小
                var OffsetX = CroppedBoarderEndPoint.X - CroppedBoarderStartPoint.X;
                var OffsetY = CroppedBoarderEndPoint.Y - CroppedBoarderStartPoint.Y;
    
                //控制裁剪区域位置
                var MoveX = CroppedBoarderEndPoint.X - CroppedBoarderPanningStartPoint.X;
                var MoveY = CroppedBoarderEndPoint.Y - CroppedBoarderPanningStartPoint.Y;
    
                //放大拖拉边框
                switch (sender)
                {
                    case "_LeftTop"://OK(研发) OK(修正) OK(测试)
                        #region --左上角控制点--
                        if (CroppedRegionWidth - OffsetX >= this.MinWidth)
                        {
                            //防止宽度先到达临界点而高度不能变化
                            this.Width = CroppedRegionWidth - OffsetX;
                            TryToMoveChangingBoarder("_LeftTop", MoveX, MoveY, "X");
                            //修正超出部分
                            if (this.RenderTransform.Value.OffsetX <= 0)
                            {
                                this.Width = this.Width + MoveX;
                            }
                        }
    
                        if (CroppedRegionHeight - OffsetY >= this.MinHeight)
                        {
                            this.Height = CroppedRegionHeight - OffsetY;
                            TryToMoveChangingBoarder("_LeftTop", MoveX, MoveY, "Y");
                            //修正超出部分
                            if (this.RenderTransform.Value.OffsetY <= 0)
                            {
                                this.Height = this.Height + MoveY;
                            }
                        }
    
                        #endregion
                        break;
                    case "_CenterTop"://OK(研发) OK(修正) OK(测试)
                        #region --顶中部控制点--
                        if (CroppedRegionHeight - OffsetY < this.MinHeight)
                            return;
    
                        this.Height = CroppedRegionHeight - OffsetY;
                        TryToMoveChangingBoarder("_CenterTop", MoveX, MoveY, "");
                        //修正超出部分
                        if (this.RenderTransform.Value.OffsetY <= 0)
                        {
                            this.Height = this.Height + MoveY;
                        }
    
                        #endregion
                        break;
                    case "_RightTop"://OK(研发) OK(修正) OK(测试)
                        #region --右上角控制点--
                        if (CroppedRegionWidth + OffsetX < this.MinWidth)
                        {
                            //防止宽度先到达临界点而高度不能变化
                            if (MoveY >= 0)
                            {
                                if (CroppedRegionHeight - OffsetY < this.MinHeight)
                                    return;
                                this.Height = CroppedRegionHeight - OffsetY;
                                TryToMoveChangingBoarder("_RightTop", MoveX, MoveY, "");
                            }
                        }
                        else
                        {
                            this.Width = CroppedRegionWidth + OffsetX;
                            if (CroppedRegionHeight - OffsetY >= this.MinHeight)
                            {
                                this.Height = CroppedRegionHeight - OffsetY;
                                TryToMoveChangingBoarder("_RightTop", MoveX, MoveY, "");
                                //修正超出部分
                                if (this.RenderTransform.Value.OffsetY <= 0)
                                {
                                    this.Height = this.Height + MoveY;
                                }
                            }
    
                        }
                        #endregion
                        break;
                    case "_LeftCenter"://OK(研发) OK(修正) OK(测试)
                        #region --左中部控制点--
                        if (CroppedRegionWidth - OffsetX < this.MinWidth)
                            return;
    
                        this.Width = CroppedRegionWidth - OffsetX;
                        TryToMoveChangingBoarder("_LeftCenter", MoveX, MoveY, "");
                        //修正超出部分
                        if (this.RenderTransform.Value.OffsetX <= 0)
                        {
                            this.Width = this.Width + MoveX;
                        }
                        #endregion
                        break;
                    case "_RightCenter"://OK(研发) OK(修正) OK(测试)
                        #region --右中部控制点--
                        if (CroppedRegionWidth + OffsetX < this.MinWidth)
                            return;
                        this.Width = CroppedRegionWidth + OffsetX;
                        #endregion
                        break;
                    case "_LeftBottom": //OK(研发) OK(修正) OK(测试)
                        #region --左下角控制点--
                        if (CroppedRegionWidth - OffsetX >= this.MinWidth)
                        {
                            //防止宽度先到达临界点而高度不能变化
                            this.Width = CroppedRegionWidth - OffsetX;
                            TryToMoveChangingBoarder("_LeftBottom", MoveX, MoveY, "X");
                            //修正超出部分
                            if (this.RenderTransform.Value.OffsetX <= 0)
                            {
                                this.Width = this.Width + MoveX;
                            }
                        }
    
    
                        if (CroppedRegionHeight + OffsetY >= this.MinHeight)
                        {
                            this.Height = CroppedRegionHeight + OffsetY;
                        }
                        #endregion
                        break;
                    case "_CenterBottom"://OK(研发) OK(修正) OK(测试)
                        #region --底中部控制点--
                        if (CroppedRegionHeight + OffsetY < this.MinHeight)
                            return;
                        this.Height = CroppedRegionHeight + OffsetY;
                        #endregion
                        break;
                    case "_RightBottom"://OK(研发) OK(修正) OK(测试)
                        #region --右下角控制点--
                        if (CroppedRegionWidth + OffsetX < this.MinWidth)
                        {
                            //防止宽度先到达临界点而高度不能变化
                            if (CroppedRegionHeight + OffsetY < this.MinHeight)
                                return;
                            this.Height = CroppedRegionHeight + OffsetY;
                        }
                        else
                        {
                            this.Width = CroppedRegionWidth + OffsetX;
                            if (CroppedRegionHeight + OffsetY >= this.MinHeight)
                            {
                                this.Height = CroppedRegionHeight + OffsetY;
                            }
                        }
                        #endregion
                        break;
                }
                #region --限定边界范围针对无动画,修正长宽--
    
                if (this.RenderTransform.Value.OffsetX + this.Width >= ((UIElement)this.Parent as FrameworkElement).Width)
                    this.Width = ((UIElement)this.Parent as FrameworkElement).Width - this.RenderTransform.Value.OffsetX;
    
                if (this.RenderTransform.Value.OffsetY + this.Height >= ((UIElement)this.Parent as FrameworkElement).Height)
                    this.Height = ((UIElement)this.Parent as FrameworkElement).Height - this.RenderTransform.Value.OffsetY;
    
    
    
    
    
    
    
                #endregion
    
                if (this.Height >= this.MinHeight)
                    ClippedRegionChanged(this.RenderTransform, e);
            }
    
    
    
    
    
            /// <summary>
            /// 矩阵平移
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="MoveX">平移的X轴距离</param>
            /// <param name="MoveY">平移的Y轴距离</param>
            private void TryToMoveChangingBoarder(string sender, double MoveX, double MoveY, string DirectionXY)
            {
                var m = this.RenderTransform.Value;
                switch (sender)
                {
                    case "_LeftTop":
                        if (DirectionXY == "X")
                            m.OffsetX = MoveX;
                        else
                        {
                            if (MoveY <= 0)
                                m.OffsetY = 0;
                            else
                                m.OffsetY = MoveY;
                        }
                        break;
                    case "_CenterTop":
                        if (MoveY <= 0)
                            m.OffsetY = 0;
                        else
                            m.OffsetY = MoveY;
                        break;
                    case "_RightTop":
                        if (MoveY <= 0)
                            m.OffsetY = 0;
                        else
                            m.OffsetY = MoveY;
                        break;
                    case "_LeftCenter":
                        m.OffsetX = MoveX;
                        break;
                    case "_LeftBottom":
                        if (DirectionXY == "X")
                            m.OffsetX = MoveX;
                        else
                            m.OffsetY = MoveY;
                        break;
                }
                //限制边框不出裁剪区域
                if (m.OffsetX < 0)
                    m.OffsetX = 0;
    
                this.RenderTransform = new MatrixTransform(m);
            }

       目前已经整合成用户控件,方便之后的项目进行引用。这边提供了核心的拖拽,伸缩代码,作为笔记方便以后进行查阅。

         

  • 相关阅读:
    F广搜
    Python中range和xrange的异同之处
    数组中出现次数超过一半的数字
    iOS开发之剖析&quot;秘密&quot;App内容页面效果(一)
    Balloon Comes!
    scikit-learn: isotonic regression(保序回归,非常有意思,仅做知识点了解,但差点儿没用到过)
    C#数据缓存介绍及Caching通用帮助类整理
    SVN Working copying &#39;xxxxx/xxxx/xxxx&#39; locked
    读书笔记-APUE第三版-(7)进程环境
    UVA 10555
  • 原文地址:https://www.cnblogs.com/BarryJames/p/8022306.html
Copyright © 2020-2023  润新知