Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何调整旋转控件的大小而不基于当前位置X和Y更改纵横比?_C#_Wpf_Controls_Transform - Fatal编程技术网

C# 如何调整旋转控件的大小而不基于当前位置X和Y更改纵横比?

C# 如何调整旋转控件的大小而不基于当前位置X和Y更改纵横比?,c#,wpf,controls,transform,C#,Wpf,Controls,Transform,目前我使用了以下代码,它工作正常,但不考虑纵横比: private double angle; private Point transformOrigin; private ContentControl designerItem; public ResizeThumb() { DragStarted += new DragStartedEventHandler(this.ResizeThumb_DragStarted);

目前我使用了以下代码,它工作正常,但不考虑纵横比:

    private double angle;
    private Point transformOrigin;
    private ContentControl designerItem;

    public ResizeThumb()
    {
        DragStarted += new DragStartedEventHandler(this.ResizeThumb_DragStarted);
        DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
    }

    private void ResizeThumb_DragStarted(object sender, DragStartedEventArgs e)
    {
        this.designerItem = DataContext as ContentControl;

        if (this.designerItem != null)
        {
            this.transformOrigin = this.designerItem.RenderTransformOrigin;
            RotateTransform rotateTransform = this.designerItem.RenderTransform as RotateTransform;
            if (rotateTransform != null)
                this.angle = rotateTransform.Angle * Math.PI / 180.0;
            else
                this.angle = 0;
        }
    }

    private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
    {
        if (this.designerItem != null)
        {
            double deltaVertical, deltaHorizontal;

            switch (VerticalAlignment)
            {
                case System.Windows.VerticalAlignment.Bottom:
                    deltaVertical = Math.Min(-e.VerticalChange, this.designerItem.ActualHeight - this.designerItem.MinHeight);
                    Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + (this.transformOrigin.Y * deltaVertical * (1 - Math.Cos(-this.angle))));
                    Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) - deltaVertical * this.transformOrigin.Y * Math.Sin(-this.angle));
                    this.designerItem.Height -= deltaVertical;
                    break;
                case System.Windows.VerticalAlignment.Top:
                    deltaVertical = Math.Min(e.VerticalChange, this.designerItem.ActualHeight - this.designerItem.MinHeight);
                    Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + deltaVertical * Math.Cos(-this.angle) + (this.transformOrigin.Y * deltaVertical * (1 - Math.Cos(-this.angle))));
                    Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + deltaVertical * Math.Sin(-this.angle) - (this.transformOrigin.Y * deltaVertical * Math.Sin(-this.angle)));
                    this.designerItem.Height -= deltaVertical;
                    break;
                default:
                    break;
            }

            switch (HorizontalAlignment)
            {
                case System.Windows.HorizontalAlignment.Left:
                    deltaHorizontal = Math.Min(e.HorizontalChange, this.designerItem.ActualWidth - this.designerItem.MinWidth);
                    Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) + deltaHorizontal * Math.Sin(this.angle) - this.transformOrigin.X * deltaHorizontal * Math.Sin(this.angle));
                    Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + deltaHorizontal * Math.Cos(this.angle) + (this.transformOrigin.X * deltaHorizontal * (1 - Math.Cos(this.angle))));
                    this.designerItem.Width -= deltaHorizontal;
                    break;
                case System.Windows.HorizontalAlignment.Right:
                    deltaHorizontal = Math.Min(-e.HorizontalChange, this.designerItem.ActualWidth - this.designerItem.MinWidth);
                    Canvas.SetTop(this.designerItem, Canvas.GetTop(this.designerItem) - this.transformOrigin.X * deltaHorizontal * Math.Sin(this.angle));
                    Canvas.SetLeft(this.designerItem, Canvas.GetLeft(this.designerItem) + (deltaHorizontal * this.transformOrigin.X * (1 - Math.Cos(this.angle))));
                    this.designerItem.Width -= deltaHorizontal;
                    break;
                default:
                    break;
            }
        }
    }
}
及其视觉(xaml):


就像我说的,它工作得很好,特别是当控件旋转时,组件的x和y位置完全按照预期工作,无论旋转了多少

完整源代码:

如何调整它的大小以保持纵横比,并且X和Y位置没有问题

