C# wpf 实现任意控件(包括窗口)更多调整大小功能

news/2024/2/29 16:53:01/文章来源:https://blog.csdn.net/u013113678/article/details/135552871

WPF拖动改变大小系列

第一节 Grid内控件拖动调整大小
第二节 Canvas内控件拖动调整大小
第三节 窗口拖动调整大小
第四节 附加属性实现拖动调整大小
第五章 拓展更多调整大小功能(本章)


文章目录

  • WPF拖动改变大小系列
  • 前言
  • 一、添加的功能
    • 1、任意控件DragResize
    • 2、边界限制
    • 3、交叉拖动
    • 4、拖动点模板
    • 5、拖动点容器模板
    • 6、整体模板
    • 7、窗口平滑拖动
    • 8、拖动事件
    • 9、其他功能
      • (1)适应MinWidth、MinHeight
      • (2)适应MaxWidth、MaxHeight
      • (3)适配任意dpi
  • 二、完整代码
  • 三、使用示例
    • 0、基础功能
      • (1)、引用命名空间
      • (2)、使用附加属性
      • (3)、窗口注意事项
    • 1、DragResize
    • 2、边界限制
    • 3、交叉拖动
    • 4、拖动点布局模板
      • (1)自定义圆点
      • (2)4个顶点
      • (3)单独定制每个点
    • 5、拖动点容器模板
      • (1)无Margin
      • (2)设置Margin
    • 6、整体模板
    • 7、窗口平滑拖动
    • 8、拖动事件
    • 9、其他功能
      • (1)适应MinWidth、MinHeight
      • (2)适应MaxWidth、MaxHeight
  • 总结


前言

上一章我们已经实现了任意控件统一的拖动调整功能,能够方便的给任意控件设置拖动调整大小。开发过程中发现还是有些功能可以继续拓展的,比如cs代码触发拖动、自定义模板、交叉拖动、限制拖动范围等功能。有功能实现起来不算太容易,却很有实用价值。


一、添加的功能

在第四章基础上添加了如下功能。

1、任意控件DragResize

我们知道wpf的Window有DragMove功能,在鼠标左键按下事件中调用此方法就能实现拖动功能很方便。对于调整大小也可以实现类似的DragResize功能, 实际效果和点击画板拖出一个形状差不多。

代码示例如下:

 /// <summary>/// 手动触发拖动改变大小,与Window.DragMove类似,只能在鼠标左键按下时调用。/// 实际效果和点击画板拖出一个形状差不多。/// 此方法为拓展方法,FrameworkElement的子类控件(即有宽高属性的控件)都可以调用此方法。/// </summary>/// <param name="elememt"></param>/// <returns>返回Task,await等待拖动完成</returns>/// <exception cref="InvalidOperationException"></exception>public static async Task DragResize(this FrameworkElement elememt){if (Mouse.LeftButton != MouseButtonState.Pressed){throw new InvalidOperationException("Left button down to call this method");}if (elememt.Parent == null && elememt is not Window){throw new InvalidOperationException("Element should be on the visual tree");}//生成Resizeable对象,第四章完整代码中。//获取右下角Thumb//手动触发Thumb拖动事件//等待拖动完成}

2、边界限制

添加一个IsResizeInBounds附加属性,表示拖动范围是否在父控件内。
代码示例如下:

public static bool GetIsResizeInBounds(DependencyObject obj)
{return (bool)obj.GetValue(IsResizeInBoundsProperty);
}public static void SetIsResizeInBounds(DependencyObject obj, bool value)
{obj.SetValue(IsResizeInBoundsProperty, value);
}/// <summary>
/// 是否在父控件范围内拖动
/// </summary>
public static readonly DependencyProperty IsResizeInBoundsProperty =DependencyProperty.RegisterAttached("IsResizeInBounds", typeof(bool), typeof(Resize), new PropertyMetadata(false));

