zoukankan      html  css  js  c++  java
  • 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);
            }

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

         

  • 相关阅读:
    ExtJS小技巧
    Oracle 表的行数、表占用空间大小,列的非空行数、列占用空间大小 查询
    NPM 私服
    IDEA 不编译java以外的文件
    SQL 引号中的问号在PrepareStatement 中不被看作是占位符
    Chrome 浏览器自动填表呈现淡黄色解决
    批量删除Maven 仓库未下载成功.lastupdate 的文件
    Oracle 11g 监听很慢,由于监听日志文件太大引起的问题(Windows 下)
    Hibernate 自动更新表出错 建表或添加列,提示标识符无效
    Hibernate 自动更新表出错 More than one table found in namespace
  • 原文地址:https://www.cnblogs.com/BarryJames/p/8022306.html
Copyright © 2011-2022 走看看