赞
踩
第一节 Grid内控件拖动调整大小
第二节 Canvas内控件拖动调整大小
第三节 窗口拖动调整大小(本章)
第四节 附加属性实现拖动调整大小
第五章 拓展更多调整大小功能
在《C# wpf Grid中实现控件拖动调整大小》中我们实现了Grid中的控件动态调整大小,对于自定义的无边框窗口也可以使用类似的方式实现。虽然能查到的方案有通过Window Api的和通过WindowChrome实现的,一个是对系统有依赖还一个是依赖.net版本,这里提供一种相对轻量的实现方法。
通过装饰器的方式添加8个方位拖动区域在窗口上,这样既可以不影响控件布局,又可以自由摆放8个拖动控件。通过重写方法,给装饰添加控件。必要的重写的方法如下面示例所示:
public class WindowResizeAdorner : Adorner
{
//获取装饰器的元素个数
protected override Visual GetVisualChild(int index);
//指定装饰器子元素个数
protected override int VisualChildrenCount{get;}
//布局,添加的子元素需要手动布局。
protected override Size ArrangeOverride(Size finalSize);
}
因为Thumb实现拖动比较容易,有相关事件获取拖动距离。在装饰器中定义8个Thumb,对应8个方位点。
示例代码如下:
//4条边
Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb;
//4个角
Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb;
初始化
public WindowResizeAdorner(UIElement adornedElement) : base(adornedElement)
{
//初始化thumb
_leftThumb = new Thumb();
_leftThumb.HorizontalAlignment = HorizontalAlignment.Left;
_leftThumb.VerticalAlignment = VerticalAlignment.Center;
_leftThumb.Cursor = Cursors.SizeWE;
//其他略...
}
在Thumb的DragDelta事件可以获取拖动距离,根据八个方位的不同计算并修改控件的大小。
private void Thumb_DragDelta(object sender, DragDeltaEventArgs e)
{
//1.右侧点HorizontalChange加宽
//2.左侧点HorizontalChange减宽,HorizontalChange加左移
//3.下侧点VerticalChange加高
//4.上侧点VerticalChange减高,VerticalChange加上移
}
代码如下:
public class WindowResizeAdorner : Adorner { //4条边 Thumb _leftThumb, _topThumb, _rightThumb, _bottomThumb; //4个角 Thumb _lefTopThumb, _rightTopThumb, _rightBottomThumb, _leftbottomThumb; //布局容器,如果不使用布局容器,则需要给上述8个控件布局,实现和Grid布局定位是一样的,会比较繁琐且意义不大。 Grid _grid; UIElement _adornedElement; Window _window; public WindowResizeAdorner(UIElement adornedElement) : base(adornedElement) { _adornedElement = adornedElement; _window = Window.GetWindow(_adornedElement); //初始化thumb _leftThumb = new Thumb(); _leftThumb.HorizontalAlignment = HorizontalAlignment.Left; _leftThumb.VerticalAlignment = VerticalAlignment.Stretch; _leftThumb.Cursor = Cursors.SizeWE; _topThumb = new Thumb(); _topThumb.HorizontalAlignment = HorizontalAlignment.Stretch; _topThumb.VerticalAlignment = VerticalAlignment.Top; _topThumb.Cursor = Cursors.SizeNS; _rightThumb = new Thumb(); _rightThumb.HorizontalAlignment = HorizontalAlignment.Right; _rightThumb.VerticalAlignment = VerticalAlignment.Stretch; _rightThumb.Cursor = Cursors.SizeWE; _bottomThumb = new Thumb(); _bottomThumb.HorizontalAlignment = HorizontalAlignment.Stretch; _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) { int thumnSize = 10; if (thumb.HorizontalAlignment == HorizontalAlignment.Stretch) { thumb.Width = double.NaN; thumb.Margin = new Thickness(thumnSize, 0, thumnSize, 0); } else { thumb.Width = thumnSize; } if (thumb.VerticalAlignment == VerticalAlignment.Stretch) { thumb.Height = double.NaN; thumb.Margin = new Thickness(0, thumnSize, 0, thumnSize); } else { thumb.Height = thumnSize; } thumb.Background = Brushes.Green; thumb.Template = new ControlTemplate(typeof(Thumb)) { VisualTree = GetFactory(new SolidColorBrush(Colors.Transparent)) }; 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(-(_window.RenderSize.Width - finalSize.Width) / 2, -(_window.RenderSize.Height - finalSize.Height) / 2), _window.RenderSize)); return finalSize; } //拖动逻辑 private void Thumb_DragDelta(object sender, DragDeltaEventArgs e) { var c = _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.HorizontalAlignment != HorizontalAlignment.Stretch) { if (width > 63) { c.Left = left; c.Width = width; } } 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.VerticalAlignment != VerticalAlignment.Stretch) { if (height > 63) { c.Top = top; c.Height = height; } } } //thumb的样式 FrameworkElementFactory GetFactory(Brush back) { var fef = new FrameworkElementFactory(typeof(Rectangle)); fef.SetValue(Rectangle.FillProperty, back); return fef; } }
示例代码如下:
<Window x:Class="WpfControlMove.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:WpfControlMove" mc:Ignorable="d" Title="MainWindow" Height="360" Width="640" Loaded="Window_Loaded" WindowStyle="None" ResizeMode="NoResize" Background="Transparent" AllowsTransparency="True" > <Border Margin="10" Background="White"> <Border.Effect> <DropShadowEffect Color="#FFAAAAAA" ShadowDepth="0" BlurRadius="10" Opacity="0.4"/> </Border.Effect> </Border> </Window>
在窗口或控件的Loaded事件中添加装饰器:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//将装饰器添加到窗口的Content控件上
var c = this.Content as UIElement;
var layer = AdornerLayer.GetAdornerLayer(c);
layer.Add(new WindowResizeAdorner(c));
}
效果预览:
以上就是今天要讲的内容,本文讲述了自定义无边框窗口实现拖动改变大小的方法,其有优点是轻量易于实现和使用,但是也有缺点,往左和往上拖动时会出现一定的界面闪烁,但总得来说,这种实现方法还是可以使用的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。