第四章的拖动逻辑中添加相应的限制功能,本质上就是判断如果超出边界则控件刚好依附在边界上,代码如下:

 var dx = left - margin.Left;var dy = top - margin.Top;if (GetIsResizeInBounds(c)){var pos = c.GetPosition();var parent = _resizeTarget.Parent as FrameworkElement;Size size;if (parent == null){size.Width = SystemParameters.PrimaryScreenWidth;size.Height = SystemParameters.PrimaryScreenHeight;}else{size.Width = parent.ActualWidth;size.Height = parent.ActualHeight;}if (pos.X + dx < 0){left = -pos.X + margin.Left;width = pos.X + c.ActualWidth;}else if (pos.X + dx + width > size.Width){width = size.Width - pos.X;right = margin.Right + c.ActualWidth - width;}if (pos.Y + dy < 0){top = -pos.Y + margin.Top;height = pos.Y + c.ActualHeight;}else if (pos.Y + dy + height > size.Height){height = size.Height - pos.Y;bottom = margin.Bottom + c.ActualHeight - height;}}                

3、交叉拖动

交叉拖动是曾经用gdi画图时会出现的一种情况,gdi绘制的宽高可以为负数,所以可以直接穿过起点反向拖动也能绘制出图形。在wpf中的控件是不支持宽高负数的,所以我们需要用其他方式实现。
下列步骤以横向为例:
(1)判断控件边界

 if (width < 0

(2)固定到控件边界
SetTargetMargin为前3章的集合,根据不同控件类型比如Window是设置Left、Top、Grid则设置Margin等。minWidth是控件的MinWidth属性。margin参考第四张完整代码。

if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
//左拖动点
{SetTargetMargin(new Thickness(margin.Left + c.Width - minWidth, margin.Top, margin.Right - c.Width + minWidth, margin.Bottom));
}
else
//右拖动点
{SetTargetMargin(new Thickness(margin.Left - c.Width + minWidth, margin.Top, margin.Right + c.Width - minWidth, margin.Bottom));
}

(3)事件转移

//当前拖动点触发鼠标弹起事件
MouseButtonEventArgs upEvent = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left)
{ RoutedEvent = UIElement.MouseLeftButtonUpEvent };
thumb.RaiseEvent(upEvent);
//反向拖动点触发鼠标按下事件
MouseButtonEventArgs downEvent = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left)
{ RoutedEvent = UIElement.MouseLeftButtonDownEvent };
t.RaiseEvent(downEvent);

4、拖动点模板

添加附加属性ThumbsTemplate

public static ControlTemplate GetThumbsTemplate(DependencyObject obj)
{return (ControlTemplate)obj.GetValue(ThumbsTemplateProperty);
}public static void SetThumbsTemplate(DependencyObject obj, ControlTemplate value)
{obj.SetValue(ThumbsTemplateProperty, value);
}/// <summary>
/// 拖动点的模板
/// </summary>
public static readonly DependencyProperty ThumbsTemplateProperty =DependencyProperty.RegisterAttached("ThumbsTemplate", typeof(ControlTemplate), typeof(Resize), new PropertyMetadata(null));

生成拖动点时会应用模板

var thumbsTemplate = GetThumbsTemplate(_resizeTarget);
thumb.Template = thumbsTemplate;

5、拖动点容器模板

拖动点的容器模板,主要用于设置margin调整拖动点的整体位置,添加附加属性ThumbsPanel。

 public static ItemsPanelTemplate GetThumbsPanel(DependencyObject obj){return (ItemsPanelTemplate)obj.GetValue(ThumbsPanelProperty);}public static void SetThumbsPanel(DependencyObject obj, ItemsPanelTemplate value){obj.SetValue(ThumbsPanelProperty, value);}/// <summary>/// 拖动点的容器,主要用于设置margin/// </summary>public static readonly DependencyProperty ThumbsPanelProperty =DependencyProperty.RegisterAttached("ThumbsPanel", typeof(ItemsPanelTemplate), typeof(Resize), new PropertyMetadata(null));

生成拖动点布局时会应用模板

var itemsPanel = GetThumbsPanel(_resizeTarget);
_defalutPanel.ItemsPanel = itemsPanel;

6、整体模板

拖动点模板和拖动点布局模板已经很大程度灵活了使用,如果需要更高的定制性,直接使用整体模板,整体模板赋值后拖动点模板和拖动点布局模板会失效。此功能与第四章的ResizeTemplate相同但名称改为Template。基本规则是第一级控件为容器、第二级控件为Thumb类型自动识别为拖动点,拖动方向由HorizontalAlignment和VerticalAlignment决定。

7、窗口平滑拖动

