C# wpf 无边框窗口实现拖动调整大小

2024-08-29 05:48

本文主要是介绍C# wpf 无边框窗口实现拖动调整大小,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

WPF拖动改变大小系列

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


文章目录

  • WPF拖动改变大小系列
  • 前言
  • 一、如何实现?
    • 1.继承Adorner
    • 2.使用Thumb
    • 3.实现拖动逻辑
  • 二、完整代码
  • 三、使用示例
  • 总结


前言

在《C# wpf Grid中实现控件拖动调整大小》中我们实现了Grid中的控件动态调整大小,对于自定义的无边框窗口也可以使用类似的方式实现。虽然能查到的方案有通过Window Api的和通过WindowChrome实现的,一个是对系统有依赖还一个是依赖.net版本,这里提供一种相对轻量的实现方法。


一、如何实现?

1.继承Adorner

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

public class WindowResizeAdorner : 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 WindowResizeAdorner(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加宽
//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));
}

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


总结

以上就是今天要讲的内容,本文讲述了自定义无边框窗口实现拖动改变大小的方法,其有优点是轻量易于实现和使用,但是也有缺点,往左和往上拖动时会出现一定的界面闪烁,但总得来说,这种实现方法还是可以使用的。

这篇关于C# wpf 无边框窗口实现拖动调整大小的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117016

相关文章

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一

c# checked和unchecked关键字的使用

《c#checked和unchecked关键字的使用》C#中的checked关键字用于启用整数运算的溢出检查,可以捕获并抛出System.OverflowException异常,而unchecked... 目录在 C# 中,checked 关键字用于启用整数运算的溢出检查。默认情况下,C# 的整数运算不会自

Python xmltodict实现简化XML数据处理

《Pythonxmltodict实现简化XML数据处理》Python社区为提供了xmltodict库,它专为简化XML与Python数据结构的转换而设计,本文主要来为大家介绍一下如何使用xmltod... 目录一、引言二、XMLtodict介绍设计理念适用场景三、功能参数与属性1、parse函数2、unpa

C#实现获得某个枚举的所有名称

《C#实现获得某个枚举的所有名称》这篇文章主要为大家详细介绍了C#如何实现获得某个枚举的所有名称,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... C#中获得某个枚举的所有名称using System;using System.Collections.Generic;usi

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

C# 读写ini文件操作实现

《C#读写ini文件操作实现》本文主要介绍了C#读写ini文件操作实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录一、INI文件结构二、读取INI文件中的数据在C#应用程序中,常将INI文件作为配置文件,用于存储应用程序的

C#实现获取电脑中的端口号和硬件信息

《C#实现获取电脑中的端口号和硬件信息》这篇文章主要为大家详细介绍了C#实现获取电脑中的端口号和硬件信息的相关方法,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 我们经常在使用一个串口软件的时候,发现软件中的端口号并不是普通的COM1,而是带有硬件信息的。那么如果我们使用C#编写软件时候,如

Python使用qrcode库实现生成二维码的操作指南

《Python使用qrcode库实现生成二维码的操作指南》二维码是一种广泛使用的二维条码,因其高效的数据存储能力和易于扫描的特点,广泛应用于支付、身份验证、营销推广等领域,Pythonqrcode库是... 目录一、安装 python qrcode 库二、基本使用方法1. 生成简单二维码2. 生成带 Log