很多应用需要定制化窗口,而窗口定制化不能绕过的一个问题是标题栏定制化。
基于wpf的窗口程序,一般会通过透明,去边框化的方式将原有的标题栏遮挡。
默认情况下,wpf 窗口的标题栏是这样的, 这时最化小,最大化/还原和关闭的行为都是
像正常windows程序的行为,不需要添加任何代码。
设置 WindowStyle="None" 之后,标题栏的图标,标题以及三个按钮都不见了。但是标题栏的还留
下一步部分,如下所示
需要添加在窗口属性中添加
AllowsTransparency="True" Background="Transparent" 才能隐藏这块区域。整个窗口成了透明的
可以任任意定制的区域。
通过以下代码定义我们自己想要的标题栏和客户区域
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Background="Blue" x:Name="titleBar">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentControl ContentTemplate="{StaticResource Icon_CaptionFlyoutBtnHome}" Margin="10 0 0 0"/>
<TextBlock Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Text="由你定制" Margin="10 0 0 0"/>
<Button x:Name="btnMin" Grid.Column="2" ToolTip="最小化" Width="30" Height="30" VerticalAlignment="Center" Style="{StaticResource PureImageButtonStyle}" ContentTemplate="{StaticResource Icon_minimize}"/>
<Button x:Name="btnRestore" Grid.Column="3" ToolTip="还原" Width="30" Height="30" Margin="10 0 0 0" VerticalAlignment="Center" Style="{StaticResource PureImageButtonStyle}" ContentTemplate="{StaticResource Icon_MinWnd}"/>
<Button x:Name="btnClose" Grid.Column="4" ToolTip="关闭" Width="30" Height="30" Margin="10 0 20 0" VerticalAlignment="Center" Style="{StaticResource PureImageButtonStyle}" ContentTemplate="{StaticResource Icon_close}"/>
</Grid>
<Border Grid.Row="1" Background="White">
<TextBlock VerticalAlignment="Center" Text="Add any content" HorizontalAlignment="Center"/>
</Border>
</Grid>
效果如下:
但是此时,这个标题栏除了样子,还不具标题栏该有的可拖动、最小化,最大化/还原,关闭的功能。
为这三个按钮加上事件以及整个工具栏的拖动事件。
窗口可以通过工具栏拖动了,最小化,半闭也正常,只不过这个时候发现最大化时,窗口会将系统的
状态栏挡住。
如果不考虑扩展屏,那么可以在窗口的构造函数中通过添加以下代码,限制窗口高度, 使最大化不至于
挡住系统任务栏。
MaxHeight = SystemParameters.WorkArea.Height;
但是如果有扩展屏,当程序被拖曳到扩展屏时,那么最大化依然会把护展屏的任务栏覆盖。
这时候我们需要检测程序是否在扩展屏上并作出来对应的处理。因为MaxHeight在运行过程动态改变不起效果。所以有扩展屏,即使能到扩展屏WorkArea.Height,简单重设MaxHeight并没有作用。所以最大化/还原就不能通过WindowState来实现。
这里主要通过判断当前窗口的大小与客户区大小的关系来判断窗口是否处于最大化,在非最大化的时候,保存窗口的位置与大小,以便用于恢复。关键代码如下
关于CustomizedToStateChanged的代码,全部提供在此 https://download.youkuaiyun.com/download/mochounv/16072523
其中注意一点。 Winform下面与Screen的尺寸参数是像素值,所以并不能直接将得到size赋给wpf的窗口。