WPF中的Window类

控件分类

在第一篇文章.Net Core和WPF介绍中的WPF的功能和特性部分根据功能性介绍了WPF的控件 名称。

在接下来的文章中,将会详细的介绍各个控件的概念及使用。

主要包括:

内容控件:Label、Button、CheckBox、ToggleButton、RadioButton、ToolTip和ScrollViewer

带有标题的内容控件:TabItem、GroupBox、Expander

导航控件:Frame、TabControl、Page

窗体控件:Window

文本控件:TextBox、PasswordBox、RichTextBox

列表控件:ListBox和ComboBox

基于范围的控件:Slider和ProgressBar

日期控件:Calender和DatePicker

媒体控件:Image和MediaElement

Window类

Window类继承自ContentControl类,也是内容控件的一种。在上一篇文章中,已经介绍过内容控件。

Window类比较特殊,它跟常规的内容控件不一样。除了额外的属性之外,它还是程序最顶级的元素。可以理解为Window类是WPF程序的最大的容器。所有的控件都是放置在Window类下。

在后面的文章中,会介绍到Application类。每个运行的程序,都由System.Windows.Application类的一个实例来表示。

Application类有一个Run函数,需要传入一个Window对象(或者通过StartupUri属性指定窗体,再调用无参Run函数)。通过调用Run函数,来启动整个WPF应用程序,并打开指定窗体。

常用属性

|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 属性 | 说明 |
| Width | 指定Window宽度 |
| Height | 指定Window高度 |
| WindowStyle | 使用WindowStyle枚举值, 设置窗体的边框类型。SingleBorderWindow(默认值)、 None(无边框,只显示内容区域,标题栏和边框都不显示)、 ToolWindow(固定工具窗口)、 ThreeDBorderWindow(具有三维边框的窗口) |
| AllowTransparency | 是否允许透明标志,默认false。 当设置为true,且背景被设置为透明色,整个窗体就会透明。 如果背景设置为透明色,AllowTransparency=false,就会显示黑色背景。 注意:AllowTransparency=true需要和WindowStyle=None配合使用,否则会报错。 这是因为边框不支持透明,只有无边框时,使用AllowTransparency=true才能生效。 |
| Icon | 指定窗口图标 |
| Left和Top | 使用设备无关像素设置窗口左上角到屏幕左部边缘及顶部之间的距离        |
| ResizeMode | 获取或设置调整大小模式,使用ResizeMode枚举值。 CanMinimize 只能最小化和还原窗口。 同时显示"最小化"和"最大化"按钮,但只有"最小化"按钮处于启用状态。 CanResize 可以调整窗口的大小。 同时显示"最小化"和"最大化"按钮,并且两个按钮均处于启用状态。 CanResizeWithGrip 可以调整窗口的大小。 同时显示"最小化"和"最大化"按钮,并且两个按钮均处于启用状态。 窗口的右下角显示一个大小调整手柄。 NoResize 无法调整窗口的大小。 标题栏中不显示"最小化"和"最大化"按钮。 |
| RestoreBounds | 获取窗体在最小化或最大化前的位置和大小 |
| ShowInTaskbar | 运行后是否显示在任务栏,默认是true。 |
| SizeToContent | 获取或设置一个值,该值指示窗口是否自动调整自身大小以适应其内容大小,使用SizeToContent枚举值。 Height 指定窗口将自动设置其高度以适合其内容的高度,而非宽度 Manual 指定窗口将如何自动设置其大小以适合其内容大小。 此外,窗口大小还可以由其他属性确定, 其中包括 Width、Height、MaxWidth、MaxHeight、MinWidth 和 MinHeight Width 指定窗口将自动设置其宽度以适合其内容的宽度,而非高度 WidthAndHeight 指定窗口将自动设置其宽度和高度以适合其内容的宽度和高度 |
| IsActive | 获取一个值,该值指示窗口是否为活动窗口。 |
| Owner | 获取或设置当前窗口的拥有者。 |
| ShowActivated | 获取或设置一个值,该值指示在第一次显示窗口时,窗口是否处于激活状态。 |
| TaskbarItemInfo | 获取或设置任务栏缩略图。在后面的文章中会详细介绍该功能 |
| Title | 获取或设置窗口的标题。 |
| TopMost | 获取或设置一个值,该值指示窗口是否出现在 Z 顺序的最顶层。 当设置该属性为true时,窗口显示在应用程序其它窗口的上面。即最顶层 |
| WindowsStartupLocation | 获取或设置窗口首次显示时的位置。使用WindowsStartupLocation枚举值。 CenterOwner Window 的启动位置位于包含它的 Window 的中央,由 Owner 属性指定。 CenterScreen Window 的启动位置位于包含鼠标光标的屏幕的中央。 Manual 可从代码中设置 Window 的启动位置,或者使用默认的 Windows 位置。 |
| WindowState | 获取或设置一个值,该值指示窗口是处于还原、最小化还是最大化状态。 使用WindowState枚举值 Maximized 最大化窗口 Minimized 最小化窗口 Normal 还原窗口 |
| DialogResult | 获取或设置对话框结果值,此值是从 ShowDialog() 方法返回的值。 |

