Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Windows proporciona una barra de título predeterminada para cada ventana y permite personalizarla para que se ajuste a la personalidad de la aplicación. La barra de título predeterminada incluye algunos componentes estándar y funcionalidades básicas, como arrastrar y cambiar el tamaño de la ventana.
Consulta el artículo Diseño de la barra de título para obtener instrucciones sobre cómo personalizar la barra de título de la aplicación, el contenido aceptable del área de la barra de título y los patrones de interfaz de usuario recomendados.
Important
En este artículo se muestra cómo personalizar la barra de título en las aplicaciones que usan el SDK de Aplicaciones para Windows, con o sin WinUI 3. En el caso de las aplicaciones que usan UWP y WinUI 2, consulte Personalización de la barra de título para UWP.
Important
Se ha agregado un nuevo control de barra de título en Windows App SDK 1.7. Simplifica el proceso de personalización de la barra de título.
- Se aplica a: Windows App SDK, aplicaciones de escritorio winUI 3
- API importantes: propiedad AppWindow.TitleBar, clase AppWindowTitleBar, clase AppWindow, clase Microsoft.UI.Xaml.Window, propiedad Window.ExtendsContentIntoTitleBar, método Window.SetTitleBar
Componentes de la barra de título
En esta lista se describen los componentes de la barra de título estándar.
- Rectángulo de la barra de título
- Texto del título
- Icono del sistema
- Menú del sistema: para acceder a él, es preciso hacer clic en el icono de la aplicación o hacer clic con el botón derecho en la barra de título
- Controles de título
- Botón Minimizar
- Botón Maximizar o restaurar
- Cerrar botón
Windowing
La funcionalidad basada en ventanas del SDK de Aplicaciones para Windows se realiza a través de la clase Microsoft.UI.Windowing.AppWindow, que se basa en el modelo HWND de Win32. En la aplicación, hay una asignación 1:1 entre un AppWindow y un HWND de nivel superior. AppWindow y sus clases relacionadas proporcionan API que permiten administrar muchos aspectos de las ventanas de nivel superior de la aplicación, entre los que se incluye la personalización de la barra de título. La barra de título predeterminada que proporciona Windows se puede modificar para que se combine con el resto de la interfaz de usuario, o bien ampliar el lienzo de la aplicación al área de la barra de título e incluir su propio contenido en la barra de título.
La funcionalidad de ventanas en WinUI 3 se realiza a través de la clase Microsoft.UI.Xaml.Window , que también se basa en el modelo HWND de Win32. En el caso de las aplicaciones XAML que usan WinUI 3, las API Window de XAML permiten personalizar de una forma más sencilla la barra de título y, al mismo tiempo, permiten acceder a las API de AppWindow cuando sea necesario.
Uso de AppWindow
Las API de AppWindow se pueden usar con cualquier marco de interfaz de usuario que el SDK de Aplicaciones para Windows admita ( Win32, WPF, WinForms o WinUI 3) y se pueden adoptar de forma incremental, es decir usar solo las API que se necesiten.
Si usas XAML de WinUI 3 como marco de interfaz de usuario de la aplicación, las API de Windows y AppWindow están disponibles para ti. A partir de Windows App SDK 1.4, la ventana XAML y AppWindow usan el mismo objeto AppWindowTitleBar para la personalización de la barra de título. Usa la propiedad Window.AppWindow para obtener un objeto AppWindow de una ventana XAML existente. Con este objeto AppWindow tiene acceso a las API de personalización de la barra de título.
Para acceder a más características de la barra de título, puede usar las API de AppWindow desde una ventana de XAML como esta: AppWindow.TitleBar.ForegroundColor = Colors.White;.
Si no usa WinUI 3 1.3, o cualquier versión posterior, utilice las API de interoperabilidad para obtener AppWindow y las API de AppWindow para personalizar la barra de título. Para más información sobre las API de interoperabilidad, consulte la sección Marco de interfaz de usuario e interoperabilidad de HWND del artículo Administrar ventanas de aplicaciones (SDK de Aplicaciones para Windows) y el ejemplo de la galería de ventanas.
Cantidad de personalización de la barra de título
Se pueden aplicar dos niveles de personalización a la barra de título: aplicar pequeñas modificaciones a la barra de título predeterminada, o bien ampliar el lienzo de la aplicación al área de la barra de título e incluir contenido propio en la barra de título.
Simple
Si va a realizar una personalización sencilla, como cambiar el color de la barra de título, puede establecer propiedades en el objeto AppWindowTitleBar para especificar los colores que desea usar para los elementos de la barra de título. En este caso, el sistema sigue siendo el responsable de los restantes aspectos de la barra de título, como dibujar el título de la aplicación y definir las áreas de arrastre.
Full
La otra opción es ocultar la barra de título del sistema predeterminada y reemplazarla por su propio contenido personalizado. Por ejemplo, en el área de la barra de título se pueden colocar texto, un cuadro de búsqueda o menús personalizados. También tendrás que usar esta opción para ampliar un telón de fondo de material , como Mica, en el área de la barra de título.
Si decide realizar una personalización completa, es responsabilidad suya colocar contenido en el área de la barra de título y puede definir sus propias regiones de arrastre. Los controles de título (botones Cerrar, Minimizar y Maximizar del sistema) siguen estando disponibles y los controla el sistema, pero los elementos como el título de la aplicación no. Tendrá que crear esos elementos a medida que la aplicación los necesite.
Personalización sencilla
Si solo quiere personalizar el título, los colores o el icono de la barra de título, puede establecer propiedades en el objeto barra de título de la ventana de la aplicación.
Title
De forma predeterminada, la barra de título muestra el tipo de aplicación como título de la ventana (por ejemplo, "WinUI Desktop"). Debe actualizar el título de la ventana para que muestre un nombre significativo para la aplicación.
Una aplicación XAML tiene un nombre para mostrar que se establece en el archivo Package.appxmanifest. Puede obtener este valor y usarlo para establecer la propiedad Title así.
Title = AppInfo.Current.DisplayInfo.DisplayName;
Para cambiar el título de la ventana, establezca la propiedad Window.Title en un valor de texto de una sola línea, como se muestra aquí.
<Window
...
Title="App title">
...
</Window>
public MainWindow()
{
InitializeComponent();
Title = "App title";
}
Para cambiar el título de la ventana mediante las API de AppWindow, establezca la propiedad AppWindow.Title en un valor de texto de una sola línea, como se muestra aquí. En este ejemplo se muestra cómo usar las API de interoperabilidad para obtener AppWindow, lo que es necesario si la aplicación no usa WinUI 3 1.3, o cualquier versión posterior.
using Microsoft.UI; // Needed for WindowId.
using Microsoft.UI.Windowing; // Needed for AppWindow.
using WinRT.Interop; // Needed for XAML/HWND interop.
private AppWindow m_AppWindow;
public MainWindow()
{
this.InitializeComponent();
m_AppWindow = GetAppWindowForCurrentWindow();
m_AppWindow.Title = "App title";
}
private AppWindow GetAppWindowForCurrentWindow()
{
IntPtr hWnd = WindowNative.GetWindowHandle(this);
WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
return AppWindow.GetFromWindowId(wndId);
}
Colors
Para personalizar los colores predeterminados de la barra de título o cambiar el icono de ventana predeterminado, deberá usar las API de AppWindow, o bien personalizar completamente la barra de título.
En este ejemplo se muestra cómo obtener una instancia de AppWindowTitleBar y establecer sus propiedades de color.
Important
La personalización de colores se omite cuando la aplicación se ejecuta en Windows 10.
// Assumes "this" is a XAML Window. In projects that don't use
// WinUI 3 1.3 or later, use interop APIs to get the AppWindow.
AppWindow m_AppWindow = this.AppWindow;
private bool SetTitleBarColors()
{
// Check to see if customization is supported.
// The method returns true on Windows 10 since Windows App SDK 1.2,
// and on all versions of Windows App SDK on Windows 11.
if (AppWindowTitleBar.IsCustomizationSupported())
{
AppWindowTitleBar m_TitleBar = m_AppWindow.TitleBar;
// Set active window colors.
// Note: No effect when app is running on Windows 10
// because color customization is not supported.
m_TitleBar.ForegroundColor = Colors.White;
m_TitleBar.BackgroundColor = Colors.Green;
m_TitleBar.ButtonForegroundColor = Colors.White;
m_TitleBar.ButtonBackgroundColor = Colors.SeaGreen;
m_TitleBar.ButtonHoverForegroundColor = Colors.Gainsboro;
m_TitleBar.ButtonHoverBackgroundColor = Colors.DarkSeaGreen;
m_TitleBar.ButtonPressedForegroundColor = Colors.Gray;
m_TitleBar.ButtonPressedBackgroundColor = Colors.LightGreen;
// Set inactive window colors.
// Note: No effect when app is running on Windows 10
// because color customization is not supported.
m_TitleBar.InactiveForegroundColor = Colors.Gainsboro;
m_TitleBar.InactiveBackgroundColor = Colors.SeaGreen;
m_TitleBar.ButtonInactiveForegroundColor = Colors.Gainsboro;
m_TitleBar.ButtonInactiveBackgroundColor = Colors.SeaGreen;
return true;
}
return false;
}
Hay varias cosas que debe tener en cuenta al establecer los colores de la barra de título:
- El color de fondo del botón no se aplica al mouse del botón de cierre y se presionan los estados. El botón Cerrar siempre usa el color definido por el sistema para esos estados.
- Si se establece una propiedad de color en
null, se restablece al color predeterminado del sistema. - No se pueden establecer colores transparentes. Se ignora el canal alfa del color.
Windows ofrece a un usuario la opción de aplicar su color de énfasis seleccionado a la barra de título. Si establece algún color para la barra de título, es aconsejable que establezca explícitamente todos los colores. Esto garantiza que no se produzcan combinaciones de colores no deseadas debido a la configuración de colores definida por el usuario.
Icono y menú del sistema
El icono del sistema no solo se puede ocultar, también se puede reemplazar por un icono personalizado. El icono del sistema muestra el menú del sistema cuando se hace clic con el botón derecho o se pulsa una vez. Cierra la ventana cuando se hace doble clic o pulsa en ella.
Para mostrar u ocultar el icono del sistema y los comportamientos asociados, establezca la propiedad IconShowOptions de la barra de título.
m_TitleBar.IconShowOptions = IconShowOptions.HideIconAndSystemMenu;
Para usar un icono de ventana personalizado, llame a uno de los métodos AppWindow.SetIcon para establecer el nuevo icono.
SetIcon(String)El método SetIcon(String) solo funciona actualmente con archivos .ico. La cadena que se pasa a este método es la ruta de acceso completa al archivo .ico.
m_AppWindow.SetIcon("iconPath/iconName.ico");SetIcon(IconId)Si ya tiene un identificador para un icono (
HICON) de una de las funciones Icon como CreateIcon, puede usar la API de interoperabilidad GetIconIdFromIcon para obtener un IconId. A continuación, puede pasarIconIdal método SetIcon(IconId) para establecer el icono de la ventana.m_AppWindow.SetIcon(iconId));
Personalización completa
Si realiza una personalización completa de la barra de título, el área cliente de la aplicación se extiende para cubrir toda la ventana, incluido el área de la barra de título. Usted es responsable tanto del dibujo como del control de entrada en toda la ventana, excepto los botones de título, que los proporciona la ventana.
Para ocultar la barra de título del sistema y extender el contenido al área de la barra de título, establezca la propiedad que extiende el contenido de la aplicación al área de la barra de título en true. En una aplicación XAML, esta propiedad se puede establecer en el método de la OnLaunched aplicación (App.xaml.cs) o en la primera página de la aplicación.
Tip
Consulte la sección Ejemplo de personalización completa para ver todo el código a la vez.
En este ejemplo se muestra cómo establecer la propiedad Window.ExtendsContentIntoTitleBar en true.
public MainWindow()
{
this.InitializeComponent();
// Hide system title bar.
ExtendsContentIntoTitleBar = true;
}
Caution
ExtendsContentIntoTitleBar se muestra en XAML IntelliSense para Window, pero si se establece en XAML, se produce un error. Establezca esta propiedad en el código.
En este ejemplo se muestra cómo obtener la propiedad AppWindowTitleBar y establecer la propiedad AppWindowTitleBar.ExtendsContentIntoTitleBar en true. En este ejemplo se muestra cómo usar las API de interoperabilidad para obtener AppWindow, algo que es necesario si la aplicación no usa WinUI 3 1.3, o cualquier versión posterior.
using Microsoft.UI; // Needed for WindowId.
using Microsoft.UI.Windowing; // Needed for AppWindow.
using WinRT.Interop; // Needed for XAML/HWND interop.
private AppWindow m_AppWindow;
public MainWindow()
{
this.InitializeComponent();
m_AppWindow = GetAppWindowForCurrentWindow();
var titleBar = m_AppWindow.TitleBar;
// Hide system title bar.
titleBar.ExtendsContentIntoTitleBar = true;
}
private AppWindow GetAppWindowForCurrentWindow()
{
IntPtr hWnd = WindowNative.GetWindowHandle(this);
WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
return AppWindow.GetFromWindowId(wndId);
}
Contenido de la barra de título y la región de arrastre predeterminada
Cuando la aplicación se extiende al área de la barra de título, usted es el responsable de definir y administrar la interfaz de usuario de la barra de título. Normalmente, esto incluye, como mínimo, especificar el texto del título y la región de arrastre. La región de arrastre de la barra de título define el lugar o lugares en que el usuario puede hacer clic y arrastrar para mover la ventana. También es donde el usuario puede hacer clic con el botón derecho para mostrar el menú del sistema.
Para más información sobre el contenido aceptable de la barra de título y los patrones de interfaz de usuario recomendados, consulte Diseño de la barra de título.
En este ejemplo se muestra el XAML de la interfaz de usuario de una barra de título personalizada sin contenido interactivo.
<Grid x:Name="AppTitleBar"
Height="32">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
<Image x:Name="TitleBarIcon" Source="ms-appx:///Assets/StoreLogo.png"
Grid.Column="1"
HorizontalAlignment="Left"
Width="16" Height="16"
Margin="8,0,0,0"/>
<TextBlock x:Name="TitleBarTextBlock"
Text="App title"
Style="{StaticResource CaptionTextBlockStyle}"
Grid.Column="1"
VerticalAlignment="Center"
Margin="28,0,0,0"/>
</Grid>
Important
LeftPaddingColumn y RightPaddingColumn se usan para reservar espacio para los botones de título. Los valores Width de estas columnas se establecen en el código, lo que se muestra más adelante. En la sección Botones de título del sistema encontrará el código y una explicación.
Las aplicaciones XAML tienen un nombre para mostrar que se establece en el archivo Package.appxmanifest. Así puede obtener este valor y usarlo en la barra de título personalizada.
TitleBarTextBlock.Text = AppInfo.Current.DisplayInfo.DisplayName;
Al extender el contenido en el área de la barra de título, la barra de título del sistema se oculta y se crea una appWindowTitleBar predeterminada que proporciona botones de título y una región de arrastre a través del ancho de la pantalla, idéntica a la barra de título del sistema. Si no coloca contenido interactivo en la barra de título, puede dejar esta región de arrastre predeterminada tal como está. Si coloca contenido interactivo en la barra de título, debe especificar qué regiones son interactivas, lo que se tratará en la siguiente sección.
Caution
Cuando se definen regiones de arrastre personalizadas, estas no tienen que estar en la parte superior de la ventana, en el área de la barra de título predeterminada; cualquier parte de la interfaz de usuario se puede definir como región de arrastre. Sin embargo, la colocación de regiones de arrastre en diferentes lugares podría dificultar su detección a los usuarios.
Contenido interactivo
Se pueden colocar controles interactivos, como botones, menús o un cuadro de búsqueda, en la parte superior de la aplicación para que parezca que están en la barra de título. Sin embargo, es preciso especificar qué regiones son interactivas, con el fin de tener la certeza de que los elementos interactivos reciben la entrada del usuario y, al mismo tiempo, permiten a los usuarios mover la ventana.
Al agregar contenido interactivo en el área de la barra de título, debe usar la clase InputNonClientPointerSource para especificar áreas en las que la entrada se pasa al control interactivo, en lugar de controlarla la barra de título. Para establecer las regiones interactivas, llame al método InputNonClientPointerSource.SetRegionRects . Este método toma un valor que especifica el tipo de región que se establece (en este caso, Passthrough) y una matriz de rectángulos, cada uno de los cuales define una región Passthrough. Cuando cambie el tamaño de la barra de título, es preciso volver a calcular las regiones interactivas para que se ajusten al nuevo tamaño y llamar a SetRegionRects con los nuevos valores.
En este ejemplo se muestra una interfaz de usuario de una barra de título personalizada con un cuadro de búsqueda y un control de cuenta PersonPicture. Muestra cómo calcular y establecer los rectángulos interactivos de estos controles para que la entrada pase por ellos.
Hay algunas aspectos de este código que se deben tener en cuenta:
- Establezca el alto de cuadrícula
AppTitleBaren 48 para seguir las instrucciones de diseño de la barra de título para el contenido interactivo. - Establezca PreferredHeightOption en
Tallpara que los botones de título sean el mismo alto que la barra de título. - Para facilitar el cambio de tamaño de los controles y el cálculo de regiones, use
Gridcon varias columnas con nombre para el diseño. - Use el tamaño de estrella (*) con
MinWidthpara la columna que contiene paraAutoSuggestBoxque cambie automáticamente el tamaño con la ventana. - Establezca
MinWidthenRightDragColumnpara reservar un área pequeña que siempre se pueda arrastrar, incluso cuando se cambia el tamaño de la ventana. - Establezca
ExtendsContentIntoTitleBarentrueen el constructor MainWindow. Si lo establece en el código al que se va a llamar más adelante, es posible que la barra de título del sistema predeterminada se muestre primero y luego se oculte. - Realice la llamada inicial para calcular las regiones interactivas después de que se haya cargado el elemento
AppTitleBar. De lo contrario, no hay ninguna garantía de que los elementos usados para el cálculo tengan sus valores correctos. - No actualice los cálculos del rectángulo interactivo hasta que el elemento
AppTitleBarhaya cambiado de tamaño (AppTitleBar_SizeChanged). Si depende del eventoChangedde la ventana, habrá situaciones (como maximizar o minimizar la ventana) en las que el evento se produzca antes de se cambia el tamaño deAppTitleBary los cálculos usarán valores incorrectos. - No establezca las áreas interactivas o de arrastre personalizadas hasta que compruebe
ExtendsContentIntoTitleBarpara confirmar que se usa una barra de título personalizada.
<Grid x:Name="AppTitleBar"
Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition x:Name="IconColumn" Width="Auto"/>
<ColumnDefinition x:Name="TitleColumn" Width="Auto"/>
<ColumnDefinition x:Name="LeftDragColumn" Width="*"/>
<ColumnDefinition x:Name="SearchColumn" Width="4*" MinWidth="220"/>
<ColumnDefinition x:Name="RightDragColumn" Width="*" MinWidth="48"/>
<ColumnDefinition x:Name="AccountColumn" Width="Auto"/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
<Image x:Name="TitleBarIcon"
Source="ms-appx:///Assets/StoreLogo.png"
Grid.Column="1"
Width="16" Height="16"
Margin="8,0,4,0"/>
<TextBlock x:Name="TitleBarTextBlock"
Text="App title"
Style="{StaticResource CaptionTextBlockStyle}"
Grid.Column="2"
VerticalAlignment="Center">
</TextBlock>
<AutoSuggestBox x:Name="TitleBarSearchBox"
Grid.Column="4"
QueryIcon="Find"
PlaceholderText="Search"
VerticalAlignment="Center"
MaxWidth="600"/>
<PersonPicture x:Name="PersonPic"
Grid.Column="6"
Height="32" Margin="0,0,16,0"/>
</Grid>
Este código muestra cómo calcular y establecer las regiones interactivas que corresponden a los controles AutoSuggestBox y PersonPicture .
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
// Assumes "this" is a XAML Window. In projects that don't use
// WinUI 3 1.3 or later, use interop APIs to get the AppWindow.
m_AppWindow = this.AppWindow;
AppTitleBar.Loaded += AppTitleBar_Loaded;
AppTitleBar.SizeChanged += AppTitleBar_SizeChanged;
ExtendsContentIntoTitleBar = true;
TitleBarTextBlock.Text = AppInfo.Current.DisplayInfo.DisplayName;
}
private void AppTitleBar_Loaded(object sender, RoutedEventArgs e)
{
if (ExtendsContentIntoTitleBar == true)
{
// Set the initial interactive regions.
SetRegionsForCustomTitleBar();
}
}
private void AppTitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (ExtendsContentIntoTitleBar == true)
{
// Update interactive regions if the size of the window changes.
SetRegionsForCustomTitleBar();
}
}
private void SetRegionsForCustomTitleBar()
{
// Specify the interactive regions of the title bar.
double scaleAdjustment = AppTitleBar.XamlRoot.RasterizationScale;
RightPaddingColumn.Width = new GridLength(m_AppWindow.TitleBar.RightInset / scaleAdjustment);
LeftPaddingColumn.Width = new GridLength(m_AppWindow.TitleBar.LeftInset / scaleAdjustment);
GeneralTransform transform = TitleBarSearchBox.TransformToVisual(null);
Rect bounds = transform.TransformBounds(new Rect(0, 0,
TitleBarSearchBox.ActualWidth,
TitleBarSearchBox.ActualHeight));
Windows.Graphics.RectInt32 SearchBoxRect = GetRect(bounds, scaleAdjustment);
transform = PersonPic.TransformToVisual(null);
bounds = transform.TransformBounds(new Rect(0, 0,
PersonPic.ActualWidth,
PersonPic.ActualHeight));
Windows.Graphics.RectInt32 PersonPicRect = GetRect(bounds, scaleAdjustment);
var rectArray = new Windows.Graphics.RectInt32[] { SearchBoxRect, PersonPicRect };
InputNonClientPointerSource nonClientInputSrc =
InputNonClientPointerSource.GetForWindowId(this.AppWindow.Id);
nonClientInputSrc.SetRegionRects(NonClientRegionKind.Passthrough, rectArray);
}
private Windows.Graphics.RectInt32 GetRect(Rect bounds, double scale)
{
return new Windows.Graphics.RectInt32(
_X: (int)Math.Round(bounds.X * scale),
_Y: (int)Math.Round(bounds.Y * scale),
_Width: (int)Math.Round(bounds.Width * scale),
_Height: (int)Math.Round(bounds.Height * scale)
);
}
}
Warning
AppWindow usa píxeles físicos para lograr compatibilidad con marcos de interfaz de usuario que no usan coordenadas lógicas. Si usa WPF o WinUI 3, RightInset, LeftInsety los valores usados para calcular regiones deben ajustarse si la escala de pantalla no es del 100 %. En este ejemplo, se obtiene un valor scaleAdjustment para tener cuenta la configuración de la escala de visualización.
- Para WinUI 3, use la propiedad XamlRoot.RasterizationScale para obtener el ajuste de escala.
- Para WPF, puede controlar el evento Window.DpiChanged para obtener el valor NewDpi y calcular el ajuste de escala.
Botones de título del sistema
El sistema se reserva la esquina superior izquierda o superior derecha de la ventana de la aplicación para los botones de título del sistema (minimizar, maximizar o restaurar, cerrar). El sistema conserva el control del área de botones de título para garantizar que se proporciona la funcionalidad mínima para arrastrar, minimizar, maximizar y cerrar la ventana. El sistema dibuja el botón Cerrar en la esquina superior derecha para los idiomas que se leen de izquierda a derecha y en la esquina superior izquierda para los idiomas que se leen de derecha a izquierda.
Puede dibujar contenido debajo del área de control de título, como el fondo de la aplicación, pero no debe colocar ninguna interfaz de usuario con la que espere que el usuario interactúe. No recibe ninguna entrada porque el sistema controla la entrada de los controles de título.
Estas líneas del ejemplo anterior muestran las columnas de relleno en el XAML que define la barra de título. El uso de columnas de relleno en lugar de márgenes garantiza que el fondo pinta el área debajo de los botones de control de título (para botones transparentes). El uso de columnas de relleno a la derecha e izquierda garantiza que la barra de título se comporta correctamente en diseños tanto de derecha a izquierda como de izquierda a derecha.
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
La clase AppWindowTitleBar comunica las dimensiones y la posición del área de control de título para que pueda tenerlo en cuenta en el diseño de la interfaz de usuario de la barra de título. Las propiedades LeftInset o RightInset proporcionan el ancho de la región reservada en cada lado y la propiedad Height asigna su alto.
Aquí se muestra cómo se especifica el ancho de las columnas de relleno cuando se calculan y establecen las regiones de arrastre.
RightPaddingColumn.Width =
new GridLength(m_AppWindow.TitleBar.RightInset / scaleAdjustment);
LeftPaddingColumn.Width =
new GridLength(m_AppWindow.TitleBar.LeftInset / scaleAdjustment);
Important
Consulte información importante en la sección Contenido interactivo sobre cómo afecta el escalado de pantalla a estos valores.
Compatibilidad de las barras de título altas con las barras de título personalizadas
Si se va a agregar contenido interactivo, como un cuadro de búsqueda o una imagen de una persona, a la barra de título, es aconsejable aumentar el alto de la barra, con el fin de que haya más espacio para estos elementos. Las barras de título altas también facilitan la manipulación táctil. La propiedad AppWindowTitleBar.PreferredHeightOption le ofrece la opción de aumentar el alto de la barra de título desde el alto estándar, que es el valor predeterminado, hasta un alto más alto. Al seleccionar el modo de barra de título Tall, los botones de subtítulo que el sistema dibuja superpuestos en el área de cliente se representan más altos con sus glifos mín./máx./cerrar centrados. Si no ha especificado ninguna región de arrastre, el sistema dibujará una que aumente el ancho de la ventana y el alto determinado por el valor de PreferredHeightOption que haya establecido.
En este ejemplo se muestra cómo se puede establecer la propiedad PreferredHeightOption.
// A taller title bar is only supported when drawing a fully custom title bar.
if (ExtendsContentIntoTitleBar == true)
{
m_AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
}
Caution
La propiedad AppWindowTitleBar.ExtendsContentIntoTitleBar debe ser true antes de establecer la PreferredHeightOption propiedad . Si intenta establecer PreferredHeightOption mientras ExtendsContentIntoTitleBar sea false, se producirá una excepción.
Color y transparencia en los botones de título
Al extender el contenido de la aplicación al área de la barra de título, puedes hacer que el fondo de los botones de título sea transparente, con el fin de que se vea el fondo de la aplicación. Normalmente, establece el fondo en Colors.Transparent para una transparencia completa. Para la transparencia parcial, establezca el canal alfa del color en el que se establece la propiedad.
Estas propiedades de la barra de título pueden ser transparentes:
- ButtonBackgroundColor
- ButtonHoverBackgroundColor
- ButtonPressedBackgroundColor
- ButtonInactiveBackgroundColor
Las restantes propiedades de color seguirán ignorando el canal alfa. Si ExtendsContentIntoTitleBar se establece en false, el canal alfa siempre se omite en todas las propiedades de color de AppWindowTitleBar.
El color de fondo del botón no se aplica al botón Cerrar y se presionan los estados. El botón Cerrar siempre usa el color definido por el sistema para esos estados.
Tip
Mica es un material encantador que ayuda a distinguir la ventana que está en el foco. Se recomienda usarlo como fondo para ventanas de larga duración en Windows 11. Si ha aplicado Mica en el área de cliente de la ventana, puede extenderla al área de la barra de título y hacer que los botones de título sean transparentes para que se vea la Mica. Consulta material de Mica para obtener más información.
Atenuación de la barra de título cuando la ventana está inactiva
Debe ser obvio en qué momento la ventana está activa o inactiva. Para ello, como mínimo, debe cambiar el color del texto, los iconos y los botones de la barra de título.
En el caso de las aplicaciones XAML, controla el evento Window.Activated para determinar el estado de activación de la ventana y actualizar la interfaz de usuario de la barra de título según sea necesario.
public MainWindow()
{
...
Activated += MainWindow_Activated;
}
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
if (args.WindowActivationState == WindowActivationState.Deactivated)
{
TitleBarTextBlock.Foreground =
(SolidColorBrush)App.Current.Resources["WindowCaptionForegroundDisabled"];
}
else
{
TitleBarTextBlock.Foreground =
(SolidColorBrush)App.Current.Resources["WindowCaptionForeground"];
}
}
En otros marcos de la interfaz de usuario, controle un evento para determinar el estado de activación de la ventana y actualizar la interfaz de usuario de la barra de título según sea necesario. La forma de determinar el estado de la ventana depende del marco de la interfaz de usuario que se use para la aplicación.
- Win32: escuche y responda al mensaje de WM_ACTIVATE .
- WPF: controla Window.Activated, Window.Deactivated.
- WinForms: controla Form.Activated, Form.Deactivate.
Restablecimiento de la barra de título
Para restablecer o cambiar a la barra de título del sistema mientras se ejecuta la aplicación, puedes llamar a AppWindowTitleBar.ResetToDefault.
m_AppWindow.TitleBar.ResetToDefault();
En el caso de las aplicaciones XAML, la barra de título también se puede restablecer de las siguientes maneras:
- Llame a SetTitleBar para cambiar a un nuevo elemento de barra de título mientras se ejecuta la aplicación.
- Llame a
SetTitleBarconnullcomo parámetro para restablecer a las regiones de arrastre predeterminadas deAppWindowTitleBar. - Llame a
SetTitleBarconnullcomo parámetro y establezca ExtendsContentIntoTitleBar enfalsepara revertir a la barra de título del sistema predeterminada.
Mostrar y ocultar la barra de título
Si agregas compatibilidad con los modos de superposición de pantalla completa o compacta a tu aplicación, es posible que tengas que realizar cambios en la barra de título cuando la aplicación cambie entre estos modos. La ventana de XAML no proporciona ninguna API para admitir el modo a pantalla completa; puede usar las API de AppWindow para ello.
Cuando la aplicación se ejecuta en modo de pantalla completa , el sistema oculta los botones de control de título y barra de título. Puede controlar el evento AppWindow.Changed y comprobar la propiedad DidPresenterChange del evento para determinar si debe mostrar, ocultar o cambiar la barra de título en respuesta a una nueva presentación de ventana.
En este ejemplo se muestra cómo controlar el evento Changed para mostrar y ocultar el elemento AppTitleBar de los ejemplos anteriores. Si la ventana se coloca en modo de superposición compacta , la barra de título se restablece a la barra de título del sistema predeterminada (o puede proporcionar una barra de título personalizada optimizada para superposición compacta).
public MainWindow()
{
this.InitializeComponent();
m_AppWindow = this.AppWindow;
m_AppWindow.Changed += AppWindow_Changed;
}
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
if (args.DidPresenterChange)
{
switch (sender.Presenter.Kind)
{
case AppWindowPresenterKind.CompactOverlay:
// Compact overlay - hide custom title bar
// and use the default system title bar instead.
AppTitleBar.Visibility = Visibility.Collapsed;
sender.TitleBar.ResetToDefault();
break;
case AppWindowPresenterKind.FullScreen:
// Full screen - hide the custom title bar
// and the default system title bar.
AppTitleBar.Visibility = Visibility.Collapsed;
sender.TitleBar.ExtendsContentIntoTitleBar = true;
break;
case AppWindowPresenterKind.Overlapped:
// Normal - hide the system title bar
// and use the custom title bar instead.
AppTitleBar.Visibility = Visibility.Visible;
sender.TitleBar.ExtendsContentIntoTitleBar = true;
break;
default:
// Use the default system title bar.
sender.TitleBar.ResetToDefault();
break;
}
}
}
Note
Los modos de superposicióncompacta y de pantalla completa solo se pueden especificar si la aplicación lo admite. Para más información, consulte Administración de ventanas de aplicaciones, FullScreenPresenter y CompactOverlayPresenter.
Cosas que hacer y cosas que evitar
- Haga que sea evidente en qué momento una ventana está activa o inactiva. Como mínimo, cambie el color del texto, los iconos y los botones de la barra de título.
- Defina una región de arrastre a lo largo del borde superior del lienzo de la aplicación. La coincidencia con la ubicación de las barras de título del sistema facilita la búsqueda por parte de los usuarios.
- Defina una región de arrastre que coincida con la barra de título visual (si existe) en el lienzo de la aplicación.
Ejemplo de personalización completa
En este ejemplo se muestra todo el código descrito en la sección Personalización completa.
<Window
x:Class="WinUI3_CustomTitleBar.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="AppTitleBar"
Height="48">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition x:Name="IconColumn" Width="Auto"/>
<ColumnDefinition x:Name="TitleColumn" Width="Auto"/>
<ColumnDefinition x:Name="LeftDragColumn" Width="*"/>
<ColumnDefinition x:Name="SearchColumn" Width="4*" MinWidth="220"/>
<ColumnDefinition x:Name="RightDragColumn" Width="*" MinWidth="48"/>
<ColumnDefinition x:Name="AccountColumn" Width="Auto"/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
<Image x:Name="TitleBarIcon"
Source="ms-appx:///Assets/StoreLogo.png"
Grid.Column="1"
Width="16" Height="16"
Margin="8,0,4,0"/>
<TextBlock x:Name="TitleBarTextBlock"
Text="App title"
Style="{StaticResource CaptionTextBlockStyle}"
Grid.Column="2"
VerticalAlignment="Center">
</TextBlock>
<AutoSuggestBox x:Name="TitleBarSearchBox"
Grid.Column="4"
QueryIcon="Find"
PlaceholderText="Search"
VerticalAlignment="Center"
MaxWidth="600"/>
<PersonPicture x:Name="PersonPic"
Grid.Column="6"
Height="32" Margin="0,0,16,0"/>
</Grid>
<NavigationView Grid.Row="1"
IsBackButtonVisible="Collapsed"
IsSettingsVisible="False">
<StackPanel>
<TextBlock Text="Content"
Style="{ThemeResource TitleTextBlockStyle}"
Margin="32,0,0,0"/>
<StackPanel Grid.Row="1" VerticalAlignment="Center">
<Button Margin="4" x:Name="CompactoverlaytBtn"
Content="Enter CompactOverlay"
Click="SwitchPresenter"/>
<Button Margin="4" x:Name="FullscreenBtn"
Content="Enter FullScreen"
Click="SwitchPresenter"/>
<Button Margin="4" x:Name="OverlappedBtn"
Content="Revert to default (Overlapped)"
Click="SwitchPresenter"/>
</StackPanel>
</StackPanel>
</NavigationView>
</Grid>
</Window>
using Microsoft.UI.Input;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using System;
using Windows.ApplicationModel;
using Rect = Windows.Foundation.Rect;
public sealed partial class MainWindow : Window
{
private AppWindow m_AppWindow;
public MainWindow()
{
this.InitializeComponent();
// Assumes "this" is a XAML Window. In projects that don't use
// WinUI 3 1.3 or later, use interop APIs to get the AppWindow.
m_AppWindow = this.AppWindow;
m_AppWindow.Changed += AppWindow_Changed;
Activated += MainWindow_Activated;
AppTitleBar.SizeChanged += AppTitleBar_SizeChanged;
AppTitleBar.Loaded += AppTitleBar_Loaded;
ExtendsContentIntoTitleBar = true;
if (ExtendsContentIntoTitleBar == true)
{
m_AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
}
TitleBarTextBlock.Text = AppInfo.Current.DisplayInfo.DisplayName;
}
private void AppTitleBar_Loaded(object sender, RoutedEventArgs e)
{
if (ExtendsContentIntoTitleBar == true)
{
// Set the initial interactive regions.
SetRegionsForCustomTitleBar();
}
}
private void AppTitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (ExtendsContentIntoTitleBar == true)
{
// Update interactive regions if the size of the window changes.
SetRegionsForCustomTitleBar();
}
}
private void SetRegionsForCustomTitleBar()
{
// Specify the interactive regions of the title bar.
double scaleAdjustment = AppTitleBar.XamlRoot.RasterizationScale;
RightPaddingColumn.Width = new GridLength(m_AppWindow.TitleBar.RightInset / scaleAdjustment);
LeftPaddingColumn.Width = new GridLength(m_AppWindow.TitleBar.LeftInset / scaleAdjustment);
// Get the rectangle around the AutoSuggestBox control.
GeneralTransform transform = TitleBarSearchBox.TransformToVisual(null);
Rect bounds = transform.TransformBounds(new Rect(0, 0,
TitleBarSearchBox.ActualWidth,
TitleBarSearchBox.ActualHeight));
Windows.Graphics.RectInt32 SearchBoxRect = GetRect(bounds, scaleAdjustment);
// Get the rectangle around the PersonPicture control.
transform = PersonPic.TransformToVisual(null);
bounds = transform.TransformBounds(new Rect(0, 0,
PersonPic.ActualWidth,
PersonPic.ActualHeight));
Windows.Graphics.RectInt32 PersonPicRect = GetRect(bounds, scaleAdjustment);
var rectArray = new Windows.Graphics.RectInt32[] { SearchBoxRect, PersonPicRect };
InputNonClientPointerSource nonClientInputSrc =
InputNonClientPointerSource.GetForWindowId(this.AppWindow.Id);
nonClientInputSrc.SetRegionRects(NonClientRegionKind.Passthrough, rectArray);
}
private Windows.Graphics.RectInt32 GetRect(Rect bounds, double scale)
{
return new Windows.Graphics.RectInt32(
_X: (int)Math.Round(bounds.X * scale),
_Y: (int)Math.Round(bounds.Y * scale),
_Width: (int)Math.Round(bounds.Width * scale),
_Height: (int)Math.Round(bounds.Height * scale)
);
}
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
{
if (args.WindowActivationState == WindowActivationState.Deactivated)
{
TitleBarTextBlock.Foreground =
(SolidColorBrush)App.Current.Resources["WindowCaptionForegroundDisabled"];
}
else
{
TitleBarTextBlock.Foreground =
(SolidColorBrush)App.Current.Resources["WindowCaptionForeground"];
}
}
private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
if (args.DidPresenterChange)
{
switch (sender.Presenter.Kind)
{
case AppWindowPresenterKind.CompactOverlay:
// Compact overlay - hide custom title bar
// and use the default system title bar instead.
AppTitleBar.Visibility = Visibility.Collapsed;
sender.TitleBar.ResetToDefault();
break;
case AppWindowPresenterKind.FullScreen:
// Full screen - hide the custom title bar
// and the default system title bar.
AppTitleBar.Visibility = Visibility.Collapsed;
sender.TitleBar.ExtendsContentIntoTitleBar = true;
break;
case AppWindowPresenterKind.Overlapped:
// Normal - hide the system title bar
// and use the custom title bar instead.
AppTitleBar.Visibility = Visibility.Visible;
sender.TitleBar.ExtendsContentIntoTitleBar = true;
break;
default:
// Use the default system title bar.
sender.TitleBar.ResetToDefault();
break;
}
}
}
private void SwitchPresenter(object sender, RoutedEventArgs e)
{
if (AppWindow != null)
{
AppWindowPresenterKind newPresenterKind;
switch ((sender as Button).Name)
{
case "CompactoverlaytBtn":
newPresenterKind = AppWindowPresenterKind.CompactOverlay;
break;
case "FullscreenBtn":
newPresenterKind = AppWindowPresenterKind.FullScreen;
break;
case "OverlappedBtn":
newPresenterKind = AppWindowPresenterKind.Overlapped;
break;
default:
newPresenterKind = AppWindowPresenterKind.Default;
break;
}
// If the same presenter button was pressed as the
// mode we're in, toggle the window back to Default.
if (newPresenterKind == AppWindow.Presenter.Kind)
{
AppWindow.SetPresenter(AppWindowPresenterKind.Default);
}
else
{
// Else request a presenter of the selected kind
// to be created and applied to the window.
AppWindow.SetPresenter(newPresenterKind);
}
}
}
}