之所有要对窗口拖动平滑处理是因为,自定义的调整大小只能设置Window的Left、Top、Width、Height,当窗口进行左或上拖动时右或下会出现残影,这种情况通过SetWindowPos和MoveWindow也无法改善。在不使用窗口自带的拖动功能的情况下,目前笔者研究出的方法就是使用透明窗口全屏,控件模拟窗口进行拖动。当然这种实现的限制就是一定要透明窗口,AllowTransparency为true或者WindowChrome的GlassFrameThickness为-1。

因为这种实现还不是很完美对装饰器不兼容,所以提供IsWindowDragSmooth属性,可以打开和关闭功能。

public static bool GetIsWindowDragSmooth(DependencyObject obj)
{return (bool)obj.GetValue(IsWindowDragSmoothProperty);
}public static void SetIsWindowDragSmooth(DependencyObject obj, bool value)
{obj.SetValue(IsWindowDragSmoothProperty, value);
}/// <summary>
/// 拖拽窗口调整大小是否平滑处理,作用是避免拖拽窗口左上时右下闪烁。
/// 此属性只对窗口有效
/// 此属性为true时需要透明窗口才能生效,即AllowTransparency为true或者WindowChrome的GlassFrameThickness为-1。
/// 当前版本不兼容有装饰器的窗口,拖动中装饰器可能会显示在窗口外面。
/// </summary>
// Using a DependencyProperty as the backing store for IsWindowDragSmooth.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsWindowDragSmoothProperty =DependencyProperty.RegisterAttached("IsWindowDragSmooth", typeof(bool), typeof(Resize), new PropertyMetadata(false));

8、拖动事件

提供3个拖动事件,拖动开始、拖动变化、拖动结束。
代码示例如下:

/// <summary>
///  拖动开始事件
/// </summary>
public static readonly RoutedEvent DragResizeStartedEvent = EventManager.RegisterRoutedEvent("DragResizeStarted", RoutingStrategy.Direct, typeof(EventHandler<DragResizeStartedEventArgs>), typeof(Resize));
/// <summary>
/// 拖动变化事件
/// </summary>
public static readonly RoutedEvent DragResizeDeltaEvent = EventManager.RegisterRoutedEvent("DragResizeDelta", RoutingStrategy.Direct, typeof(EventHandler<DragResizeDeltaEventArgs>), typeof(Resize));
/// <summary>
/// 拖动结束事件
/// </summary>
public static readonly RoutedEvent DragResizeCompletedEvent = EventManager.RegisterRoutedEvent("DragResizeCompleted", RoutingStrategy.Direct, typeof(EventHandler<DragResizeCompletedEventArgs>), typeof(Resize));

9、其他功能

(1)适应MinWidth、MinHeight

在第四章完整带的基础上将边界判断修改为控件的MinWidth、MinHeight即可。
横向

if (width >= minWidth/*原本是0*/)
{//略
}

纵向与横向逻辑一致,修改对应变量即可,略

(2)适应MaxWidth、MaxHeight

超过了最大值需要进行修正示例如下
横向:

if (width > c.MaxWidth)
{if (thumb.HorizontalAlignment == HorizontalAlignment.Left){left += width - c.MaxWidth;right = margin.Right;}else{left = margin.Left;right += width - c.MaxWidth;}width = c.MaxWidth;
}

纵向与横向逻辑一致,修改对应变量即可,略。

(3)适配任意dpi

所有改变坐标以及大小的代码已经适配了任意dpi。
主要注意的就是PointToScreen得到的坐标需要dpi转换。
下列是获取dpi的方法。

static Point GetDpiFromVisual(Visual visual)
{var source = PresentationSource.FromVisual(visual);var dpiX = 96.0;var dpiY = 96.0;if (source?.CompositionTarget != null){dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;}return new Point(dpiX, dpiY);
}

二、完整代码

vs2022 wpf .net 6.0 项目,包含了第四章的功能,不需要重复下载。
https://download.csdn.net/download/u013113678/88749991


三、使用示例

0、基础功能

这个是与第四章一致的基础功能。

(1)、引用命名空间

Window 的其他属性略

<Window xmlns:ac="clr-namespace:AC"/>

(2)、使用附加属性

需要某个控件可以拖动调整大小则

<Grid ac:Resize.IsResizeable="True" />

(3)、窗口注意事项

当Window需要使用此功能时

<Window ac:Resize.IsResizeable="True" />

