using System.Windows.Input;
|
using System.Windows;
|
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls;
|
using System.Windows.Documents;
|
using System.Windows.Media;
|
using System;
|
using System.Windows.Shapes;
|
using WPFProject.Controls;
|
using System.Xml.Linq;
|
|
namespace WPFProject.Utils
|
{
|
public class Resize
|
{
|
private static readonly double MinWidth = 60;
|
private static readonly double MinHeight = 60;
|
|
public static double GetReMaxWidth(DependencyObject obj)
|
{
|
return (double)obj.GetValue(ReMaxWithProperty);
|
}
|
public static void SetReMaxWidth(DependencyObject obj, double value)
|
{
|
obj.SetValue(ReMaxWithProperty, value);
|
}
|
public static readonly DependencyProperty ReMaxWithProperty =
|
DependencyProperty.RegisterAttached("ReMaxWith", typeof(double), typeof(Resize), new PropertyMetadata(0.0));
|
|
|
// 拖拽模板
|
public static ControlTemplate GetResizeTemplate(DependencyObject obj)
|
{
|
return (ControlTemplate)obj.GetValue(ResizeTemplateProperty);
|
}
|
|
public static void SetResizeTemplate(DependencyObject obj, ControlTemplate value)
|
{
|
obj.SetValue(ResizeTemplateProperty, value);
|
}
|
|
public static readonly DependencyProperty ResizeTemplateProperty =
|
DependencyProperty.RegisterAttached("ResizeTemplate", typeof(ControlTemplate), typeof(Resize), new PropertyMetadata(null, (d, e) =>
|
{
|
FrameworkElement element = d as FrameworkElement;
|
if (element == null) return;
|
var resize = GetResizeable(element);
|
if (resize == null) return;
|
resize.Detach();
|
resize.Attach();
|
}));
|
|
// 是否可以拖拽改变大小
|
public static bool GetIsResizeable(DependencyObject obj)
|
{
|
return (bool)obj.GetValue(IsResizeableProperty);
|
}
|
public static void SetIsResizeable(DependencyObject obj, bool value)
|
{
|
obj.SetValue(IsResizeableProperty, value);
|
}
|
public static readonly DependencyProperty IsResizeableProperty =
|
DependencyProperty.RegisterAttached("IsResizeable", typeof(bool), typeof(Resize), new PropertyMetadata(false, (d, e) =>
|
{
|
FrameworkElement element = d as FrameworkElement;
|
if (element == null) return;
|
// 先取消之前的拖拽装饰
|
Resizeable resize = GetResizeable(element);
|
if (resize != null) resize.Detach();
|
// 实现逻辑
|
// 判断属性设置的是不是true
|
if (!(bool)e.NewValue)
|
{
|
SetResizeable(element, null);
|
return;
|
}
|
|
if (!element.IsLoaded)
|
{
|
RoutedEventHandler Loaded_Resize = null;
|
Loaded_Resize = (sender, e1) =>
|
{
|
Resizeable resize = new Resizeable(element);
|
resize.Attach();
|
SetResizeable(element, resize);
|
element.Loaded -= Loaded_Resize;
|
};
|
element.Loaded += Loaded_Resize;
|
}
|
else
|
{
|
resize = new Resizeable(element);
|
resize.Attach();
|
SetResizeable(element, resize);
|
}
|
}));
|
|
public static Resizeable GetResizeable(DependencyObject obj)
|
{
|
return (Resizeable)obj.GetValue(ResizeableProperty);
|
}
|
|
public static void SetResizeable(DependencyObject obj, Resizeable value)
|
{
|
obj.SetValue(ResizeableProperty, value);
|
}
|
|
// Using a DependencyProperty as the backing store for Resizeable. This enables animation, styling, binding, etc...
|
static readonly DependencyProperty ResizeableProperty =
|
DependencyProperty.RegisterAttached("Resizeable", typeof(Resizeable), typeof(Resize), new PropertyMetadata(null));
|
|
static int i = 0;
|
static SolidColorBrush[] colors = new SolidColorBrush[] {
|
new SolidColorBrush(Colors.White),
|
new SolidColorBrush(Colors.Red),
|
new SolidColorBrush(Colors.Blue),
|
new SolidColorBrush(Colors.Green),
|
new SolidColorBrush(Colors.LightBlue),
|
new SolidColorBrush(Colors.Orange),
|
new SolidColorBrush(Colors.Yellow),
|
new SolidColorBrush(Colors.Black),
|
};
|
|
public class Resizeable
|
{
|
ResizeType _resizeType;
|
enum ResizeType
|
{
|
None,
|
Grid,
|
Canvas,
|
Window,
|
Others,
|
}
|
FrameworkElement _resizeTarget;
|
|
FrameworkElement _thumbsParent = null;
|
public Resizeable(FrameworkElement resizeTarget)
|
{
|
_resizeTarget = resizeTarget;
|
}
|
|
public void Attach()
|
{
|
FrameworkElement thumbsRoot = null;
|
ControlTemplate template = GetResizeTemplate(_resizeTarget);
|
// 看不懂了,大概是拖拽模板
|
if (template != null)
|
{
|
Control control = new Control();
|
control.Template = template;
|
control.ApplyTemplate();
|
thumbsRoot = control;
|
_thumbsParent = VisualTreeHelper.GetChild(thumbsRoot, 0) as FrameworkElement;
|
}
|
|
if (thumbsRoot != null)
|
{
|
UIElement element = _resizeTarget is Window _windowTarget ? _windowTarget.Content as UIElement : _resizeTarget;
|
if (element != null)
|
{
|
if (element is InnerWindow _inner)
|
{
|
AdornerLayer layer = _inner.ResizeAdornerDecorator.AdornerLayer;
|
if (layer == null)
|
throw new Exception("获取控件装饰层失败,控件可能没有装饰层!");
|
layer.Add(new ResizeAdorner(layer, thumbsRoot));
|
}
|
else
|
{
|
AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
|
if (layer == null)
|
throw new Exception("获取控件装饰层失败,控件可能没有装饰层!");
|
layer.Add(new ResizeAdorner(element, thumbsRoot));
|
}
|
}
|
}
|
|
// 使用缺省样式
|
if (thumbsRoot == null)
|
{
|
Thumb leftThumb = null, topThumb = null, rightThumb = null, bottomThumb = null,
|
lefTopThumb = null, rightTopThumb = null, rightBottomThumb = null, leftbottomThumb = null;
|
int thumnSize = 5;
|
// 初始化thumb
|
leftThumb = new Thumb();
|
leftThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
|
leftThumb.VerticalAlignment = VerticalAlignment.Stretch;
|
leftThumb.Cursor = Cursors.SizeWE;
|
leftThumb.Width = thumnSize;
|
leftThumb.Height = double.NaN;
|
leftThumb.Margin = new Thickness(0, thumnSize, 0, thumnSize);
|
|
topThumb = new Thumb();
|
topThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
topThumb.HorizontalAlignment = HorizontalAlignment.Stretch;
|
topThumb.VerticalAlignment = VerticalAlignment.Top;
|
topThumb.Cursor = Cursors.SizeNS;
|
topThumb.Width = double.NaN;
|
topThumb.Height = thumnSize;
|
topThumb.Margin = new Thickness(thumnSize, 0, thumnSize, 0);
|
|
rightThumb = new Thumb();
|
rightThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
rightThumb.HorizontalAlignment = HorizontalAlignment.Right;
|
rightThumb.VerticalAlignment = VerticalAlignment.Stretch;
|
rightThumb.Cursor = Cursors.SizeWE;
|
rightThumb.Width = thumnSize;
|
rightThumb.Height = double.NaN;
|
rightThumb.Margin = new Thickness(0, thumnSize, 0, thumnSize);
|
|
bottomThumb = new Thumb();
|
bottomThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
bottomThumb.HorizontalAlignment = HorizontalAlignment.Stretch;
|
bottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
|
bottomThumb.Cursor = Cursors.SizeNS;
|
bottomThumb.Width = double.NaN;
|
bottomThumb.Height = thumnSize;
|
bottomThumb.Margin = new Thickness(thumnSize, 0, thumnSize, 0);
|
|
lefTopThumb = new Thumb();
|
lefTopThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
lefTopThumb.HorizontalAlignment = HorizontalAlignment.Left;
|
lefTopThumb.VerticalAlignment = VerticalAlignment.Top;
|
lefTopThumb.Cursor = Cursors.SizeNWSE;
|
lefTopThumb.Width = thumnSize;
|
lefTopThumb.Height = thumnSize;
|
|
rightTopThumb = new Thumb();
|
rightTopThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
rightTopThumb.HorizontalAlignment = HorizontalAlignment.Right;
|
rightTopThumb.VerticalAlignment = VerticalAlignment.Top;
|
rightTopThumb.Cursor = Cursors.SizeNESW;
|
rightTopThumb.Width = thumnSize;
|
rightTopThumb.Height = thumnSize;
|
|
rightBottomThumb = new Thumb();
|
rightBottomThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
rightBottomThumb.HorizontalAlignment = HorizontalAlignment.Right;
|
rightBottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
|
rightBottomThumb.Cursor = Cursors.SizeNWSE;
|
rightBottomThumb.Width = thumnSize;
|
rightBottomThumb.Height = thumnSize;
|
|
leftbottomThumb = new Thumb();
|
leftbottomThumb.Template = new ControlTemplate(typeof(Thumb))
|
{
|
VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent))
|
};
|
leftbottomThumb.HorizontalAlignment = HorizontalAlignment.Left;
|
leftbottomThumb.VerticalAlignment = VerticalAlignment.Bottom;
|
leftbottomThumb.Cursor = Cursors.SizeNESW;
|
leftbottomThumb.Width = thumnSize;
|
leftbottomThumb.Height = thumnSize;
|
|
|
Grid 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);
|
UIElement element;
|
if (_resizeTarget is Window _resizeTargetWindow)
|
{
|
element = _resizeTargetWindow.Content as UIElement;
|
}
|
else
|
{
|
element = _resizeTarget;
|
}
|
if (element != null)
|
{
|
if (element is InnerWindow _inner)
|
{
|
AdornerLayer layer = _inner.ResizeAdornerDecorator.AdornerLayer;
|
if (layer == null)
|
throw new Exception("获取控件装饰层失败,控件可能没有装饰层!");
|
layer.Add(new ResizeAdorner(layer, grid));
|
}
|
else
|
{
|
AdornerLayer layer = AdornerLayer.GetAdornerLayer(element);
|
if (layer == null)
|
throw new Exception("获取控件装饰层失败,控件可能没有装饰层!");
|
layer.Add(new ResizeAdorner(element, grid));
|
}
|
}
|
thumbsRoot = grid;
|
_thumbsParent = thumbsRoot;
|
}
|
|
//注册事件
|
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(_thumbsParent); i++)
|
{
|
Thumb thumb = VisualTreeHelper.GetChild(_thumbsParent, i) as Thumb;
|
if (thumb != null)
|
{
|
thumb.DragStarted += Thumb_DragStarted;
|
thumb.DragDelta += Thumb_DragDelta;
|
}
|
}
|
}
|
public void Detach()
|
{
|
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(_thumbsParent); i++)
|
{
|
Thumb thumb = VisualTreeHelper.GetChild(_thumbsParent, i) as Thumb;
|
if (thumb != null)
|
{
|
thumb.DragStarted -= Thumb_DragStarted;
|
thumb.DragDelta -= Thumb_DragDelta;
|
}
|
}
|
_thumbsParent = null;
|
}
|
|
private void Thumb_DragStarted(object sender, DragStartedEventArgs e)
|
{
|
_resizeType = GetResizeType();
|
if (_resizeType == ResizeType.Canvas && _resizeTarget is InnerWindow _inner)
|
{
|
Canvas parent = GetCanvas(_inner);
|
CanvasHelper.SetTopZIndex(_inner, parent, _inner.GetType());
|
}
|
}
|
|
private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
|
{
|
switch (_resizeType)
|
{
|
case ResizeType.None:
|
break;
|
case ResizeType.Grid:
|
{
|
FrameworkElement element = _resizeTarget;
|
FrameworkElement thumb = sender as FrameworkElement;
|
double left, top, right, bottom, width, height;
|
if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
|
{
|
right = element.Margin.Right;
|
left = element.Margin.Left + e.HorizontalChange;
|
width = (double.IsNaN(element.Width) ? element.ActualWidth : element.Width) - e.HorizontalChange;
|
}
|
else
|
{
|
left = element.Margin.Left;
|
right = element.Margin.Right - e.HorizontalChange;
|
width = (double.IsNaN(element.Width) ? element.ActualWidth : element.Width) + e.HorizontalChange;
|
}
|
|
if (thumb.VerticalAlignment == VerticalAlignment.Top)
|
{
|
bottom = element.Margin.Bottom;
|
top = element.Margin.Top + e.VerticalChange;
|
height = (double.IsNaN(element.Height) ? element.ActualHeight : element.Height) - e.VerticalChange;
|
}
|
else
|
{
|
top = element.Margin.Top;
|
bottom = element.Margin.Bottom - e.VerticalChange;
|
height = (double.IsNaN(element.Height) ? element.ActualHeight : element.Height) + e.VerticalChange;
|
}
|
if (thumb.HorizontalAlignment != HorizontalAlignment.Center && thumb.HorizontalAlignment != HorizontalAlignment.Stretch)
|
{
|
if (width >= 0)
|
{
|
element.Margin = new Thickness(left, element.Margin.Top, right, element.Margin.Bottom);
|
element.Width = width;
|
}
|
}
|
if (thumb.VerticalAlignment != VerticalAlignment.Center && thumb.VerticalAlignment != VerticalAlignment.Stretch)
|
{
|
if (height >= 0)
|
{
|
element.Margin = new Thickness(element.Margin.Left, top, element.Margin.Right, bottom);
|
element.Height = height;
|
}
|
}
|
}
|
break;
|
case ResizeType.Canvas:
|
{
|
FrameworkElement target = _resizeTarget;
|
Canvas parent = GetCanvas(target);
|
FrameworkElement thumb = sender as FrameworkElement;
|
if (parent == null)
|
{
|
// 一般不会出现这种情况,保险判断一下
|
return;
|
}
|
|
double left, top, width, height;
|
if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
|
{
|
left = double.IsNaN(Canvas.GetLeft(target)) ? 0 : Canvas.GetLeft(target) + e.HorizontalChange;
|
width = (double.IsNaN(target.ActualWidth) ? 0 : target.ActualWidth) - e.HorizontalChange;
|
}
|
else
|
{
|
left = Canvas.GetLeft(target);
|
width = (double.IsNaN(target.ActualWidth) ? 0 : target.ActualWidth) + e.HorizontalChange;
|
}
|
if (thumb.VerticalAlignment == VerticalAlignment.Top)
|
{
|
top = double.IsNaN(Canvas.GetTop(target)) ? 0 : Canvas.GetTop(target) + e.VerticalChange;
|
height = (double.IsNaN(target.ActualHeight) ? 0 : target.ActualHeight) - e.VerticalChange;
|
}
|
else
|
{
|
top = Canvas.GetTop(target);
|
height = (double.IsNaN(target.ActualHeight) ? 0 : target.ActualHeight) + e.VerticalChange;
|
}
|
if (thumb.HorizontalAlignment != HorizontalAlignment.Center && thumb.HorizontalAlignment != HorizontalAlignment.Stretch)
|
{
|
if (e.HorizontalChange > 0 || (width >= MinWidth && left >= 0))
|
{
|
Canvas.SetLeft(target, left);
|
target.Width = width;
|
}
|
}
|
if (thumb.VerticalAlignment != VerticalAlignment.Center && thumb.VerticalAlignment != VerticalAlignment.Stretch)
|
{
|
if (e.VerticalChange > 0 || (height >= MinHeight && top >= 0))
|
{
|
Canvas.SetTop(target, top);
|
target.Height = height;
|
}
|
}
|
}
|
break;
|
case ResizeType.Window:
|
{
|
var c = _resizeTarget as Window;
|
var thumb = sender as FrameworkElement;
|
double left, top, width, height;
|
if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
|
{
|
left = c.Left + e.HorizontalChange;
|
width = c.Width - e.HorizontalChange;
|
}
|
else
|
{
|
left = c.Left;
|
width = c.Width + e.HorizontalChange;
|
}
|
|
if (thumb.VerticalAlignment == VerticalAlignment.Top)
|
{
|
|
top = c.Top + e.VerticalChange;
|
height = c.Height - e.VerticalChange;
|
}
|
else
|
{
|
top = c.Top;
|
height = c.Height + e.VerticalChange;
|
}
|
|
if (thumb.HorizontalAlignment != HorizontalAlignment.Center && thumb.HorizontalAlignment != HorizontalAlignment.Stretch)
|
{
|
if (width > 63)
|
{
|
c.Width = width;
|
c.Left = left;
|
}
|
}
|
if (thumb.VerticalAlignment != VerticalAlignment.Center && thumb.VerticalAlignment != VerticalAlignment.Stretch)
|
{
|
if (height > 63)
|
{
|
c.Top = top;
|
c.Height = height;
|
}
|
}
|
}
|
break;
|
case ResizeType.Others:
|
|
break;
|
}
|
}
|
ResizeType GetResizeType()
|
{
|
ResizeType rt;
|
DependencyObject parent = VisualTreeHelper.GetParent(_resizeTarget);
|
if (parent is Grid)
|
{
|
rt = ResizeType.Grid;
|
}
|
else if (parent is Canvas)
|
{
|
rt = ResizeType.Canvas;
|
}
|
else if (_resizeTarget is Window)
|
{
|
rt = ResizeType.Window;
|
}
|
else
|
{
|
rt = ResizeType.Grid;
|
}
|
return rt;
|
}
|
|
// 方形工厂
|
FrameworkElementFactory GetFactory(Brush back)
|
{
|
FrameworkElementFactory fac = new FrameworkElementFactory(typeof(Rectangle));
|
fac.SetValue(Rectangle.FillProperty, back);
|
return fac;
|
}
|
|
// 装饰器
|
public class ResizeAdorner : Adorner
|
{
|
// 布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。
|
UIElement _child;
|
public ResizeAdorner(UIElement adornedElement, UIElement child) : base(adornedElement)
|
{
|
_child = child;
|
AddVisualChild(child);
|
}
|
|
protected override Visual GetVisualChild(int index)
|
{
|
return _child;
|
}
|
protected override int VisualChildrenCount { get; } = 1;
|
protected override Size ArrangeOverride(Size finalSize)
|
{
|
// 直接给grid布局,grid内部的thumb会自动布局。
|
_child.Arrange(new Rect(new Point(0, 0), finalSize));
|
return finalSize;
|
}
|
public void ttt(int index)
|
{
|
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(_child); i++)
|
{
|
DependencyObject child = VisualTreeHelper.GetChild(_child, i);
|
Canvas.SetZIndex(child as UIElement, index);
|
|
}
|
|
}
|
|
}
|
}
|
|
static Canvas GetCanvas(DependencyObject element)
|
{
|
DependencyObject e = element;
|
while (e is not null and not Canvas)
|
{
|
e = VisualTreeHelper.GetParent(e);
|
}
|
return e == null ? null : e as Canvas;
|
}
|
}
|
}
|