窗口组成

WPF窗口由两个不同的区域组成:

  • 非工作区,用于托管窗口装饰,包括图标、标题、系统菜单、最小化按钮、最大化按钮、还原按钮、关闭按钮和边框。

  • 一个工作区,用于托管特定于应用程序的内容。

下图显示了一个标准窗口:

显示窗口

显示窗口主要是调用Window类的Show ()函数和ShowDialog()函数。

在程序启动时,WPF内部调用了MainWindow的Show函数。

当我们需要显示新的窗口时,可以有以下两种做法

1、使用Visual Studio 添加一个窗口

在XAML中对窗口进行布局

复制代码
 1 <Window x:Class="WindowDemo.XAMLWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WindowDemo"
 7         mc:Ignorable="d"
 8         Title="XAMLWindow" Height="450" Width="800">
 9     <Grid>
10         
11     </Grid>
12 </Window>

显示窗体

复制代码
1 XAMLWindow xAMLWindow = new XAMLWindow();
2 xAMLWindow.ShowDialog();

复制代码
1 XAMLWindow xAMLWindow = new XAMLWindow();
2 xAMLWindow.Show();

2、直接使用代码创建窗口并显示

复制代码
 1 Window window = new Window();
 2 window.Width = 720;
 3 window.Height = 500;
 4 window.Background = Brushes.LightSkyBlue;
 5 window.Title = "Window 1";
 6 
 7 Grid grid = new Grid();
 8 
 9 Label label = new Label();
10 label.HorizontalAlignment = HorizontalAlignment.Center;
11 label.VerticalAlignment = VerticalAlignment.Center;
12 label.Content = "Hello World";
13 label.FontSize = 30;
14 grid.Children.Add(label);
15 
16 window.Content = grid;
17 
18 window.ShowDialog();

Show()和ShowDialog的区别

Show():显示非模态窗口,非模态窗口不会阻止用户访问其它任何窗口。调用Show()函数,函数会立即返回。

ShowDialog():显示模态窗口(Modal),模态窗口会通过一种类似强制置顶的模式,锁住所有鼠标和键盘输入来阻止用户访问父窗口,直到模态窗口被关闭。在关闭模态窗口前,ShowDialog()函数也不会返回,这也就意味着后面的代码会被阻塞。

说明:

ShowDialog()函数会返回一个bool?值,代表Dialog的活动是被接受 (true) 还是被取消 (false)。 返回值是 DialogResult 属性在窗口关闭前具有的值。

像我们平常在调用各种对话框时,都会通过返回值来判断是否执行成功,如文件打开对话框

复制代码
1 OpenFileDialog openFileDialog = new OpenFileDialog();
2 
3 if(openFileDialog.ShowDialog() == true)
4 {
5     //操作选中的文件
6 }

