Windows 为每个窗口提供一个默认标题栏,并支持对其进行自定义以匹配应用的个性。 默认标题栏附带了一些标准组件和核心功能,例如拖动窗口和调整窗口大小。
有关自定义应用标题栏、可接受的标题栏区域内容和推荐的 UI 模式的指导,请参阅标题栏设计一文。
注释
本文介绍如何为使用 UWP 和 WinUI 2 的应用自定义标题栏。 有关使用 Windows 应用 SDK 和 WinUI 3 的应用,请参阅 Windows 应用 SDK 的 标题栏自定义 。
如果你正在考虑将 UWP 应用迁移到 Windows 应用 SDK,请查看我们的开窗功能迁移指南。 有关详细信息,请参阅 窗口功能迁移 。
- 适用于:UWP/WinUI 2
- 重要 API: ApplicationView.TitleBar 属性、 ApplicationViewTitleBar 类、 CoreApplicationViewTitleBar 类
标题栏组件
此列表描述了标准标题栏的组件。
- 标题栏矩形
- 标题文本
- 系统菜单 - 通过单击应用图标或右键单击标题栏来访问
- 标题控件
- 最小化按钮
- 最大化/还原按钮
- “关闭”按钮
在 UWP 应用程序中,可以使用 ApplicationView 和 CoreApplicationView 类的成员来自定义标题栏。 有多个 API 可以根据所需的自定义级别逐步修改标题栏的外观。
注释
用于 UWP 应用中辅助窗口的 Windows.UI.WindowManagement.AppWindow 类不支持标题栏自定义。 若要自定义使用辅助窗口的 UWP 应用的标题栏,请使用 ApplicationView,如 使用 ApplicationView显示多个视图中所述。
标题栏可以自定义到什么程度
可将两个级别的自定义应用于标题栏:对默认标题栏应用轻微修改,或将应用画布扩展到标题栏区域并提供完全自定义的内容。
简单
对于简单的自定义,例如更改标题栏颜色,可以在应用窗口的标题栏对象上设置属性,以指定要用于标题栏元素的颜色。 在此情况下,系统仍对标题栏的所有其他方面负责,例如绘制应用标题和定义拖动区域。
完全
另一个选项是隐藏默认标题栏,并将其替换为你自己的自定义内容。 例如,你可以在标题栏区域中放置文本、搜索框或自定义菜单。 还需要使用此选项将 材料 背景(如 Mica)扩展到标题栏区域。
选择完全自定义时,你负责将内容放入标题栏区域,并且可以定义自己的拖动区域。 标题控件(系统关闭、最小化和最大化按钮)仍然可用并由系统处理,但应用标题等元素则不可用。 你需要根据应用的需求自行创建这些元素。
简单自定义
如果只想自定义标题栏颜色或图标,可以在应用窗口的标题栏对象上设置属性。
标题
默认情况下,标题栏将应用的显示名称显示为窗口标题。 显示名称在 Package.appxmanifest
文件中设置。
若要将自定义文本添加到标题,请将 ApplicationView.Title 属性设置为文本值,如下所示。
public MainPage()
{
this.InitializeComponent();
ApplicationView.GetForCurrentView().Title = "Custom text";
}
文本位于窗口标题前面,该标题将显示为“自定义文本 - 应用显示名称”。 若要显示没有应用显示名称的自定义标题,必须替换默认标题栏,如 完全自定义 部分所示。
颜色
此示例演示如何获取 ApplicationViewTitleBar 的实例并设置其颜色属性。
调用 Window.Activate 后,可以将此代码放置在应用的 OnLaunched 方法(App.xaml.cs)、或应用的第一页中。
// using Windows.UI;
// using Windows.UI.ViewManagement;
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
// Set active window colors
titleBar.ForegroundColor = Colors.White;
titleBar.BackgroundColor = Colors.Green;
titleBar.ButtonForegroundColor = Colors.White;
titleBar.ButtonBackgroundColor = Colors.SeaGreen;
titleBar.ButtonHoverForegroundColor = Colors.White;
titleBar.ButtonHoverBackgroundColor = Colors.DarkSeaGreen;
titleBar.ButtonPressedForegroundColor = Colors.Gray;
titleBar.ButtonPressedBackgroundColor = Colors.LightGreen;
// Set inactive window colors
titleBar.InactiveForegroundColor = Colors.Gainsboro;
titleBar.InactiveBackgroundColor = Colors.SeaGreen;
titleBar.ButtonInactiveForegroundColor = Colors.Gainsboro;
titleBar.ButtonInactiveBackgroundColor = Colors.SeaGreen;
设置标题栏颜色时需要注意以下几点:
- 关闭按钮的背景颜色没有应用到悬停状态(), 和按下状态(),。 关闭按钮始终为这些状态使用系统定义的颜色。
- 将颜色属性设置为
null
会将其重置为默认系统颜色。 - 无法设置透明颜色。 颜色的 alpha 通道将被忽略。
Windows 的用户可以选择将所选主题色应用于标题栏。 如果你选择设置标题栏颜色,建议明确设置所有颜色。 这可确保不会因用户定义的颜色设置而发生意外的颜色组合。
完全自定义
当你选择进行标题栏完全自定义时,应用的客户端区域会进行扩展以覆盖整个窗口,包括标题栏区域。 你负责对整个窗口进行绘图和输入处理,但不包括标题按钮,因为标题按钮仍由窗口提供。
若要隐藏默认标题栏并将内容扩展到标题栏区域,请将 ExtendViewIntoTitleBar 属性设置为 true
。 可以在应用 OnLaunched
的方法(App.xaml.cs)或应用的第一页中设置此属性。
此示例演示如何获取 CoreApplicationViewTitleBar 并将 ExtendViewIntoTitleBar 属性设置为 true
。
using Windows.ApplicationModel.Core;
public MainPage()
{
this.InitializeComponent();
// Hide default title bar.
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
}
小窍门
当应用关闭并重启时,此设置将保持不变。 在 Visual Studio 中,如果将 ExtendViewIntoTitleBar
设置为 true
,然后想要还原为默认值,则应将其显式设置为 false
并运行应用程序以覆盖已持久化的设置。
标题栏内容和可拖动区域
当应用扩展到标题栏区域时,你将负责定义和管理标题栏的 UI。 这通常至少包括指定标题文本和拖动区域。 标题栏的拖动区域定义了用户可以单击和拖动以移动窗口的位置。 这也是用户可以右键单击以显示系统菜单的位置。
要详细了解可接受的标题栏内容和建议的 UI 模式,请参阅标题栏设计。
可以通过调用 Window.SetTitleBar 方法并传入定义拖动区域的 UIElement 来指定拖动区域。
UIElement
(通常是一个包含其他元素的面板。)ExtendViewIntoTitleBar
属性必须设置为 true
,才能使对 SetTitleBar
的调用产生效果。
下面介绍如何将内容 Grid
设置为可拖动标题栏区域。 此代码位于应用的第一页的 XAML 和代码隐藏文件中。
<Grid x:Name="AppTitleBar" Background="Transparent">
<!-- Width of the padding columns is set in LayoutMetricsChanged handler. -->
<!-- Using padding columns instead of Margin ensures that the background
paints the area under the caption control buttons (for transparent buttons). -->
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
<Image Source="Assets/WindowIcon.png"
Grid.Column="1"
HorizontalAlignment="Left"
Width="16" Height="16"
Margin="8,0,0,0"/>
<TextBlock x:Name="AppTitleTextBlock"
Text="App title"
Style="{StaticResource CaptionTextBlockStyle}"
Grid.Column="1"
VerticalAlignment="Center"
Margin="28,0,0,0"/>
</Grid>
public MainPage()
{
this.InitializeComponent();
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
// Set XAML element as a drag region.
Window.Current.SetTitleBar(AppTitleBar);
}
默认情况下,系统标题栏将应用的显示名称显示为窗口标题。 显示名称在 Package.appxmanifest 文件中设置。 你可以获取此值并将其用于自定义标题栏中,如下所示。
AppTitleTextBlock.Text = AppInfo.Current.DisplayInfo.DisplayName;
重要
指定的拖动区域需要支持碰撞检测。 默认情况下,某些 UI 元素(如 Grid
)在没有设置背景时不参与命中测试。 这意味着,对于某些元素,可能需要设置透明背景画笔。 有关详细信息,请参阅 VisualTreeHelper.FindElementsInHostCoordinates 上的备注。
例如,如果将网格定义为拖动区域,则将其设置为 Background="Transparent"
可拖动。
此网格不可拖动(但其中的可见元素为): <Grid x:Name="AppTitleBar">
此网格看起来相同,但整个网格是可拖动的: <Grid x:Name="AppTitleBar" Background="Transparent">
交互式内容
可以将交互式控件(如按钮、菜单或搜索框)放在应用顶部,以便它们显示在标题栏中。 但是,必须遵循一些规则来确保交互式元素接收用户输入,同时仍允许用户移动窗口。
- 必须调用 SetTitleBar ,才能将区域定义为可拖动标题栏区域。 如果没有,系统将设置页面顶部的默认拖动区域。 然后,系统将处理此区域的所有用户输入,并阻止输入到达控件。
- 将交互式控件放置在 调用 setTitleBar 定义的拖动区域的顶部(具有更高的 z 顺序)。 不要将 UIElement 的交互式控件子级 传递给
SetTitleBar
。 将元素SetTitleBar
传递给后,系统将它视为系统标题栏,并处理指向该元素的所有指针输入。
在这里, AutoSuggestBox 元素的 z 顺序高于 AppTitleBar
,因此它接收用户输入。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="48"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="AppTitleBar" Background="Transparent">
<!-- Width of the padding columns is set in LayoutMetricsChanged handler. -->
<!-- Using padding columns instead of Margin ensures that the background
paints the area under the caption control buttons (for transparent buttons). -->
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
<Image Source="Assets/WindowIcon.png"
Grid.Column="1"
HorizontalAlignment="Left"
Width="16" Height="16"
Margin="8,0,0,0"/>
<TextBlock x:Name="AppTitleTextBlock"
Text="App title"
Style="{StaticResource CaptionTextBlockStyle}"
Grid.Column="1"
VerticalAlignment="Center"
Margin="28,0,0,0"/>
</Grid>
<!-- This control has a higher z-order than AppTitleBar,
so it receives user input. -->
<AutoSuggestBox QueryIcon="Find"
PlaceholderText="Search"
HorizontalAlignment="Center"
Width="260" Height="32"/>
</Grid>
系统标题按钮
系统保留应用窗口的左上角或右上角,用于系统标题按钮(最小化、最大化/还原、关闭)。 系统保留对标题按钮区域的控制权,以确保为拖动、最小化、最大化和关闭窗口提供最低功能。 系统为从左到右的语言绘制右上角的“关闭”按钮,为从右到左的语言绘制左上角的“关闭”按钮。
可以在标题控件区域(如应用背景)下绘制内容,但不应放置任何你期望用户能够与之交互的 UI。 它不会收到任何输入,因为标题控件的输入由系统处理。
上一示例中的这些行显示了 XAML 中定义标题栏的填充列。 使用填充列而不是边距可确保背景绘制标题控件按钮下的区域(对于透明按钮)。 使用左右填充列可确保标题栏在从右向左和从左到右布局中都正常运行。
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
标题控件区域的维度和位置由 CoreApplicationViewTitleBar 类传达,以便你在标题栏 UI 中的布局时加以考虑。 SystemOverlayLeftInset 或 SystemOverlayRightInset 属性确定每侧保留区域的宽度,高度由 Height 属性确定。
你可以处理 LayoutMetricsChanged 事件,以响应标题按钮大小的变化。 例如,如果应用布局从从左到右更改为从右到左,则可能会发生这种情况。 处理此事件以验证和更新依赖于标题栏大小的 UI 元素的位置。
此示例演示如何调整标题栏的布局,以考虑标题栏指标中的更改。
AppTitleBar
、LeftPaddingColumn
和 RightPaddingColumn
都在之前显示的 XAML 中声明。
private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
{
// Get the size of the caption controls and set padding.
LeftPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayLeftInset);
RightPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayRightInset);
}
标题按钮中的颜色和透明度
将应用内容扩展到标题栏区域时,可以将标题按钮的背景设为透明,以便让应用背景显示出来。 通常将背景设置为 Colors.Transparent 才能实现完全透明度。 对于部分透明,请为你将属性设置的颜色设置 alpha 通道。
这些标题栏属性可以是透明的:
所有其他颜色属性将继续忽略 alpha 通道。 如果 ExtendViewIntoTitleBar
设置为 false
,则所有 ApplicationViewTitleBar
颜色属性将会始终忽略 alpha 通道。
按钮背景色不适用于“关闭”按钮,将鼠标悬停 并 按下 状态。 关闭按钮始终为这些状态使用系统定义的颜色。
小窍门
Mica 是一种令人愉快的 材料,有助于区分处于焦点的窗口。 建议将其作为 Windows 11 中长期活动窗口的背景。 如果在窗口的工作区中应用了 Mica,则可以将其扩展到标题栏区域,并将标题按钮设为透明,以便 Mica 显示出来。 有关详细信息,请参阅 Mica 材料。
当窗口处于非活动状态时,将标题栏变暗
应当清晰显示窗口何时处于活动状态,何时处于非活动状态。 至少应更改标题栏中文本、图标和按钮的颜色。
处理 CoreWindow.Activated 事件以确定窗口的激活状态,并根据需要更新标题栏 UI。
public MainPage()
{
...
Window.Current.CoreWindow.Activated += CoreWindow_Activated;
}
private void CoreWindow_Activated(CoreWindow sender, WindowActivatedEventArgs args)
{
UISettings settings = new UISettings();
if (args.WindowActivationState == CoreWindowActivationState.Deactivated)
{
AppTitleTextBlock.Foreground =
new SolidColorBrush(settings.UIElementColor(UIElementType.GrayText));
}
else
{
AppTitleTextBlock.Foreground =
new SolidColorBrush(settings.UIElementColor(UIElementType.WindowText));
}
}
重置标题栏
可以在应用运行时调用 SetTitleBar 切换到新的标题栏元素。 还可以将null
作为参数传递给SetTitleBar
,并将ExtendViewIntoTitleBar设置为false
以还原到默认系统标题栏。
显示和隐藏标题栏
如果向应用添加对全屏或紧凑覆盖模式的支持,则当应用在这些模式之间切换时可能需要更改标题栏。
当应用以 全屏 或 平板电脑模式 (仅限 Windows 10)运行时,系统将隐藏标题栏和标题控件按钮。 但是,用户可以调出标题栏,使其覆盖在应用 UI 顶部。
可以处理 CoreApplicationViewTitleBar.IsVisibleChanged 事件,以在隐藏或调用标题栏时收到通知,并根据需要显示或隐藏自定义标题栏内容。
此示例演示如何处理 IsVisibleChanged
事件以显示和隐藏前面示例中的 AppTitleBar
元素。
public MainPage()
{
this.InitializeComponent();
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
// Register a handler for when the title bar visibility changes.
// For example, when the title bar is invoked in full screen mode.
coreTitleBar.IsVisibleChanged += CoreTitleBar_IsVisibleChanged;
}
private void CoreTitleBar_IsVisibleChanged(CoreApplicationViewTitleBar sender, object args)
{
if (sender.IsVisible)
{
AppTitleBar.Visibility = Visibility.Visible;
}
else
{
AppTitleBar.Visibility = Visibility.Collapsed;
}
}
注释
仅当应用支持时,才能进入 全屏 模式。 有关详细信息,请参阅 ApplicationView.IsFullScreenMode 。 平板电脑模式 (仅限 Windows 10) 是受支持硬件上的 Windows 10 中的用户选项,因此用户可以选择在平板电脑模式下运行任何应用。
注意事项与禁忌
- 务必清楚地显示窗口何时处于活动状态,何时处于非活动状态。 至少要更改标题栏中文本、图标和按钮的颜色。
- 请在应用画布的上边缘明确定义一个拖动区域。 匹配系统标题栏的位置会便于用户查找。
- 务必定义一个拖动区域,以匹配应用画布上的可视标题栏(如果有)。
完全自定义示例
此示例显示了“完全自定义”部分中介绍的所有代码。
<Page
x:Class="WinUI2_ExtendedTitleBar.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUI2_ExtendedTitleBar"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
muxc:BackdropMaterial.ApplyToRootOrPageBackground="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="48"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="AppTitleBar" Background="Transparent">
<!-- Width of the padding columns is set in LayoutMetricsChanged handler. -->
<!-- Using padding columns instead of Margin ensures that the background
paints the area under the caption control buttons (for transparent buttons). -->
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
<Image Source="Assets/WindowIcon.png"
Grid.Column="1"
HorizontalAlignment="Left"
Width="16" Height="16"
Margin="8,0,0,0"/>
<TextBlock x:Name="AppTitleTextBlock"
Text="App title"
Style="{StaticResource CaptionTextBlockStyle}"
Grid.Column="1"
VerticalAlignment="Center"
Margin="28,0,0,0"/>
</Grid>
<!-- This control has a higher z-order than AppTitleBar,
so it receives user input. -->
<AutoSuggestBox QueryIcon="Find"
PlaceholderText="Search"
HorizontalAlignment="Center"
Width="260" Height="32"/>
<muxc:NavigationView Grid.Row="1"
IsBackButtonVisible="Collapsed"
IsSettingsVisible="False">
<StackPanel>
<TextBlock Text="Content"
Style="{ThemeResource TitleTextBlockStyle}"
Margin="12,0,0,0"/>
</StackPanel>
</muxc:NavigationView>
</Grid>
</Page>
public MainPage()
{
this.InitializeComponent();
// Hide default title bar.
CoreApplicationViewTitleBar coreTitleBar =
CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
// Set caption buttons background to transparent.
ApplicationViewTitleBar titleBar =
ApplicationView.GetForCurrentView().TitleBar;
titleBar.ButtonBackgroundColor = Colors.Transparent;
// Set XAML element as a drag region.
Window.Current.SetTitleBar(AppTitleBar);
// Register a handler for when the size of the overlaid caption control changes.
coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged;
// Register a handler for when the title bar visibility changes.
// For example, when the title bar is invoked in full screen mode.
coreTitleBar.IsVisibleChanged += CoreTitleBar_IsVisibleChanged;
// Register a handler for when the window activation changes.
Window.Current.CoreWindow.Activated += CoreWindow_Activated;
}
private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
{
// Get the size of the caption controls and set padding.
LeftPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayLeftInset);
RightPaddingColumn.Width = new GridLength(coreTitleBar.SystemOverlayRightInset);
}
private void CoreTitleBar_IsVisibleChanged(CoreApplicationViewTitleBar sender, object args)
{
if (sender.IsVisible)
{
AppTitleBar.Visibility = Visibility.Visible;
}
else
{
AppTitleBar.Visibility = Visibility.Collapsed;
}
}
private void CoreWindow_Activated(CoreWindow sender, WindowActivatedEventArgs args)
{
UISettings settings = new UISettings();
if (args.WindowActivationState == CoreWindowActivationState.Deactivated)
{
AppTitleTextBlock.Foreground =
new SolidColorBrush(settings.UIElementColor(UIElementType.GrayText));
}
else
{
AppTitleTextBlock.Foreground =
new SolidColorBrush(settings.UIElementColor(UIElementType.WindowText));
}
}