Window的拖动点会放在子控件的装饰层,需要注意以几点:
①Window必须有子控件,子控件有装饰层(大部分控件都有装饰层比如Grid、Border、Button等)。
②子控件不可限定大小需要,跟随窗口大小变化。
③此功能与Window自带的调整大小区别是,此功能可以用于无边框窗口以及自定义拖动点。

1、DragResize

DragResize需要在鼠标左键按下事件中使用,对已存在的控件或者动态生成控件使用。此方法不需要ac:Resize.IsResizeable="True"也可以使用。
xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"WindowStyle="None"ResizeMode="NoResize"><Grid x:Name="grid" Background="SeaGreen"  MouseLeftButtonDown="Window_MouseLeftButtonDown"/>
</Window>

因为是拓展方法,所以获取到控件对象直接调用DragResize即可。
cs

using AC;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;namespace WpfResize
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private async void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){//生成控件var border = new Border();border.Background = Brushes.Azure;border.Width = 0;border.Height = 0;//加入到容器grid.Children.Add(border);//拖出控件await border.DragResize();//如果宽高为0则移除if (border.Width == 0|| border.Height == 0){grid.Children.Remove(border);}}}
}

效果预览
注:qq录制鼠标出现了偏移
在这里插入图片描述

2、边界限制

设置ac:Resize.IsResizeInBounds="True"即可。边界限制的范围是父控件。
xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"WindowStyle="None"ResizeMode="NoResize"     ><Grid x:Name="grid" Background="SeaGreen"><Border BorderThickness="1" BorderBrush="White" Margin="40"><StackPanel><Border ac:Resize.IsResizeable="True" ac:Resize.IsResizeInBounds="False" Background="White" Height="100" Width="200"  CornerRadius="10" ><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="不限制边界"></TextBlock></Border><Border ac:Resize.IsResizeable="True" ac:Resize.IsResizeInBounds="True"  Margin="0,20,0,0" Background="White" Height="100" Width="200"  CornerRadius="10" ><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="限制边界"></TextBlock></Border></StackPanel></Border></Grid>
</Window>

效果预览
注:qq录制鼠标出现了偏移
在这里插入图片描述

3、交叉拖动

通过附加属性ac:Resize.IsAllowsCrossover设置是否交叉拖动,默认为true。
xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"WindowStyle="None"ResizeMode="NoResize"     ><Grid x:Name="grid" Background="SeaGreen"><StackPanel><Border  Margin="0,20,0,0"  ac:Resize.IsResizeable="True" ac:Resize.IsAllowsCrossover="False"  Background="White" Height="100" Width="200"  CornerRadius="10" ><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="不允许交叉拖动"></TextBlock></Border><Border ac:Resize.IsResizeable="True" ac:Resize.IsAllowsCrossover="True"   Margin="0,20,0,0" Background="White" Height="100" Width="200"  CornerRadius="10" ><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="允许交叉拖动"></TextBlock></Border></StackPanel></Grid>
</Window>

效果预览
注:qq录制鼠标出现了偏移
在这里插入图片描述

4、拖动点布局模板

通过ac:Resize.ThumbsTemplate设置拖动点模板

(1)自定义圆点

xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  ><Grid x:Name="grid" Background="White"><Grid  Margin="0,20,0,0"  ac:Resize.IsResizeable="True" ac:Resize.IsAllowsCrossover="False"  Background="SeaGreen " Height="100" Width="200" ><ac:Resize.ThumbsTemplate><ControlTemplate  ><Border BorderBrush="Gray" BorderThickness="2" CornerRadius="8"  Background="White" Width="16" Height="16"/></ControlTemplate></ac:Resize.ThumbsTemplate><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="自定义拖动点模板"></TextBlock></Grid></Grid>
</Window>

效果预览
在这里插入图片描述

(2)4个顶点

xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  WindowStyle="None"ResizeMode="NoResize"><Grid x:Name="grid" Background="White"><Grid  Margin="0,20,0,0"  ac:Resize.IsResizeable="True" ac:Resize.IsAllowsCrossover="False"  Background="SeaGreen " Height="100" Width="200" ><ac:Resize.ThumbsTemplate><ControlTemplate ><Border x:Name="brd" BorderBrush="Gray" BorderThickness="2" CornerRadius="8"  Background="White" Width="16" Height="16"/><!--通过触发器隐藏4条边上的点--><ControlTemplate.Triggers><!--左右两条边上的点--><Trigger Property="HorizontalAlignment" Value="Stretch"><Setter TargetName="brd" Property="Visibility" Value="Collapsed" ></Setter></Trigger><!--上下两条边上的点--><Trigger Property="VerticalAlignment" Value="Stretch"><Setter TargetName="brd" Property="Visibility" Value="Collapsed" ></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></ac:Resize.ThumbsTemplate><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="自定义拖动点模板"></TextBlock></Grid></Grid>
</Window>

效果预览
在这里插入图片描述

(3)单独定制每个点

通过MultiTrigger触发器来区分每个点。
xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  WindowStyle="None"ResizeMode="NoResize"><Grid x:Name="grid" Background="White"><Grid  Margin="0,20,0,0"  ac:Resize.IsResizeable="True" ac:Resize.IsAllowsCrossover="False"  Background="SeaGreen" Height="100" Width="200" ><ac:Resize.ThumbsTemplate><ControlTemplate ><Border x:Name="brd" BorderBrush="Gray" BorderThickness="2" CornerRadius="8"  Background="White" Width="16" Height="16"/><ControlTemplate.Triggers><!--左上--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Left" ></Condition><Condition Property="VerticalAlignment" Value="Top" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="Aqua"></Setter></MultiTrigger><!--右上--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Right" ></Condition><Condition Property="VerticalAlignment" Value="Top" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="DarkGoldenrod"></Setter></MultiTrigger><!--右下--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Right" ></Condition><Condition Property="VerticalAlignment" Value="Bottom" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="DeepPink"></Setter></MultiTrigger><!--左下--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Left" ></Condition><Condition Property="VerticalAlignment" Value="Bottom" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="Red"></Setter></MultiTrigger><!--上--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Stretch" ></Condition><Condition Property="VerticalAlignment" Value="Top" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="Gold"></Setter></MultiTrigger><!--下--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Stretch" ></Condition><Condition Property="VerticalAlignment" Value="Bottom" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="Indigo"></Setter></MultiTrigger><!--左--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Left" ></Condition><Condition Property="VerticalAlignment" Value="Stretch" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="Blue"></Setter></MultiTrigger><!--右--><MultiTrigger><MultiTrigger.Conditions><Condition Property="HorizontalAlignment" Value="Right" ></Condition><Condition Property="VerticalAlignment" Value="Stretch" ></Condition></MultiTrigger.Conditions><Setter TargetName="brd" Property="BorderBrush" Value="Green"></Setter></MultiTrigger></ControlTemplate.Triggers></ControlTemplate></ac:Resize.ThumbsTemplate><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="自定义拖动点模板"></TextBlock></Grid></Grid>
</Window>

效果预览

在这里插入图片描述

5、拖动点容器模板

通过ac:Resize.ThumbsPanel设置拖动点容器模板,主要作用是设置margin,方便调整拖动点的偏移
默认的容器有Margin="-3"的偏移

(1)无Margin

此示例是为了说明无Margin的情况
xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  WindowStyle="None"ResizeMode="NoResize"><Grid x:Name="grid" Background="White"><Grid  Margin="0,20,0,0"  ac:Resize.IsResizeable="True" ac:Resize.IsAllowsCrossover="False"  Background="SeaGreen " Height="100" Width="200" ><ac:Resize.ThumbsTemplate><ControlTemplate ><Border x:Name="brd" BorderBrush="Gray" BorderThickness="2" CornerRadius="8"  Background="White" Width="16" Height="16"/></ControlTemplate></ac:Resize.ThumbsTemplate><ac:Resize.ThumbsPanel><ItemsPanelTemplate><Grid></Grid></ItemsPanelTemplate></ac:Resize.ThumbsPanel><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="自定义拖点容器模板"></TextBlock></Grid></Grid>
</Window>

效果预览
在这里插入图片描述

(2)设置Margin