我们在自己设计一个对话框时,可以通过DialogResult属性来设置对话框的返回值,不管设置哪个值,对话框都会立即关闭并返回。

我们可以创建一个简单的窗口来试验一下

界面XAML

复制代码
1  <Grid>
2      <Button Content="DialogResult = true" HorizontalAlignment="Center" VerticalAlignment="Top" IsDefault="True" Click="Button_Click"></Button>
3      <Button Content="DialogResult = false" HorizontalAlignment="Center" VerticalAlignment="Bottom" IsCancel="True" Click="Button_Click_1"></Button>
4  </Grid>

后台代码

复制代码
1  private void Button_Click(object sender, RoutedEventArgs e)
2  {
3      this.DialogResult = true;
4  }
5 
6  private void Button_Click_1(object sender, RoutedEventArgs e)
7  {
8      this.DialogResult = false;
9  }

运行效果

关闭窗口

使用Close()函数可以关闭窗口。

如果我们只是想隐藏窗口,可以调用Hide()函数或设置Visibility属性为Hidden。不管使用哪种方式隐蔽窗口,代码依然会在后台执行。

有时候我们想在用户单击关闭按钮后,隐藏窗口,而不关闭窗口,可以在窗口的Closing事件中添加如下代码:

复制代码
1   private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
2   {
3       e.Cancel = true;
4       //隐藏窗口、最小化窗口、创建托盘图标或其它操作
5   }

像平常使用的微信软件就是在关闭后执行隐藏操作,而不是真正的退出。

窗口启动位置

可以通过设置Window.WindowStartupLocation属性指定第一次打开窗口时所要显示到的位置。

它的取值是WindowStartupLocation枚举类型,定义如下:

复制代码
1 public enum WindowStartupLocation
2 {
3     Manual,                 //手动设置第一次启动位置
4     CenterScreen,           //屏幕中央
5     CenterOwner             //拥有者窗口中央
6 }

Manual

窗口第一次启动时,显示在用户指定的位置。

当设置为Manual时,可以通过Window.Left属性和Window.Top属性来设置具体的启动位置。

Window.Left:窗口左边缘相对于桌面的位置

Window.Top:窗口上边缘相对于桌面的位置

如设置Left为80,Top为100,则启动位置如下图所示:

CenterScreen

窗口第一次启动时,显示在屏幕中央位置。

注意:这是第一次启动时的位置,在启动后,仍然可以通过Window.Left和Window.Top属性来修改窗口的位置

CenterOwner

窗口第一次启动时,显示在拥有者窗口的中央。

当设置为CenterOwner时,需要指定窗口的拥有者窗口

如下所示:

复制代码
1 XAMLWindow xAMLWindow = new XAMLWindow();
2 //设置XAMLWindow的拥有者为当前窗口
3 xAMLWindow.Owner = this; 
4 //XAMLWindow的启动位置设置为当前窗口的中央
5 xAMLWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner; 
6 xAMLWindow.Show();

定位窗口

通过Width和Height属性,可以指定窗口的宽度和高度。

通过Left和Top属性,可以控制窗口距离屏幕边缘的位置。

有时候我们需要控制窗口的尺寸和位置,例如当窗口的大小会超过当前屏幕的分辨率的时候。

WPF提供了一个System.Window.SystemParamters类,SystemParamters类里面定义了大量的静态属性,可以用来快速查询系统设置,如屏幕大小、鼠标参数、键盘参数等。

如果我们想获取不带任务栏的屏幕大小,可以通过下面的方式

复制代码
1 var width = SystemParameters.FullPrimaryScreenWidth;
2 var height = SystemParameters.FullPrimaryScreenHeight;

如果我们想获取整个屏幕(主屏幕)的大小,可以通过下面的方式

复制代码
1 var width = SystemParameters.PrimaryScreenWidth;
2 var height = SystemParameters.PrimaryScreenHeight;

