C#wpfGrid中实现控件拖动调整大小的示例代码

 

前言

在《C# wpf Canvas中实现控件动态调整大小》中我们实现了Canvas中的控件动态调整大小,由于Grid也是可层叠布局,在Grid中也是可以实现动态调整大小的。

 

一、功能说明

8个点方放置在控件的8个方位上,通过拖动这些点对控件进行拉伸或缩小,示意图如下:

在这里插入图片描述

 

二、如何实现?

1.继承Adorner

通过装饰器的方式添加8个点在控件上,这样既可以不影响控件布局,又可以自由摆放8点控件。通过重写方法,给装饰添加控件。必要的重写的方法如下面示例所示:

public class GridAdorner : Adorner
{
//获取装饰器的元素个数
protected override Visual GetVisualChild(int index);
//指定装饰器子元素个数
protected override int VisualChildrenCount{get;}
//布局,添加的子元素需要手动布局。
protected override Size ArrangeOverride(Size finalSize);      
}

2.使用Thumb

因为Thumb实现拖动比较容易,有相关事件获取拖动距离。在装饰器中定义8个Thumb,对应8个方位点。
示例代码如下:

//4条边
Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
//4个角
Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;

初始化

 public GridAdorner(UIElement adornedElement) : base(adornedElement)
{
   //初始化thumb
   _leftThumb = new Thumb();
   _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
   _leftThumb.VerticalAlignment = VerticalAlignment.Center;
   _leftThumb.Cursor = Cursors.SizeWE;
   //其他略...
}

3.实现拖动逻辑

在Thumb的DragDelta事件可以获取拖动距离,根据八个方位的不同计算并修改控件的大小。

private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
//1.右侧点HorizontalChange加宽,右边距减HorizontalChange
//2.左侧点HorizontalChange减宽,左边距加HorizontalChange
//3.下侧点VerticalChange加高,下边距减VerticalChange
//4.上侧点VerticalChange减高,上边距加VerticalChange
}

 

三、完整代码