Margin设置为拖动点的一半大小就刚好在边线中间。
xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  WindowStyle="None"ResizeMode="NoResize"><Grid x:Name="grid" Background="White"><Grid  Margin="0,20,0,0"  ac:Resize.IsResizeable="True" ac:Resize.IsAllowsCrossover="False"  Background="SeaGreen " Height="100" Width="200" ><ac:Resize.ThumbsTemplate><ControlTemplate ><Border x:Name="brd" BorderBrush="Gray" BorderThickness="2" CornerRadius="8"  Background="White" Width="16" Height="16"/></ControlTemplate></ac:Resize.ThumbsTemplate><ac:Resize.ThumbsPanel><ItemsPanelTemplate><Grid Margin="-8"></Grid></ItemsPanelTemplate></ac:Resize.ThumbsPanel><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="自定义拖点容器模板"></TextBlock></Grid></Grid>
</Window>

效果预览
在这里插入图片描述

6、整体模板

设置整体模板Template后会覆盖拖动点模板和拖动点布局模板。规则是第一级控件为容器、第二级控件为Thumb类型自动识别为拖动点,拖动方向由HorizontalAlignment和VerticalAlignment决定, 即可以有任意个拖动点Thumb,也可以放任意其他控件。

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  WindowStyle="None"ResizeMode="NoResize"><Grid x:Name="grid" Background="White"><Grid  Margin="0,20,0,0"  ac:Resize.IsResizeable="True"   Background="SeaGreen " Height="100" Width="200" ><ac:Resize.Template><ControlTemplate ><Grid  Margin="-4"><Grid.Resources><Style TargetType="Thumb"><Setter Property="Width" Value="8"></Setter><Setter Property="Height" Value="8"></Setter><Setter Property="Template"><Setter.Value><ControlTemplate><Border  Background="Aqua"></Border></ControlTemplate></Setter.Value></Setter></Style></Grid.Resources><Border BorderBrush="Aqua"  BorderThickness="2" Margin="4"></Border><!--左--><Thumb   HorizontalAlignment="Left"  Cursor="SizeWE"/><!--上--><Thumb   VerticalAlignment="Top" Cursor="SizeNS"/><!--右--><Thumb   HorizontalAlignment="Right"  Cursor="SizeWE"/><!--下--><Thumb    VerticalAlignment="Bottom" Cursor="SizeNS"/><!--左上--><Thumb    HorizontalAlignment="Left" VerticalAlignment="Top" Cursor="SizeNWSE"/><!--右上--><Thumb    HorizontalAlignment="Right" VerticalAlignment="Top"  Cursor="SizeNESW"/><!--右下--><Thumb    HorizontalAlignment="Right" VerticalAlignment="Bottom"  Cursor="SizeNWSE"/><!--左下--><Thumb    HorizontalAlignment="Left" VerticalAlignment="Bottom" Cursor="SizeNESW"/></Grid></ControlTemplate></ac:Resize.Template><TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" Text="自定义整体模板"></TextBlock></Grid></Grid>
</Window>

效果预览
在这里插入图片描述

7、窗口平滑拖动

窗口为透明窗口(AllowTransparency为true或者WindowChrome的GlassFrameThickness为-1),附加属性 ac:Resize.IsWindowDragSmooth设置为true即可以实现平滑拖动。
注:当前版本和装饰器不兼容,拖动时装饰器可能显示在窗口外面,谨慎使用此属性

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  WindowStyle="None"ResizeMode="NoResize"AllowsTransparency="True"ac:Resize.IsResizeable="True"ac:Resize.IsWindowDragSmooth="True"><Grid Background="SeaGreen "/>
</Window>

作为对比先展示非平滑拖动
注:qq录制鼠标出现了偏移
在这里插入图片描述

设置平滑拖动效果预览
注:qq录制鼠标出现了偏移
在这里插入图片描述

8、拖动事件

3个事件,拖动开始ac:Resize.DragResizeStarted、拖动变化ac:Resize.DragResizeDelta、拖动结束ac:Resize.DragResizeCompleted
xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  ><Grid Background="SeaGreen "><Border Background="Aqua" Width="200" Height="200"   ac:Resize.IsResizeable="True"  ac:Resize.DragResizeStarted="Border_DragResizeStarted"  ac:Resize.DragResizeCompleted="Border_DragResizeCompleted" ac:Resize.DragResizeDelta="Border_DragResizeDelta"></Border></Grid>
</Window>

cs