如果有多个显示器,想获取副屏(其它屏幕)的大小,可以通过下面的方式

复制代码
1   //多个屏幕时
2   System.Windows.Forms.Screen[] allScreen = System.Windows.Forms.Screen.AllScreens;
3 
4   //屏幕1的工作区域
5   var firstScreenWorkingArea = allScreen[0].WorkingArea;
6   var width = firstScreenWorkingArea.Width;
7   var height = firstScreenWorkingArea.Height;

说明:

如果我们在窗口显示之后再去设置窗口的大小或位置,视觉效果上会看到窗口的改变。

窗口位置

针对窗口位置,可以在调用Show ()或者ShowDialog()函数之前设置。

窗口大小

如果窗口的大小是已知且固定的,可以在调用Show()或者ShowDialog()函数之前设置。

如果窗口的大小是动态的,可以在窗口的Loaded事件处理函数中设置。

保存/还原窗口位置和大小

有时候我们需要记录窗口关闭前的位置和大小,以便下次启动时,恢复窗口原来的大小及位置。

我们可以在关闭时,将窗口的Left、Top、Width和Height属性值记录下来,保存到配置文件中。

在启动时,读取配置文件,将窗口恢复到原来的大小和位置。

在日常开发中,需要保存的参数可能远不止窗口位置和大小,如字体大小,界面参数等等,我们都可以用这种方式实现。

WPF提供了一套默认的应用程序设置,可以很方便的保存/读取设置。

说明:

这种方式是保存在资源文件中,无法通过记事本等文本编辑器直接编辑,正式项目推荐使用以XML/Json外部文件的形式保存。

使用默认应用程序设置的方法

1、打开项目的属性页,切换到设置选项卡

2、点击创建或打开应用程序设置,在这里我们可以添加不同类型的设置项。

添加一个System.Drawing.Size类型的值,用于记录窗口大小;

添加一个System.Drawing.Point类型的值,用于记录窗口的位置。

如下所示

3、在代码中使用设置项

关闭时

复制代码
1 //使用RestoreBounds属性获取窗口在最小化或最大化之前的大小和位置
2 var restoreBounds = this.RestoreBounds;
3 
4 Properties.Settings.Default.WindowPos = new System.Drawing.Point() { X = (int)restoreBounds.X, Y = (int)restoreBounds.Y };
5 Properties.Settings.Default.WindowSize = new System.Drawing.Size() { Width = (int)restoreBounds.Width, Height = (int)restoreBounds.Height };
6 
7 //保存
8 Properties.Settings.Default.Save();

启动时

复制代码
1 var winSize = Properties.Settings.Default.WindowSize;
2 var winPos = Properties.Settings.Default.WindowPos;
3 if (winSize.Width != 0 && winSize.Height != 0)
4 {
5     this.Left = winPos.X;
6     this.Top = winPos.Y;
7     this.Width = winSize.Width;
8     this.Height = winSize.Height;
9 }

运行效果

窗口的图标

通过Icon属性可以指定窗口的图标,它可以是来自外部文件、嵌入的资源,也可以是自己绘制的图像。

1、嵌入的资源

复制代码
1 1 <Window ...
2 2         Icon="logo.jpg">
3 3 </Window>

2、外部文件

复制代码
1 1 <Window ...
2 2         Icon="D:\logo.jpg">
3 3 </Window>

3、绘制的图像

复制代码
1 <Window.Icon>
2     <DrawingImage>
3         <DrawingImage.Drawing>
4              ...
5         </DrawingImage.Drawing>
6     </DrawingImage>
7 </Window.Icon>

窗口的边框样式

可以通过Window.WindowStyle 属性设置窗口的边框样式,它是一个WindowStyle枚举类型,定义如下:

复制代码
1 public enum WindowStyle
2 {  
3     None,                         //无
4     SingleBorderWindow,           //单边框(默认值)
5     ThreeDBorderWindow,           //3-d 边框
6     ToolWindow                    //固定的工具窗口
7  }

