Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Windows tillhandahåller ett standardnamnfält för varje fönster och gör att du kan anpassa det så att det matchar appens personlighet. Standardrubrikfältet levereras med vissa standardkomponenter och kärnfunktioner som att dra och ändra storlek på fönstret.
Se designartikeln för rubrikfält för vägledning om hur du anpassar appens namnlist, acceptabelt innehåll i namnlisten och rekommenderade användargränssnittsmönster.
Important
Den här artikeln visar hur du anpassar namnlisten för appar som använder Windows App SDK, antingen med eller utan WinUI 3. För appar som använder UWP och WinUI 2, se Anpassning av titellist för UWP.
Important
En ny namnlistkontroll har lagts till i Windows App SDK 1.7. Det förenklar processen för anpassning av namnlister.
- Gäller för: Windows App SDK, WinUI 3-skrivbordsappar
- Viktiga API:er: Egenskapen AppWindow.TitleBar, klassen AppWindowTitleBar, klassen AppWindow, klassen Microsoft.UI.Xaml.Window,Window.ExtendsContentIntoTitleBar, window.SetTitleBar-metoden
Komponenter i titelraden
I den här listan beskrivs komponenterna i standardrubrikfältet.
- Rektangel för titelrad
- Rubriktext
- Systemikon
- Systemmeny – nås genom att klicka på appikonen eller högerklicka på namnlisten
- Beskrivningskontroller
- Knappen Minimera
- Knappen Maximera/återställa
- Knappen Stäng
Windowing
Fönsterfunktionerna i Windows App SDK finns i klassen Microsoft.UI.Windowing.AppWindow, som baseras på Win32 HWND-modellen. Det finns en 1:1-mappning mellan en AppWindow och en HWND på toppnivå i din app. AppWindow och dess relaterade klasser tillhandahåller API:er som gör att du kan hantera många aspekter av appens toppnivåfönster, inklusive anpassning av namnlisten. Du kan ändra standardrubrikfältet som Windows tillhandahåller så att det blandas med resten av användargränssnittet eller utöka apparbetsytan till rubrikfältet och ange ditt eget innehåll i namnlisten.
Fönsterfunktionerna i WinUI 3 går via klassen Microsoft.UI.Xaml.Window , som också baseras på Win32 HWND-modellen. För XAML-appar som använder WinUI 3 är XAML-fönster-API:er ett enklare sätt att anpassa namnlisten, samtidigt som du kan komma åt AppWindow-API:erna när det behövs.
Så här arbetar du med AppWindow
Du kan använda AppWindow-API:er med valfritt gränssnittsramverk som Windows App SDK stöder – Win32, WPF, WinForms eller WinUI 3 – och du kan använda dem stegvis med bara de API:er du behöver.
Om du använder WinUI 3 XAML som appens gränssnittsramverk är både Windows - och AppWindow-API :erna tillgängliga för dig. Från och med Windows App SDK 1.4 använder XAML-fönstret och AppWindow samma AppWindowTitleBar-objekt för anpassning av namnlisten. Använd egenskapen Window.AppWindow för att hämta ett AppWindow-objekt från ett befintligt XAML-fönster. Med det här AppWindow-objektet har du åtkomst till API:erna för anpassning av namnlisten.
Om du vill komma åt ytterligare funktioner i namnlisten kan du använda AppWindow-API:erna från XAML-fönstret så här: AppWindow.TitleBar.ForegroundColor = Colors.White;.
Om du inte använder WinUI 3 1.3 eller senare använder du interop-API:er för att hämta AppWindow och använda AppWindow-API:erna för att anpassa namnlisten. Mer information om interop-API:er finns i Manage app windows – UI framework och HWND interop och i Windowing gallery sample.
Hur mycket du vill anpassa namnlisten
Det finns två anpassningsnivåer som du kan tillämpa på namnlisten: tillämpa mindre ändringar på standardrubrikfältet eller utöka apparbetsytan till området med namnlisten och tillhandahålla helt anpassat innehåll.
Simple
För enkel anpassning, som att ändra namnlistfärgen, kan du ange egenskaper för objektet AppWindowTitleBar för att ange de färger som du vill använda för rubrikfältelement. I det här fallet behåller systemet ansvaret för alla andra aspekter av titelraden, till exempel för att rita upp apptiteln och definiera dragområden.
Full
Det andra alternativet är att dölja standardfältet för systemrubriker och ersätta det med ditt eget anpassade innehåll. Du kan till exempel placera text, en sökruta eller anpassade menyer i namnlistområdet. Du måste också använda det här alternativet för att utöka en materialbakgrund , som Mica, till rubrikfältet.
När du väljer fullständig anpassning ansvarar du för att placera innehåll i namnlistområdet och du kan definiera dina egna dragregioner. Undertextkontrollerna (systemknapparna Stäng, Minimera och Maximera) är fortfarande tillgängliga och hanteras av systemet, men element som apprubriken är det inte. Du måste skapa dessa element själv efter behov av din app.
Enkel anpassning
Om du bara vill anpassa namnlistens rubrik, färger eller ikon kan du ange egenskaper för namnlistobjektet för appfönstret.
Title
Som standard visar namnlisten apptypen som fönsterrubrik (till exempel "WinUI Desktop"). Du bör uppdatera fönsterrubriken så att den visar ett beskrivande visningsnamn för din app.
En XAML-app har ett visningsnamn som anges i Package.appxmanifest-filen. Du kan hämta det här värdet och använda det för att ange egenskapen Title så här.
Title = AppInfo.Current.DisplayInfo.DisplayName;
Om du vill ändra fönsterrubriken anger du egenskapen Window.Title till ett textvärde med en rad, som du ser här.
<Window
...
Title="App title">
...
</Window>
public MainWindow()
{
InitializeComponent();
Title = "App title";
}
Om du vill ändra fönsterrubriken med appwindow-API:er anger du egenskapen AppWindow.Title till ett textvärde med en rad, som du ser här. Det här exemplet visar hur du använder interop-API:er för att hämta AppWindow, som behövs för din app inte använder WinUI 3 1.3 eller senare.
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
Om du vill anpassa standardfärgerna i namnlisten eller ändra standardfönsterikonen måste du använda AppWindow-API:erna eller välja att anpassa namnlisten helt.
Det här exemplet visar hur du hämtar en instans av AppWindowTitleBar och anger dess färgegenskaper.
Important
Färganpassning ignoreras när appen körs i 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;
}
Det finns några saker att tänka på när du anger namnlistfärger:
- Knappens bakgrundsfärg tillämpas inte på stängknappens hovring och trycklägen . Knappen Stäng använder alltid den systemdefinierade färgen för dessa tillstånd.
- Om du anger en färgegenskap till
nullåterställs den till standardsystemfärgen. - Du kan inte ange transparenta färger. Färgens alfakanal ignoreras.
Windows ger en användare möjlighet att använda den valda accentfärgen i namnlisten. Om du anger någon namnlistfärg rekommenderar vi att du uttryckligen anger alla färger. Detta säkerställer att det inte finns några oavsiktliga färgkombinationer som inträffar på grund av användardefinierade färginställningar.
Ikon och systemmeny
Du kan dölja systemikonen eller ersätta den med en anpassad ikon. Systemikonen visar systemmenyn när du högerklickar eller knackar en gång. Fönstret stängs när man dubbelklickar eller knackar på det.
Om du vill visa eller dölja systemikonen och tillhörande beteenden anger du egenskapen IconShowOptions i namnlisten.
m_TitleBar.IconShowOptions = IconShowOptions.HideIconAndSystemMenu;
Om du vill använda en anpassad fönsterikon anropar du någon av AppWindow.SetIcon-metoderna för att ange den nya ikonen.
SetIcon(String)Metoden SetIcon(String) fungerar för närvarande bara med .ico filer. Strängen som du skickar till den här metoden är den fullständigt kvalificerade sökvägen till filen .ico.
m_AppWindow.SetIcon("iconPath/iconName.ico");SetIcon(IconId)Om du redan har ett handtag till en ikon (
HICON) från en av ikonfunktionerna som CreateIcon kan du använda Api:et GetIconIdFromIcon interop för att hämta ett IconId. Du kan sedan skickaIconIdtill metoden SetIcon(IconId) för att ange fönsterikonen.m_AppWindow.SetIcon(iconId));
Fullständig anpassning
När du väljer fullständig anpassning av namnlisten utökas appens klientområde så att det täcker hela fönstret, inklusive området med namnlisten. Du ansvarar för ritning och indatahantering för hela fönstret förutom bildtextknapparna, som fortfarande tillhandahålls av fönstret.
Om du vill dölja systemrubrikfältet och utöka innehållet till namnlistområdet ställer du in egenskapen som utökar appinnehållet i namnlistområdet till true. I en XAML-app kan den här egenskapen anges i appens OnLaunched metod (App.xaml.cs) eller på appens första sida.
Tip
Se avsnittet Fullständig anpassning för att se all kod samtidigt.
Det här exemplet visar hur du anger egenskapen Window.ExtendsContentIntoTitleBar till true.
public MainWindow()
{
this.InitializeComponent();
// Hide system title bar.
ExtendsContentIntoTitleBar = true;
}
Caution
ExtendsContentIntoTitleBar visas i XAML IntelliSense för Window, men om du anger det i XAML uppstår ett fel. Ange den här egenskapen i kod i stället.
Det här exemplet visar hur du hämtar egenskapen AppWindowTitleBar och anger egenskapen AppWindowTitleBar.ExtendsContentIntoTitleBar till true. Det här exemplet visar hur du använder interop-API:er för att hämta AppWindow, som behövs om din app inte använder WinUI 3 1.3 eller senare.
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);
}
Innehåll i namnlisten och standarddragregionen
När appen utökas till namnlistområdet ansvarar du för att definiera och hantera användargränssnittet för namnlisten. Det innefattar vanligtvis, åtminstone, rubriktext och draområdet. Dra-regionen i namnlisten definierar var användaren kan klicka och dra för att flytta runt fönstret. Det är också där användaren kan högerklicka för att visa systemmenyn.
Mer information om acceptabelt innehåll i namnlisten och rekommenderade användargränssnittsmönster finns i designen Namnlist.
Det här exemplet visar XAML för ett anpassat användargränssnitt för namnlister utan interaktivt innehåll.
<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 och RightPaddingColumn används för att reservera utrymme för bildtextknapparna. De Width värdena för dessa kolumner anges i kod, som visas senare. Se avsnittet Knappar för systembeskrivning för koden och förklaringen.
En XAML-app har ett visningsnamn som anges i filen Package.appxmanifest. Du kan hämta det här värdet och använda det i din anpassade titellist så här.
TitleBarTextBlock.Text = AppInfo.Current.DisplayInfo.DisplayName;
När du utökar innehållet till området med namnlisten döljs systemrubrikfältet och en standardappWindowTitleBar skapas som innehåller bildtextknappar och en dragregion över skärmens bredd, identisk med systemets namnlist. Om du inte placerar interaktivt innehåll i namnlisten kan du lämna den här standarddragregionen as-is. Om du placerar interaktivt innehåll i namnlisten måste du ange de regioner som är interaktiva, som vi tar upp i nästa avsnitt.
Caution
När du definierar anpassade dragregioner behöver de inte vara överst i fönstret i standardområdet för namnlisten. du kan definiera valfri del av användargränssnittet som en dragregion. Att placera dra regioner på olika platser kan dock göra det svårt för användarna att identifiera dem.
Interaktivt innehåll
Du kan placera interaktiva kontroller, till exempel knappar, menyer eller en sökruta, i den övre delen av appen så att de visas i namnlisten. Du måste dock ange vilka regioner som är interaktiva för att säkerställa att dina interaktiva element tar emot användarindata samtidigt som användarna kan flytta runt fönstret.
När du lägger till interaktivt innehåll i namnlistområdet måste du använda klassen InputNonClientPointerSource för att ange områden där indata skickas till den interaktiva kontrollen i stället för att hanteras av namnlisten. Om du vill ange de interaktiva regionerna anropar du metoden InputNonClientPointerSource.SetRegionRects . Den här metoden tar ett värde som anger vilken typ av region som anges (i det här fallet Passthrough) och en matris med rektanglar, som var och en definierar en Passthrough region. När namnlistens storlek ändras måste du beräkna om de interaktiva regionerna så att de matchar den nya storleken och anropa SetRegionRects med de nya värdena.
Det här exemplet visar ett anpassat användargränssnitt för namnlisten med en sökruta och en PersonPicture-kontokontroll. Den visar hur du beräknar och ställer in interaktiva rektanglar för dessa kontroller så att indata skickas vidare till dem.
Här följer några viktiga punkter att lägga märke till om den här koden:
- Ange rutnätets
AppTitleBarhöjd till 48 för att följa designvägledningen för namnlisten för interaktivt innehåll. - Ange PreferredHeightOption till så att
Tallbildtextknapparna har samma höjd som namnlisten. - Om du vill göra det enklare att ändra storlek på kontroller och beräkna regioner använder du en
Gridmed flera namngivna kolumner för layouten. - Använd stjärnstorleken (*) med
MinWidthför kolumnen som innehållerAutoSuggestBoxså att den automatiskt ändrar storlek med fönstret. - Ställ in
MinWidthpåRightDragColumnför att reservera ett litet område som alltid kan dras även när fönstret ändrar storlek. - Ange
ExtendsContentIntoTitleBartilltruei MainWindow-konstruktorn. Om du anger den i kod som anropas senare kan standardfältet för systemtitel visas först och sedan döljas. - Gör det första anropet för att beräkna interaktiva regioner när
AppTitleBar-elementet har lästs in. Annars finns det ingen garanti för att de element som används för beräkningen har rätt värden. - Uppdatera de interaktiva rektangelberäkningarna först när
AppTitleBar-elementet har ändrat storlek (AppTitleBar_SizeChanged). Om du är beroende av händelsen för fönstretChanged, kommer det att finnas situationer, som när ett fönster maximeras eller minimeras, där händelsen inträffar innanAppTitleBarhar storleksändrats och beräkningarna använder felaktiga värden. - Ställ in dina anpassade drag-/interaktiva områden endast efter att du har kontrollerat
ExtendsContentIntoTitleBarför att bekräfta att en anpassad titellist används.
<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>
Den här koden visar hur du beräknar och anger de interaktiva regioner som motsvarar kontrollerna AutoSuggestBox och 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 använder fysiska pixlar för kompatibilitet med gränssnittsramverk som inte använder logiska koordinater. Om du använder WPF eller WinUI 3 RightInset, LeftInsetoch värdena som används för att beräkna regioner måste justeras om visningsskalan inte är 100%. I det här exemplet får vi ett scaleAdjustment värde för att ta hänsyn till inställningen för visningsskalning.
- För WinUI 3 använder du egenskapen XamlRoot.RasterizationScale för att hämta skalningsjusteringen.
- För WPF kan du hantera händelsen Window.DpiChanged för att hämta NewDpi-värdet och beräkna skalningsjusteringen.
Knappar för systemrubrik
Systemet reserverar det övre vänstra eller övre högra hörnet i appfönstret för knapparna för systembeskrivning (minimera, maximera/återställa, stäng). Systemet behåller kontrollen över knappområdet för bildtexten för att garantera att minsta möjliga funktionalitet tillhandahålls för att dra, minimera, maximera och stänga fönstret. Systemet drar knappen Stäng i det övre högra hörnet för språk från vänster till höger och det övre vänstra för höger-till-vänster-språk.
Du kan rita innehåll under kontrollområdet för bildtext, till exempel din appbakgrund, men du bör inte placera något användargränssnitt som du förväntar dig att användaren ska kunna interagera med. Den tar inte emot några indata eftersom indata för beskrivningskontrollerna hanteras av systemet.
Dessa rader från föregående exempel visar utfyllnadskolumnerna i XAML som definierar namnlisten. Genom att använda utfyllnadskolumner i stället för marginaler ser du till att bakgrunden målar upp området under knapparna för textkontroll (för transparenta knappar). Genom att använda både höger och vänster utfyllnadskolumner ser du till att namnlisten fungerar korrekt i både höger-till-vänster- och vänster-till-höger-layouter.
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
<ColumnDefinition/>
<ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>
Måtten och positionen för kontrollområdet för bildtexten kommuniceras av klassen AppWindowTitleBar så att du kan ta hänsyn till det i layouten för ditt användargränssnitt för namnlisten. Bredden på den reserverade regionen på varje sida anges av egenskaperna LeftInset eller RightInset och dess höjd anges av egenskapen Height .
Så här specificeras bredden på utfyllnadskolumnerna när dragningsregionerna beräknas och definieras.
RightPaddingColumn.Width =
new GridLength(m_AppWindow.TitleBar.RightInset / scaleAdjustment);
LeftPaddingColumn.Width =
new GridLength(m_AppWindow.TitleBar.LeftInset / scaleAdjustment);
Important
Se viktig information i avsnittet Interaktivt innehåll om hur visningsskalning påverkar dessa värden.
Stöd för höga titellister för anpassade titellister
När du lägger till interaktivt innehåll som en sökruta eller personbild i namnlisten rekommenderar vi att du ökar höjden på namnlisten för att ge mer utrymme för dessa element. En högre titelrad gör också pekmanipulering enklare. Egenskapen AppWindowTitleBar.PreferredHeightOption ger dig möjlighet att öka höjden på namnlisten från standardhöjden, som är standard, till en högre höjd. När du väljer Tall titelbarmode återges de knappar som systemet ritar som ett överlägg i klientområdet högre med centrerade min/max/stäng-ikoner. Om du inte har angett en dragregion ritar systemet en som utökar fönstrets bredd och den höjd som bestäms av det PreferredHeightOption värde som du anger.
Det här exemplet visar hur du kan ange egenskapen 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
Egenskapen AppWindowTitleBar.ExtendsContentIntoTitleBar måste vara true innan du anger PreferredHeightOption egenskapen. Om du försöker ange PreferredHeightOption när ExtendsContentIntoTitleBar är falsegenereras ett undantag.
Färg och transparens i bildtextknappar
När du utökar appinnehållet till området med namnlisten kan du göra bakgrunden för bildtextknapparna transparent så att appens bakgrund visas. Du ställer vanligtvis in bakgrunden på Colors.Transparent för fullständig transparens. För partiell transparens anger du alfakanalen för den färg som du anger egenskapen till.
De här egenskaperna för namnlisten kan vara transparenta:
- ButtonBackgroundColor
- ButtonHoverBackgroundColor
- ButtonPressedBackgroundColor
- ButtonInactiveBackgroundColor
Alla andra färgegenskaper fortsätter att ignorera alfakanalen. Om ExtendsContentIntoTitleBar är inställt på falseignoreras alfakanalen alltid för alla AppWindowTitleBar färgegenskaper.
Knappens bakgrundsfärg tillämpas inte på knappen Stäng hovra och tryck på tillstånd. Knappen Stäng använder alltid den systemdefinierade färgen för dessa tillstånd.
Tip
Mica är ett förtjusande material som hjälper till att särskilja fönstret som är i fokus. Vi rekommenderar det som bakgrund för långlivade fönster i Windows 11. Om du har tillämpat Mica i klientområdet i fönstret kan du utöka det till namnlistområdet och göra bildtextknapparna transparenta så att Mica visas. Mer information finns i Mica-material .
Dimma titelraden när fönstret är inaktiv
Du bör göra det uppenbart när fönstret är aktivt eller inaktivt. Du bör åtminstone ändra färgen på texten, ikonerna och knapparna i namnlisten.
För XAML-appar hanterar du händelsen Window.Activated för att fastställa aktiveringstillståndet för fönstret och uppdaterar användargränssnittet för namnlisten efter behov.
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"];
}
}
För andra gränssnittsramverk hanterar du en händelse för att fastställa aktiveringstillståndet för fönstret och uppdaterar användargränssnittet för namnlisten efter behov. Hur du avgör tillståndet för fönstret beror på det användargränssnittsramverk som du använder för din app.
- Win32: Lyssna och svara på meddelandet WM_ACTIVATE .
- WPF: Hantera Window.Activated, Window.Deactivated.
- WinForms: Hantera Form.Activated, Form.Deactivate.
Återställ namnlisten
Om du vill återställa eller växla till systemrubrikfältet medan appen körs kan du anropa AppWindowTitleBar.ResetToDefault.
m_AppWindow.TitleBar.ResetToDefault();
För XAML-appar kan du också återställa namnlisten på följande sätt:
- Anropa SetTitleBar för att växla till ett nytt rubrikfältelement medan appen körs.
- Anropa
SetTitleBarmednullsom parameter för att återställa till standardAppWindowTitleBardragområden. - Anropa
SetTitleBarmednullsom parameter och ställ in ExtendsContentIntoTitleBar för attfalseåtergå till standardfältet för systemrubrik.
Visa och dölj namnlisten
Om du lägger till stöd för helskärmslägen eller kompakta överläggslägen i din app kan du behöva göra ändringar i namnlisten när appen växlar mellan dessa lägen. XAML-fönstret tillhandahåller inga API:er för helskärmsläge. du kan använda AppWindow-API:er för detta.
När appen körs i helskärmsläge döljer systemet knapparna för namnlist och bildtextkontroll. Du kan hantera händelsen AppWindow.Changed och kontrollera egenskapen event args DidPresenterChange för att avgöra om du ska visa, dölja eller ändra namnlisten som svar på en ny fönsterpresentation.
Det här exemplet visar hur du hanterar händelsen Changed för att visa och dölja elementet AppTitleBar från tidigare exempel. Om fönstret försätts i kompakt överläggsläge återställs namnlisten till standardfältet för systemrubrik (eller så kan du ange ett anpassat namnlist som är optimerat för kompakt överlägg).
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
Helskärmslägen och kompakta överläggslägen kan endast anges om det stöds av din app. Mer information finns i Hantera appfönster, FullScreenPresenteroch CompactOverlayPresenter.
Vad man ska göra och inte göra
- Gör det uppenbart när ditt fönster är aktivt eller inaktivt. Ändra åtminstone färgen på texten, ikonerna och knapparna i namnlisten.
- Definiera en dragregion längs apparbetsytans övre kant. Genom att matcha placeringen av systemrubrikstaplar blir det enklare för användarna att hitta dem.
- Definiera en dragregion som matchar den visuella titelraden (om det finns någon) på appens arbetsyta.
Fullständigt anpassningsexempel
I de här exemplen visas all kod som beskrivs i avsnittet Fullständig anpassning.
<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);
}
}
}
}
Relaterade artiklar
Windows developer