using AC;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;namespace WpfResize
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private void Border_DragResizeStarted(object sender, DragResizeStartedEventArgs e){Console.WriteLine("开始拖动");}private void Border_DragResizeCompleted(object sender, DragResizeCompletedEventArgs e){Console.WriteLine("结束拖动");}private void Border_DragResizeDelta(object sender, DragResizeDeltaEventArgs e){Console.WriteLine("横向变化:"+e.HorizontalChange+ " 纵向变化:"+e.VerticalChange+ " 宽变化:" + e.WidthChange + " 高变化:" + e.HeightChange);}}
}

效果预览
注:qq录制鼠标出现了偏移在这里插入图片描述

9、其他功能

(1)适应MinWidth、MinHeight

xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  ><Grid Background="SeaGreen "><Border Background="Aqua" MinWidth="100" MinHeight="100" Width="200" Height="200"   ac:Resize.IsResizeable="True"  ></Border></Grid>
</Window>

效果预览
注:qq录制鼠标出现了偏移
在这里插入图片描述

(2)适应MaxWidth、MaxHeight

xaml

<Window x:Class="WpfResize.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfResize"xmlns:ac="clr-namespace:AC"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"  ><Grid Background="SeaGreen "><Border Background="Aqua" MaxWidth="200" MaxHeight="200" Width="100" Height="100"   ac:Resize.IsResizeable="True"  ></Border></Grid>
</Window>

效果预览
在这里插入图片描述


总结

以上就是今天要讲的内容,拓展后的功能更加全面以及兼容性更强了,比如DragRezie就可以用于画板,边界限制也是比较实用的功能,拖动点模板简化了自定义的难度,拖动事件可以用于实现撤销重做功能,窗口平滑拖动优化了使用体验。但是还是有些功能不够完,需要后期继续优化。总的来说,本文实现的拖动调整大小模块已经变得更加方便实用,后期还会继续完善优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_925526.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot参数校验

介绍 在开发现代应用程序时&#xff0c;数据验证是确保用户输入的正确性和应用程序数据完整性的关键方面。Spring Boot 提供了强大的数据验证机制&#xff0c;使开发者能够轻松地执行验证操作。本文将深入介绍 Spring Boot 中的 Validation&#xff0c;以及如何在应用程序中正…

网络文件共享服务

目录 一、网络文件共享服务原理内容 1.存储类型 2.应用场景 3.总结 二、FTP——文件传输协议 1.工作原理介绍 2.vsftpd软件 2.1使用ftp 2.2延伸——FileZilla 2.3修改默认端口号 2.4主动模式端口 2.5被动模式端口 2.6匿名用户登录 2.7匿名用户上传 2.8匿名用户…

5文件操作

包含头文件<fstream> 操作文件三大类&#xff1a; ofstream : 写文件ifstream &#xff1a;读文件fstream : 读写文件 5.1文本文件 -文件以ascii的形式存储在计算机中 5.1.1写文件 步骤&#xff1a; 包含头文件 #include "fstream"创建流对象 ofs…

Open CASCADE学习|参数化球面的奇异性

参数曲面的奇异性是一个相对复杂的概念&#xff0c;它涉及到参数曲面的几何特性和参数化过程中的一些特殊情况。参数曲面通常用于描述三维空间中的复杂形状&#xff0c;通过参数方程将二维参数域映射到三维空间中。然而&#xff0c;在某些情况下&#xff0c;参数曲面可能会表现…

ssm基于vue的儿童教育网站的设计与实现论文

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;视频信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足广大…

react 项目结构配置

1 项目整体目录结构的搭建 如下图&#xff1a; 2 重置css样式: normalize.css reset.less ; 第一步 安装 npm i normalize.css 入口文件index.tsx导入&#xff1a;import ‘noremalize.css’ 第二步 创建自己的css样式&#xff1a;在assets文件夹中创建css…

Go 知多少?

作为一名已接触过其他语言的开发&#xff0c;再去学习一门新语言可比之前轻松不少&#xff0c; 语言之间存在很多相似点&#xff0c;但是新语言也有自己的不同点&#xff0c;通常我会先了解它与其他语言常遇到的不同点有哪些&#xff0c; 使自己先能够上手编写基础程序&#…

深入理解 Spark(一)spark 运行模式简介与启动流程源码分析

spark 的运行模式 standalone 模式 以 standalone-client 为例&#xff0c;运行过程如下&#xff1a; SparkContext 连接到 Master&#xff0c;向 Master 注册并申请资源&#xff08;CPU Core 和 Memory&#xff09;&#xff1b;Master 根据 SparkContext 的资源申请要求和 …