各样式的显示效果如下:

说明:

1、当设置窗口允许透明,即AllowTransparency=true 时,WindowStyle 要设置为None,因为边框不支持透明,否则会报错。

2、Windows 10/11 22H2之前的版本可以通过Win32 API 函数SetWindowCompositionAttribute()设置带边框的窗口支持毛玻璃透明效果。如下所示

3、在后面创建不规则窗口时,也需要设置为WindowStyleNone

调整大小模式

可以通过ResizeMode属性,来设置窗口的调整大小模式。它是一个ResizeMode枚举类型,定义如下:

复制代码
1 public enum ResizeMode
2 {
3     NoResize,         //不能调整大小,“最小化”和“最大化”按钮不会显示在标题栏
4     CanMinimize,      //窗口只能最小化/恢复。同时显示“最小化”和“最大化”按钮,但仅启用“最小化”按钮。
5     CanResize,        //可以调整大小,并显示“最小化”和“最大化”按钮(默认值)
6     CanResizeWithGrip //可以调整窗口的大小。最小化和最大化按钮同时显示和启用。窗口的右下角将显示一个调整大小的夹点。
7 }

各模式的效果如下:

窗口状态

可以通过Window.WindowState属性设置窗口状态当前的状态。它是一个WindowState枚举类型,定义如下:

复制代码
1 public enum WindowState
2 {  
3     Normal,                  //正常显示(默认)
4     Minimized,               //最小化
5     Maximized                //最大化
6 }

例如我们想手动设置窗口最小化,可以使用下面的代码

复制代码
1   this.WindowState = WindowState.Minimized;

说明:

1、在最小化或最大化窗口之前,其大小和位置存储在RestoreBounds中。 在随后还原窗口时,其大小和位置值使用RestoreBounds中的值进行还原。

2、更改 WindowState 属性时, Window.StateChanged 事件将被触发 。

创建非矩形的窗口

传统的应用程序基本都是矩形的窗口,对于现在的应用程序开发来说,不再拘泥于传统的窗口展现形式。

例如像桌面美化软件upupoo就采用了圆角矩形的安装包

小鸟壁纸采用了圆形的安装界面

下面介绍如何在WPF中实现非矩形的窗口。

1、设置Window.AllowTransparency属性为true

2、设置Window.WindowStyle属性为None

3、背窗口背景颜色设置为透明,即Window.Background=Transparent

此时我们已经得到了一个全透明的窗口,往窗口上增加不透明的具有所需形状的内容,窗口就会显示为该形状的效果。

这里我们可以添加但不仅限于以下内容:

1、使用支持透明格式的文件提供背景插图,如使用PNG,效果如下图所示。需要注意的是,因为在具有更高DPI的窗口中呈现时需要使用更多的像素,背景图片可能会变得模糊,当允许用户更改窗口大小时,也会出现这一问题。

XAML

复制代码
 1 <Window x:Class="WindowDemo.PngWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WindowDemo"
 7         mc:Ignorable="d"
 8         Title="PngWindow" Height="450" Width="800" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
 9     <Grid>
10         <Grid.Background>
11             <ImageBrush ImageSource="dd.png" Stretch="Uniform"></ImageBrush>
12         </Grid.Background>
13 
14         <Button Content="关闭" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click"></Button>
15     </Grid>
16 </Window>

2、使用形状绘制功能创建具有矢量内容的背景,不管是窗口尺寸改变,还是系统DPI改变,矢量内容都不会失真。

XAML

复制代码
 1 <Window x:Class="WindowDemo.PathWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WindowDemo"
 7         mc:Ignorable="d"
 8         Title="PathWindow" Height="450" Width="800" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
 9     <Grid>
