第一步:基本实现
- 添加Window的Style定义,并设置WindowChrome.WindowChrome属性;
- 设置WindowChrome标题栏:
- CaptionHeight——主要用于拖动有效区;
- GlassFrameThickness——影响标题栏系统按钮显示,0表示不使用系统按钮【后面介绍】,-1表示用的系统默认值,如下示例则表示标题栏高度30;
- 自定义窗体Title
-
<Style x:Key="WindowStyle1" TargetType="{x:Type Window}"> <Setter Property="WindowChrome.WindowChrome"> <Setter.Value> <WindowChrome CaptionHeight="30" GlassFrameThickness="0,30,0,0"/> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Window}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" > <AdornerDecorator > <Grid> <Grid.RowDefinitions> <RowDefinition Height="30"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <ContentPresenter Grid.Row="1"/> <TextBlock Text="{TemplateBinding Title}" HorizontalAlignment="Left" VerticalAlignment="Center" /> </Grid> </AdornerDecorator> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
第二步:优化边界处理
- 方法1:模板添加最大化触发器,设置最大化时,内部布局Margin设为8
- 方法2:模板添加最大化触发器,设置最大化时,限制布局最大化的宽高最大值
<ControlTemplate TargetType="{x:Type Window}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" > <AdornerDecorator > <Grid Name="win_content"> <Grid.RowDefinitions> <RowDefinition Height="30" x:Name="row_title"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <ContentPresenter Grid.Row="1"/> <TextBlock Text="{TemplateBinding Title}" HorizontalAlignment="Left" VerticalAlignment="Center" /> </Grid> </AdornerDecorator> </Border> <ControlTemplate.Triggers> <Trigger Property="WindowState" Value="Maximized"> <Setter Property="Margin" TargetName="win_content" Value="8"/> <!--二选一--> <Setter Property="MaxWidth" TargetName="win_content" Value="{Binding Source={x:Static SystemParameters.WorkArea},Path=Width}" /> <Setter Property="MaxHeight" TargetName="win_content" Value="{Binding Source={x:Static SystemParameters.WorkArea},Path=Height}"/> <Setter Property="Height" TargetName="row_title" Value="22" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate>
第三步:完全自定义标题栏【即,不使用系统的操作按钮】
- 初步操作类似第一步,其中将
GlassFrameThickness
设置为0
- 在内容定义部分添加自定义的标题栏,添加操作按钮,并设置按钮属性
WindowChrome.IsHitTestVisibleInChrome="True"
- 如果不设置
WindowChrome.IsHitTestVisibleInChrome
,则由于我们之前设置CaptionHeight
,则这个区域内,按钮将失效。 - 但是,也不能将整个标题栏布局设置这个属性,那样会完全覆盖系统标题栏的操作,如拖动效果,即
CaptionHeight
设置的那个区域。<!--样式定义--> <Style x:Key="WindowStyle2" TargetType="{x:Type Window}"> <Setter Property="WindowChrome.WindowChrome"> <Setter.Value> <WindowChrome UseAeroCaptionButtons="False" GlassFrameThickness="0" CaptionHeight="30" /> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Window}"> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" > <AdornerDecorator > <ContentPresenter x:Name="win_content" /> </AdornerDecorator> </Border> <ControlTemplate.Triggers> <Trigger Property="WindowState" Value="Maximized"> <Setter Property="Margin" TargetName="win_content" Value="8"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
<!--定义标题栏--> <Grid Background="Red" > <Grid Height="30" HorizontalAlignment="Stretch" VerticalAlignment="Top" Background="Blue"> <StackPanel Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True" HorizontalAlignment="Right" > <Button Name="btn_Min" Content="—" ></Button> <Button Name="btn_Max" Content="☐" ></Button> <Button Name="btn_Close" Content="✕" ></Button> </StackPanel> </Grid> </Grid>
//标题栏按钮功能实现 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.btn_Min.Click += Btn_Min_Click; this.btn_Max.Click += Btn_Max_Click; this.btn_Close.Click += Btn_Close_Click; } private void Btn_Close_Click(object sender, RoutedEventArgs e) { this.Close(); } private void Btn_Max_Click(object sender, RoutedEventArgs e) { this.WindowState = WindowState.Maximized == this.WindowState ? WindowState.Normal : WindowState.Maximized; } private void Btn_Min_Click(object sender, RoutedEventArgs e) { this.WindowState = WindowState.Minimized; } }