ruoyi后台管理系统部署-4-安装nginx

yum 安装 ngix 1.24 yum 官方源安装&#xff1a; # 1. 需要预先安装 yum-utils sudo yum install yum-utils # 2. 配置yum repo touch /etc/yum.repos.d/nginx.repongix.repo: [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/$releasever/$…

ETF交易好不好?如何选择一个好的ETF基金?

作为普通投资者&#xff0c;交易ETF基金时&#xff0c;拥有证券账户即可&#xff0c;如同买卖股票一样操作&#xff0c;非常便捷&#xff0c;可以在盘中实时买卖。和投资股票相比较&#xff0c;风险相对较低。 首先&#xff0c;什么是ETF基金? ETF其实是一个缩写&#xff1a…

41k+ stars 闪电般快速的开源搜索引擎 docker安装教程

目录 1.下载 2.启动 成功示例 3.创建索引 4.插入数据 4.1下载数据 4.2插入数据 4.3查看数据 5.官方地址 1.下载 docker pull getmeili/meilisearch:latest 2.启动 mkdir -p /opt/meili_datadocker run -it --rm \-p 7700:7700 \-v /opt/meili_data:/meili_data \ge…

AI绘画学起来真的那么难吗?附全网最全教程!!

手把手教你入门绘图超强的AI绘画&#xff0c;用户只需要输入一段图片的文字描述&#xff0c;即可生成精美的绘画。给大家带来了全新保姆级教程资料包 &#xff08;文末可获取&#xff09; 随着2022年末ChatGPT的爆火&#xff0c;人们终于不能再忽视AI的强大了&#xff0c;AI绘…

Android studio RecyclerView 应用设计

一、创建empty activity项目: 二、打开activity_main.xml布局文件: 添加RecyclerView控件 <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/…

浅谈对Maven的理解

一、什么是Maven Maven——是Java社区事实标准的项目管理工具&#xff0c;能帮你从琐碎的手工劳动中解脱出来&#xff0c;帮你规范整个组织的构建系统。不仅如此&#xff0c;它还有依赖管理、自动生成项目站点等特性&#xff0c;已经有无数的开源项目使用它来构建项目并促进团队…

【LabVIEW FPGA 编程入门】使用FPGA IO进行编程

1.在项目中新建一个VI&#xff0c;命名为FPGA IO Test。 2. 可以直接将项目中的FPGA IO拖入程序框图中。 FPGA IO的类型&#xff1a; 数字线&#xff1a; 数字端口&#xff1a; 模拟IO&#xff1a; 其他&#xff1a; 3.如果新增加了FPGA资源&#xff0c;不是创建项目时扫描到的…

C++算法学习心得五.二叉树(3)

1.合并二叉树&#xff08;617题&#xff09; 题目要求&#xff1a; 给定两个二叉树&#xff0c;想象当你将它们中的一个覆盖到另一个上时&#xff0c;两个二叉树的一些节点便会重叠。 你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠&#xff0c;那么将他们…

用Python做一个2048小游戏

文章目录 逻辑设计绘图逻辑主循环 逻辑设计 2048的逻辑无非是操作 4 4 4\times4 44的方格&#xff0c;每个方格中有一个数&#xff0c;这些数可以移动&#xff0c;如果两个相同的数字在移动时相撞了&#xff0c;就可以彼此合并。 而这个 4 4 4\times4 44的方格&#xff0c;…

Jenkins自动化部署docker

Jenkins自动化部署docker和普通方式构建 docker外挂目录 准备测试服务器docker环境准备jdk环境将上传jar包修改为app.jar对外暴露1000端口启动jar FROM openjdk:8-jdk-alpine ARG JAR_FILE COPY ${JAR_FILE} app.jar EXPOSE 1000 ENTRYPOINT ["java","-jar&q…

搭建知识付费小程序平台:如何避免被坑,选择最佳方案?

随着知识经济的兴起&#xff0c;知识付费已经成为一种趋势。越来越多的人开始将自己的知识和技能进行变现&#xff0c;而知识付费小程序平台则成为了一个重要的渠道。然而&#xff0c;市面上的知识付费小程序平台琳琅满目&#xff0c;其中不乏一些不良平台&#xff0c;让老实人…

(学习日记)2024.01.09

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…