10         <Canvas UseLayoutRounding="False" Width="180" Height="180">
11             <Canvas.Clip>
12                 <RectangleGeometry Rect="0.0,0.0,169.39037,161.76305"/>
13             </Canvas.Clip>
14             <Path Fill="#ff000000">
15                 <Path.Data>
16                     <PathGeometry Figures="m 163.915 56.9601 l -50.78 -7.38 l -22.7 -46.02 c -0.62 -1.26 -1.64 -2.28 -2.9 -2.9 c -3.16 -1.56 -7 -0.26 -8.58 2.9 l -22.7 46.02 l -50.78 7.38 c -1.4 0.2 -2.68 0.86 -3.66 1.86 c -2.46 2.54 -2.42 6.58 0.12 9.06 l 36.74 35.82 l -8.68 50.58 c -0.24 1.38 -0.02 2.82 0.64 4.06 c 1.64 3.12 5.52 4.34 8.64 2.68 l 45.42 -23.88 l 45.42 23.88 c 1.24 0.66 2.68 0.88 4.06 0.64 c 3.48 -0.6 5.82 -3.9 5.22 -7.38 l -8.68 -50.58 l 36.74 -35.82 c 1 -0.98 1.66 -2.26 1.86 -3.66 c 0.54 -3.5 -1.9 -6.74 -5.4 -7.26 z m -48.66 41.7 l 7.22 42.06 l -37.78 -19.84 l -37.78 19.86 l 7.22 -42.06 l -30.56 -29.8 l 42.24 -6.14 l 18.88 -38.26 l 18.88 38.26 l 42.24 6.14 z" FillRule="Nonzero"/>
17                 </Path.Data>
18             </Path>
19         </Canvas>
20         <Button Content="关闭" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click"></Button>
21     </Grid>
22 </Window>

3、使用更简单的具有所有形状的WPF元素,如使用Border可以创建出具有圆角的窗口,使用Ellipse可以创建椭圆窗口。

XAML

复制代码
 1 <Window x:Class="WindowDemo.IrregularElementWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WindowDemo"
 7         mc:Ignorable="d"
 8         Title="IrregularElementWindow" Height="450" Width="800" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
 9     <Grid>
10         <Border Width="200" Height="400" BorderThickness="3" BorderBrush="Green" CornerRadius="20">
11             <Border.Effect>
12                 <DropShadowEffect></DropShadowEffect>
13             </Border.Effect>
14         </Border>
15 
16         <Button Content="关闭" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click"></Button>
17     </Grid>
18 </Window>

如何移动不规则的窗口

不规则窗口不再具有标题栏,所以无法拖动窗口,幸运的是,系统封装了一个函数可以启动拖动模式。调用Window.DragMove()函数可以对窗口进行拖动

XAML

复制代码
1  <Grid Height="30" Background="LightBlue" VerticalAlignment="Top" Margin="0,35" Width="160" MouseDown="Grid_MouseDown">
2      <Label Content="点击我可以拖动窗口"></Label>
3  </Grid>

XAML.cs

复制代码
1         private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
2         {
3             if(e.LeftButton == MouseButtonState.Pressed)
4                 this.DragMove();
5         }

如何改变非矩形窗口的尺寸

对于非矩形的窗口,如果窗口的形状大体上还是矩形,或者窗口的内容基本是铺满整个窗口的,我们可以设置Window.ResizeMode为CanResizeWithGrip值为窗口添加一个用于改变窗口大小的手柄。如下所示:

但这种方式并不理想,最好的办法还是捕获鼠标,根据鼠标移动来动态计算窗口的大小。

原理如下:

1、放置一个热点区域,当鼠标进入时,变成可拖动状态。

2、鼠标按下时,捕获鼠标,根据鼠标拖动的大小调整窗口大小

3、鼠标松开时,释放鼠标。

具体实现方法如下:

1、放置一个Rectange/Border元素,设置背景为Transparent,宽度为5个单位,并显示在内容区域右边。

