在开发Windows应用程序时,经常需要自定义窗口的外观,以满足特定的设计需求。然而,当将窗口的样式(WindowStyle)设置为"None"以创建一个带有自定义边框的窗口时,会发现失去了标准的Windows功能。本文将介绍如何使用WPFShell Integration Library来解决这些问题,并在此基础上添加标题栏按钮(最小化、最大化/还原、关闭)以及一个窗口图标控件,该控件在单击时显示系统菜单,在双击时关闭窗口。
WPFShell Integration Library提供了一种简单的方式来恢复以下功能,这些功能在将WindowStyle设置为"None"时会丢失:
但是,它对于以下附加功能的帮助不大:
在尝试创建一个具有完全功能的自定义边框窗口时,找不到类似于标准Windows最小化/最大化/关闭按钮的现有按钮代码,并且希望将这种功能方便地整合到未来的项目中,因此创建了这个新的库,并将其命名为"WPF Custom Chrome Library"。
标准边框是熟悉的Windows 7样式:
<Window x:Class="CustomChromeSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomChromeSample"
Title="Window 1 - Standard Chrome"
Height="350" Width="525">
当将WindowStyle设置为"None"时,会失去标题栏和标题栏按钮,但仍然有调整大小的边框:
<Window x:Class="CustomChromeSample.Window3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomChromeSample"
WindowStyle="None"
ResizeMode="NoResize"
Title="Window 3 - No Chrome"
Height="350" Width="525">
现在有了追求的基本自定义外观,但失去了像标题栏按钮、拖动、双击最大化以及系统菜单这样的标准窗口功能。
WPFShell Integration Library恢复了基本功能。以下是Window声明以及来自Shell Integration Library的WindowChrome的XAML:
<Window x:Class="CustomChromeSample.Window4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"
xmlns:ccl="clr-namespace:CustomChromeLibrary;assembly=CustomChromeLibrary"
xmlns:local="clr-namespace:CustomChromeSample"
Title="Custom Chrome Sample"
Height="350" Width="525">
<shell:WindowChrome.WindowChrome>
<shell:WindowChrome ResizeBorderThickness="6" CaptionHeight="43" CornerRadius="25,25,10,10" GlassFrameThickness="0">
</shell:WindowChrome>
</shell:WindowChrome.WindowChrome>
</Window>
WindowChrome类恢复了设置WindowStyle为"None"时丢失的基本窗口功能。这个类的完整功能以及如何自定义它需要单独一篇文章来介绍。需要注意的一些要点:
请注意,通常这些WindowChrome设置没有任何视觉效果;它们只控制行为(例外是GlassFrameThickness,如果设置为非零值,将导致显示窗口玻璃)。需要将WindowChrome设置与自定义边框窗口的视觉尺寸相匹配。
另外,当WindowChrome类应用于窗口时,它会自动设置WindowStyle="None"和ResizeMode="NoResize",所以不需要这样做。
完成自定义边框窗口的最后步骤是:
首先展示窗口及其XAML,然后解释底层代码和支持库。
<ccl:CustomChromeWindow x:Class="CustomChromeSample.Window5"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"
xmlns:ccl="clr-namespace:CustomChromeLibrary;assembly=CustomChromeLibrary"
xmlns:local="clr-namespace:CustomChromeSample"
Title="Custom Chrome Sample"
Height="350" Width="525">
<shell:WindowChrome.WindowChrome>
<shell:WindowChrome ResizeBorderThickness="6" CaptionHeight="43" CornerRadius="25,25,10,10" GlassFrameThickness="0">
</shell:WindowChrome>
</shell:WindowChrome.WindowChrome>
<Window.Resources>
<ResourceDictionary>
<local:CaptionButtonRectToMarginConverter x:Key="CaptionButtonMarginConverter" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/GlassButton.xaml" />
<ResourceDictionary Source="Resources/GlassIcon.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- 提供整个表单的背景。在实践中,这看起来像是窗口的调整大小边框,因为标题和窗口内容遮挡了其余部分 -->
<Border CornerRadius="10,10,5,5" Grid.RowSpan="2" BorderThickness="3" BorderBrush="LightSteelBlue">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#99bbbbff" Offset="0" />
<GradientStop Color="#ff7777bb" Offset="1" />
</LinearGradientBrush>
</Border.Background>
</Border>
<!-- 标题栏 -->
<Border CornerRadius="10,10,0,0" BorderThickness="3,3,3,1" BorderBrush="LightSteelBlue" Margin="{Binding Path=CaptionButtonMargin}">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#ffbbbbff" Offset="0" />
<GradientStop Color="#ff7777bb" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<StackPanel Orientation="Horizontal" Margin="0" VerticalAlignment="Top">
<ccl:WindowIcon Width="35" Height="35" Background="#ff0000bb" Margin="7,3,5,5" Style="{StaticResource GlassIcon}" />
<TextBlock Text="Window 5 - Caption Buttons" FontFamily="Calibri" FontWeight="Bold" FontSize="26" Foreground="#FF000044" VerticalAlignment="Center" />
</StackPanel>
</Border>
<!-- 最小化/最大化/关闭按钮 -->
<ccl:CaptionButtons/>
<!-- 内容 -->
<Grid Grid.Row="1">
<TextBlock Grid.Row="1" Margin="10" FontFamily="Verdana" FontSize="14">
Complete custom chrome with caption buttons.
</TextBlock>
</Grid>
</Grid>
</ccl:CustomChromeWindow>