通过多种方式尝试,在保持纵横比的同时,很容易获得新尺寸。但我不能让它正常工作,因为组件可以旋转,X和Y位置乱七八糟。我不知道如何调整和纠正新的X和Y保持比例

  • 计算垂直三角洲和水平三角洲
  • 将纵横比应用于三角洲
  • 更新designerItem的位置和大小
  • 更新:从工作解决方案重新调整Zethumb类实现。设计器项绑定到视图模型(位置、大小、角度旋转):

    //
    ///定义用于调整形状大小的拇指。
    /// 
    公共类ResizeThumb:Thumb
    {  
    /// 
    ///保存设计器项。
    /// 
    私人设计公司(DesignerItem);
    /// 
    ///保存设计器项的集合。
    /// 
    私人设计公司(DesignerItems);
    /// 
    ///保存设计器项的变换原点
    /// 
    私人点(来源);;
    /// 
    ///保持设计器项的旋转变换角度
    /// 
    私人双_角=0.0;
    /// 
    ///初始化类的新实例。
    /// 
    公众辞职
    {
    DragStarted+=ResizeThumbDragStarted;
    DragDelta+=ResizeThumbDragDelta;
    DragCompleted+=ResizeThumbDragCompleted;
    }
    /// 
    ///开始拖动拇指时处理通知。
    /// 
    ///发送方对象
    ///事件参数
    私有void ResizeThumbDragStarted(对象发送方,DragStartedEventArgs e)
    {
    _designerItem=数据上下文作为designerItem;
    如果(_designerItem==null)
    回来
    _designerItem.isResising=true;
    _designerItem.isDraging=true;
    _designerItems=\u designerItem.GetItemsControl();
    _transformOrigin=\u designerItem.renderTransferOrigin;
    var rotateTransform=\u designerItem.RenderTransform作为rotateTransform;
    if(rotateTransform!=null)
    _角度=旋转变换角度*Math.PI/180.0;
    其他的
    _角度=0.0;
    }
    /// 
    ///在拇指拖动完成时处理通知。
    /// 
    ///发送方对象
    ///事件参数
    私有void ResizeThumbDragCompleted(对象发送方,DragCompletedEventArgs e)
    {
    如果(_designerItem!=null)
    {
    _designerItem.isResising=false;
    _designerItem.isDraging=false;
    }
    }
    /// 
    ///在拖动拇指时处理通知。
    /// 
    ///发送方对象
    ///事件参数
    私有void resizetumbdragdelta(对象发送方,DragDeltaEventArgs e)
    {
    如果(_designerItem==null||
    _designerItems==null||
    !\u designerItem.IsSelected)
    {
    回来
    }
    变量项=_designerItem;
    var minLeft=double.MaxValue;
    var minTop=double.MaxValue;
    var minDeltaHorizontal=double.MaxValue;
    var mindeltical=double.MaxValue;
    minLeft=Math.Min(Canvas.GetLeft(项目),minLeft);
    minTop=Math.Min(Canvas.GetTop(item),minTop);
    minDeltaVertical=Math.Min(minDeltaVertical,item.ActualHeight-item.MinHeight);
    minDeltaHorizontal=Math.Min(minDeltaHorizontal,item.ActualWidth-item.MinWidth);
    //停止移动时
    //至少一个选定项目已锁定
    如果(项目已锁定)
    {
    回来
    }
    双精度?dragDeltaVertical=null;
    开关(垂直对齐)
    {
    外壳垂直对齐。底部:
    dragDeltaVertical=数学最小值(-e.垂直变化,minDeltaVertical);
    打破
    外壳垂直对齐。顶部:
    dragDeltaVertical=Math.Min(Math.Max(-minTop,e.VerticalChange),minDeltaVertical);
    打破
    }
    double?dragDeltaHorizontal=null;
    开关(水平对齐)
    {
    案例水平对齐。左:
    dragDeltaHorizontal=Math.Min(Math.Max(-minLeft,e.HorizontalChange),minDeltaHorizontal);
    打破
    案例水平对齐。右侧:
    dragDeltaHorizontal=数学最小值(-e.水平变化,minDeltaHorizontal);
    打破
    }
    //如果保持纵横比,则调整宽度和高度
    if(项目KeepAspectRatio)
    {
    检查AspectRatio(参考dragDeltaHorizontal、参考DragDeltahovertical、item.ActualHeight/item.ActualWidth);
    }
    if(dragDeltaVertical.HasValue)
    {
    开关(垂直对齐)
    {
    case System.Windows.VerticalAlignment.Bottom:
    SetTop(item,Canvas.GetTop(item)+(_transformOrigin.Y*dragDeltaVertical.Value*(1-Math.Cos(-_angle)));
    SetLeft(item,Canvas.GetLeft(item)-dragDeltaVertical.Value*\u transformOrigin.Y*Math.Sin(-\u angle));
    打破
    案例System.Windows.VerticalAlignment.Top:
    Canvas.SetTop(item,Canvas.GetTop(item)+dragDeltaVertical.Value*Math.Cos(-u角度)+(_transformOrigin.Y*dragDeltaVertical.Value*(1-Math.Cos(-u角度)));
    Canvas.SetLeft(项,Canvas.GetLef
    
        <Grid>
      <s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 -4 0 0"
                     VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
      <s:ResizeThumb Width="3" Cursor="SizeWE" Margin="-4 0 0 0"
                     VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
      <s:ResizeThumb Width="3" Cursor="SizeWE" Margin="0 0 -4 0"
                     VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
      <s:ResizeThumb Height="3" Cursor="SizeNS" Margin="0 0 0 -4"
                     VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
      <s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="-6 -6 0 0"
                     VerticalAlignment="Top" HorizontalAlignment="Left"/>
      <s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="0 -6 -6 0"
                     VerticalAlignment="Top" HorizontalAlignment="Right"/>
      <s:ResizeThumb Width="7" Height="7" Cursor="SizeNESW" Margin="-6 0 0 -6"
                     VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
      <s:ResizeThumb Width="7" Height="7" Cursor="SizeNWSE" Margin="0 0 -6 -6"
                     VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
            <!-- ... -->
        </Grid>
    
        /// <summary>
        /// Defines a thumb for resizing shapes.
        /// </summary>
        public class ResizeThumb : Thumb
        {  
        /// <summary>
        /// Holds a designer item.
        /// </summary>
        private DesignerItem _designerItem;
    
        /// <summary>
        /// Holds a collection of designer items.
        /// </summary>
        private DesignerItems _designerItems;
    
        /// <summary>
        /// holds a transform origin of the designer item 
        /// </summary>
        private Point _transformOrigin;
    
        /// <summary>
        /// holds an angle of the rotation transformation of the designer item
        /// </summary>
        private double _angle = 0.0;
    
        /// <summary>
        /// Initializes a new instance of the <see cref="ResizeThumb"/> class.
        /// </summary>
        public ResizeThumb()
        {
            DragStarted += ResizeThumbDragStarted;
            DragDelta += ResizeThumbDragDelta;
            DragCompleted += ResizeThumbDragCompleted;
        }
    
        /// <summary>
        /// Handles notifications when the dragging of the thumb starts.
        /// </summary>
        /// <param name="sender">the sender object</param>
        /// <param name="e">the event arguments</param>
        private void ResizeThumbDragStarted(object sender, DragStartedEventArgs e)
        {
            _designerItem = DataContext as DesignerItem;
    
            if (_designerItem == null) 
                return;
    
            _designerItem.IsResizing = true;
            _designerItem.IsDragging = true;
            _designerItems = _designerItem.GetItemsControl();
    
            _transformOrigin = _designerItem.RenderTransformOrigin;            
            var rotateTransform = _designerItem.RenderTransform as RotateTransform;
            if (rotateTransform != null)
                _angle = rotateTransform.Angle * Math.PI / 180.0;
            else
                _angle = 0.0;
        }
    
        /// <summary>
        /// Handles notifications when the dragging of the thumb completes.
        /// </summary>
        /// <param name="sender">the sender object</param>
        /// <param name="e">the event arguments</param>
        private void ResizeThumbDragCompleted(object sender, DragCompletedEventArgs e)
        {
            if (_designerItem != null)
            {
                _designerItem.IsResizing = false;
                _designerItem.IsDragging = false;
            }
        }
    
        /// <summary>
        /// Handles notifications when the thumb has been dragged.
        /// </summary>
        /// <param name="sender">the sender object</param>
        /// <param name="e">the event arguments</param>
        private void ResizeThumbDragDelta(object sender, DragDeltaEventArgs e)
        {
            if (_designerItem == null ||
                _designerItems == null ||
                !_designerItem.IsSelected)
            {
                return;
            }
    
            var item = _designerItem;
            var minLeft = double.MaxValue;
            var minTop = double.MaxValue;
            var minDeltaHorizontal = double.MaxValue;
            var minDeltaVertical = double.MaxValue;
    
            minLeft = Math.Min(Canvas.GetLeft(item), minLeft);
            minTop = Math.Min(Canvas.GetTop(item), minTop);
    
            minDeltaVertical = Math.Min(minDeltaVertical, item.ActualHeight - item.MinHeight);
            minDeltaHorizontal = Math.Min(minDeltaHorizontal, item.ActualWidth - item.MinWidth);
    
            // stop moving when
            // at least one of the selected items is locked
            if (item.IsLocked)
            {
                return;
            }
    
            double? dragDeltaVertical = null;
            switch (VerticalAlignment)
            {
                case VerticalAlignment.Bottom:
                    dragDeltaVertical = Math.Min(-e.VerticalChange, minDeltaVertical);
                    break;
                case VerticalAlignment.Top:
                    dragDeltaVertical = Math.Min(Math.Max(-minTop, e.VerticalChange), minDeltaVertical);
                    break;
            }
    
            double? dragDeltaHorizontal = null;
            switch (HorizontalAlignment)
            {
                case HorizontalAlignment.Left:
                    dragDeltaHorizontal = Math.Min(Math.Max(-minLeft, e.HorizontalChange), minDeltaHorizontal);
                    break;
                case HorizontalAlignment.Right:
                    dragDeltaHorizontal = Math.Min(-e.HorizontalChange, minDeltaHorizontal);
                    break;
            }
    
            // in case the aspect ratio is kept then adjust both width and height
            if (item.KeepAspectRatio)
            {
                CheckAspectRatio(ref dragDeltaHorizontal, ref dragDeltaVertical, item.ActualHeight / item.ActualWidth);
            }
    
            if (dragDeltaVertical.HasValue)
            {
                switch (VerticalAlignment)
                {
                    case System.Windows.VerticalAlignment.Bottom:
                        Canvas.SetTop(item, Canvas.GetTop(item) + (_transformOrigin.Y * dragDeltaVertical.Value * (1 - Math.Cos(-_angle))));
                        Canvas.SetLeft(item, Canvas.GetLeft(item) - dragDeltaVertical.Value * _transformOrigin.Y * Math.Sin(-_angle));
                        break;
                    case System.Windows.VerticalAlignment.Top:
                        Canvas.SetTop(item, Canvas.GetTop(item) + dragDeltaVertical.Value * Math.Cos(-_angle) + (_transformOrigin.Y * dragDeltaVertical.Value * (1 - Math.Cos(-_angle))));
                        Canvas.SetLeft(item, Canvas.GetLeft(item) + dragDeltaVertical.Value * Math.Sin(-_angle) - (_transformOrigin.Y * dragDeltaVertical.Value * Math.Sin(-_angle)));
                        break;
                    default:
                        break;
                }
    
                item.Height = item.ActualHeight - dragDeltaVertical.Value;
            }
    
            if (dragDeltaHorizontal.HasValue)
            {
                switch (HorizontalAlignment)
                {
                    case System.Windows.HorizontalAlignment.Left:
                        Canvas.SetTop(item, Canvas.GetTop(item) + dragDeltaHorizontal.Value * Math.Sin(_angle) - _transformOrigin.X * dragDeltaHorizontal.Value * Math.Sin(_angle));
                        Canvas.SetLeft(item, Canvas.GetLeft(item) + dragDeltaHorizontal.Value * Math.Cos(_angle) + (_transformOrigin.X * dragDeltaHorizontal.Value * (1 - Math.Cos(_angle))));
                        break;
                    case System.Windows.HorizontalAlignment.Right:
                        Canvas.SetTop(item, Canvas.GetTop(item) - _transformOrigin.X * dragDeltaHorizontal.Value * Math.Sin(_angle));
                        Canvas.SetLeft(item, Canvas.GetLeft(item) + (dragDeltaHorizontal.Value * _transformOrigin.X * (1 - Math.Cos(_angle))));
                        break;
                    default:
                        break;
                }
    
                item.Width = item.ActualWidth - dragDeltaHorizontal.Value;
            }
    
            e.Handled = true;
        }
    
        /// <summary>
        /// Checks the values so that the ratio beween them has a defined value.
        /// </summary>
        /// <param name="dragDeltaHorizontal">horizontal delta</param>
        /// <param name="dragDeltaVertical">vertical delta</param>
        /// <param name="aspectRatio">horizontal to vertical ration</param>
        private void CheckAspectRatio(ref double? dragDeltaHorizontal, ref double? dragDeltaVertical, double aspectRatio)
        {
            double? dragValue = null;
            if (dragDeltaVertical.HasValue && dragDeltaHorizontal.HasValue)
            {
                dragValue = Math.Max(dragDeltaVertical.Value, dragDeltaHorizontal.Value);
            }
            else if (dragDeltaVertical.HasValue)
            {
                dragValue = dragDeltaVertical;
            }
            else if (dragDeltaHorizontal.HasValue)
            {
                dragValue = dragDeltaHorizontal;
            }
    
            if (dragValue.HasValue)
            {
                dragDeltaVertical = dragValue.Value * aspectRatio;
                dragDeltaHorizontal = dragValue;
            }
        }
        }