复制代码
 1 <Window ... Height="450" Width="205" WindowStyle="None" AllowsTransparency="True" Background="Transparent">
 2     <Grid>
 3         <Rectangle Width="5" Height="400" HorizontalAlignment="Right" Fill="Transparent" Cursor="SizeWE"></Rectangle>
 4         <Border Name="content" Margin="0,0,5,0" Height="400" BorderThickness="3" BorderBrush="Green" CornerRadius="20" Background="White">
 5             <Border.Effect>
 6                 <DropShadowEffect></DropShadowEffect>
 7             </Border.Effect>
 8         </Border>
 9     </Grid>
10 </Window>

说明:这里只添加了右侧调整大小的手柄,依次添加其它方向即可。

2、为Rectangle/Border添加鼠标按下/松开和移动的事件处理

复制代码
1 <Rectangle 
2  ... MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" MouseLeftButtonUp="Rectangle_MouseLeftButtonUp" MouseMove="Rectangle_MouseMove" />

3、事件处理逻辑如下:

复制代码
 1 private bool isPressed = false;
 2 
 3 public IrregularElementWindowWithResize()
 4 {
 5     InitializeComponent();
 6 }
 7 
 8 private void Rectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 9 {
10     isPressed = true;
11 }
12 
13 private void Rectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
14 {
15     isPressed = false;
16     var rect = sender as Rectangle;
17     rect.ReleaseMouseCapture();  
18 }
19 
20 private void Rectangle_MouseMove(object sender, MouseEventArgs e)
21 {
22     if (isPressed)
23     {
24         Rectangle rect = sender as Rectangle;
25         rect.CaptureMouse();
26         var currentPos = e.GetPosition(this.content);
27         double newWidth = currentPos.X + 5;
28         if(newWidth > 0)
29         {
30             this.Width = newWidth + 5; 
31         }
32     }
33 }

实现效果如下:

其它常用属性

窗口置顶(TopMost)

通过Window.TopMost属性可以设置为窗口是否置顶,当设置TopMost为True时,窗口会置顶显示,不会被其它窗口盖住,即使焦点不在当前窗口。

显示在任务栏(ShowInTaskbar)

通过Window.ShowInTaskBar属性可以设置为窗口是否显示在任务栏,当设置ShowInTaskbar为False时,当前窗口不会显示在任务栏。

根据内容自动调整窗口大小(SizeToContent)

通过Window.SizeToContent属性可以指示窗口是否自动调整自身大小以适应其内容大小。当设置为True时,窗口大小会根据窗口内容自动调整

首次显示是否激活(ShowActivated)

通过Window.ShowActivated属性可以指示在第一次显示窗口时,窗口是否处于激活状态。当设置为False时,窗口在第一次显示时不会激活。

示例代码

https://github.com/zhaotianff/DotNetCoreWPF/tree/master/七、WPF中的常用控件(二)

参考资料

Window Class (System.Windows) | Microsoft Learn

相关推荐
麻花20132 小时前
C#之WPF的C1FlexGrid空间的行加载事件和列事件变更处理动态加载的枚举值
开发语言·c#·wpf
lcintj3 小时前
【WPF】Prism学习(九)
学习·wpf·prism
界面开发小八哥3 小时前
界面控件DevExpress WPF中文教程:网格视图数据布局的列和卡片字段
wpf·界面控件·devexpress·ui开发·用户界面
△曉風殘月〆3 小时前
如何在WPF中嵌入其它程序
wpf
Crazy Struggle3 小时前
功能齐全的 WPF 自定义控件资源库(收藏版)
.net·wpf·ui控件库
shepherd枸杞泡茶17 小时前
WPF动画
c#·.net·wpf
lcintj17 小时前
【WPF】Prism学习(十)
学习·wpf·prism
wyh要好好学习17 小时前
WPF数据加载时添加进度条
ui·wpf
code_shenbing17 小时前
跨平台WPF框架Avalonia教程 三
前端·microsoft·ui·c#·wpf·跨平台·界面设计
lcintj2 天前
【WPF】Prism学习(八)
学习·wpf·prism