代码如下:

 public class GridAdorner : Adorner
  {
      //4条边
      Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
      //4个角
      Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;
      //布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。
      Grid _grid;
      UIElement _adornedElement;
      public GridAdorner(UIElement adornedElement) : base(adornedElement)
      {
          _adornedElement = adornedElement;
          //初始化thumb
          _leftThumb = new Thumb();
          _leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
          _leftThumb.VerticalAlignment = VerticalAlignment.Center;
          _leftThumb.Cursor = Cursors.SizeWE;
          _topThumb = new Thumb();
          _topThumb.HorizontalAlignment = HorizontalAlignment.Center;
          _topThumb.VerticalAlignment = VerticalAlignment.Top;
          _topThumb.Cursor = Cursors.SizeNS;
          _rightThumb = new Thumb();
          _rightThumb.HorizontalAlignment = HorizontalAlignment.Right;
          _rightThumb.VerticalAlignment = VerticalAlignment.Center;
          _rightThumb.Cursor = Cursors.SizeWE;
          _bottomThumb = new Thumb();
          _bottomThumb.HorizontalAlignment = HorizontalAlignment.Center;
          _bottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
          _bottomThumb.Cursor = Cursors.SizeNS;
          _lefTopThumb = new Thumb();
          _lefTopThumb.HorizontalAlignment = HorizontalAlignment.Left;
          _lefTopThumb.VerticalAlignment = VerticalAlignment.Top;
          _lefTopThumb.Cursor = Cursors.SizeNWSE;
          _rightTopThumb = new Thumb();
          _rightTopThumb.HorizontalAlignment = HorizontalAlignment.Right;
          _rightTopThumb.VerticalAlignment = VerticalAlignment.Top;
          _rightTopThumb.Cursor = Cursors.SizeNESW;
          _rightBottomThumb = new Thumb();
          _rightBottomThumb.HorizontalAlignment = HorizontalAlignment.Right;
          _rightBottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
          _rightBottomThumb.Cursor = Cursors.SizeNWSE;
          _leftbottomThumb = new Thumb();
          _leftbottomThumb.HorizontalAlignment = HorizontalAlignment.Left;
          _leftbottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
          _leftbottomThumb.Cursor = Cursors.SizeNESW;
          _grid = new Grid();
          _grid.Children.Add(_leftThumb);
          _grid.Children.Add(_topThumb);
          _grid.Children.Add(_rightThumb);
          _grid.Children.Add(_bottomThumb);
          _grid.Children.Add(_lefTopThumb);
          _grid.Children.Add(_rightTopThumb);
          _grid.Children.Add(_rightBottomThumb);
          _grid.Children.Add(_leftbottomThumb);
          AddVisualChild(_grid);
          foreach (Thumb thumb in _grid.Children)
          {
              thumb.Width = 16;
              thumb.Height = 16;
              thumb.Background = Brushes.Green;
              thumb.Template = new ControlTemplate(typeof(Thumb))
              {
                  VisualTree = GetFactory(new SolidColorBrush(Colors.White))
              };
              thumb.DragDelta += Thumb_DragDelta;
          }
      }
      protected override Visual GetVisualChild(int index)
      {
          return _grid;
      }
      protected override int VisualChildrenCount
      {
          get
          {
              return 1;
          }
      }
      protected override Size ArrangeOverride(Size finalSize)
      {
          //直接给grid布局,grid内部的thumb会自动布局。
          _grid.Arrange(new Rect(new Point(-_leftThumb.Width / 2, -_leftThumb.Height / 2), new Size(finalSize.Width + _leftThumb.Width, finalSize.Height + _leftThumb.Height)));
          return finalSize;
      }
      //拖动逻辑
      private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
      {
          var c = _adornedElement as FrameworkElement;
          var thumb = sender as FrameworkElement;
          double left, top, right, bottom, width, height;
          if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
          {
              right = c.Margin.Right;
              left = c.Margin.Left + e.HorizontalChange;
              width =(double.IsNaN(c.Width)?c.ActualWidth:c.Width)- e.HorizontalChange;
          }
          else
          {
              left = c.Margin.Left;
              right = c.Margin.Right - e.HorizontalChange;
              width = (double.IsNaN(c.Width) ? c.ActualWidth : c.Width )+ e.HorizontalChange;
          }

          if (thumb.VerticalAlignment == VerticalAlignment.Top)
          {
              bottom = c.Margin.Bottom;
              top = c.Margin.Top + e.VerticalChange;
              height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height) - e.VerticalChange;

          }
          else
          {
              top = c.Margin.Top;
              bottom = c.Margin.Bottom - e.VerticalChange;
              height = (double.IsNaN(c.Height) ? c.ActualHeight : c.Height )+ e.VerticalChange;
          }
          if (thumb.HorizontalAlignment != HorizontalAlignment.Center)
          {
              if (width >= 0)
              {
                  c.Margin = new Thickness(left, c.Margin.Top, right, c.Margin.Bottom);
                  c.Width = width;
              }
          }
          if (thumb.VerticalAlignment != VerticalAlignment.Center)
          {
              if (height >= 0)
              {
                  c.Margin = new Thickness(c.Margin.Left, top, c.Margin.Right, bottom);
                  c.Height = height;
              }
          }
      }
      //thumb的样式
      FrameworkElementFactory GetFactory(Brush back)
      {
          var fef = new FrameworkElementFactory(typeof(Ellipse));
          fef.SetValue(Ellipse.FillProperty, back);
          fef.SetValue(Ellipse.StrokeProperty, new SolidColorBrush((Color)ColorConverter.ConvertFromString("#999999")));
          fef.SetValue(Ellipse.StrokeThicknessProperty, (double)2);
          return fef;
      }
  }

 

四、使用示例

示例代码如下:

xml

<Grid>
  <Border  x:Name="border"  Width="200" Height="200"  Background="Gray" ></Border>
</Grid>

在窗口或控件的Loaded事件中添加装饰器:
cs

private void window_Loaded(object sender, RoutedEventArgs e)
{
  var layer = AdornerLayer.GetAdornerLayer(border);
  layer.Add(new GridAdorner(border));
}

效果预览:

在这里插入图片描述

 

总结

以上就是今天要讲的内容,本文讲述了Grid中控件缩放的方法与实现,与Canvas的实现大部分是相同的,唯一的区别就是设置Margin,总得来说还是比较容易实现的,最终呈现的效果也是比较不错的。

关于C# wpf Grid中实现控件拖动调整大小的示例代码的文章就介绍至此,更多相关C# wpf Grid拖动调整大小内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 前言上一章我们实现了截屏界面与功能,接下来可以在此基础上实现录屏功能,录屏采用ffmpeg命令行实现会方便一些,效果也是不错的,当然前提是要对Windows子进程的控制比较熟悉 ...