四、WinUI3下TitleBar的自定义

WinUI3下TitleBar的自定义

对于Windows软件开发者来说重写标题栏样式是一个很重要的事情,在WPF阶段很多人写出来性能很差的窗口,而且为了适配Win11系统的Snaplayout后性能就更差了,这篇是写WinUI3下提供的重写TitleBar的方式;

1、修改文本

public MainWindow()
{
    this.InitializeComponent();
    Title = "Duwenlong learn App Title";
}

可以修改默认标题栏显示文本;但是无法自定义其他内容;所有操作都请在InitializeComponent方法后执行,不然会报错;

public MainWindow()
{
    this.InitializeComponent();

    // Hide default title bar.
    ExtendsContentIntoTitleBar = true;
}

修改后我们有完整的区域用看显示内容,只是目前还比较丑而且标题栏部分不支持拖动;

2、完全自定义

通过调用 Window.SetTitleBar 方法并传入定义拖动区域的 UIElement 来指定拖动区域。

1、标题栏内容和拖动区域

代码如下:

<Window
    x:Class="TitleBarCustomizationDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TitleBarCustomizationDemo"
    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 Height="*"/>
        </Grid.RowDefinitions>
        <Grid x:Name="AppTitleBar"> 
            <TextBlock x:Name="AppTitleTextBlock" Text="Duwenlong learn Now App Title"
               TextWrapping="NoWrap"
               Style="{StaticResource CaptionTextBlockStyle}" 
               VerticalAlignment="Center"
               Margin="28,6,0,6"/>
        </Grid>
    </Grid> 
</Window> 
public MainWindow()
{
    this.InitializeComponent(); 
    ExtendsContentIntoTitleBar = true;
    SetTitleBar(AppTitleBar);
} 

2、交互式内容

我们可以放置一些不影响用户的交互式按钮
使用XAML的嵌套语法尝试放置一些内容,我放置了一个textblock,用于在标题栏显示一个消息;

<Window
    x:Class="TitleBarCustomizationDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TitleBarCustomizationDemo"
    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 Height="*"/>
        </Grid.RowDefinitions>
        <Grid x:Name="AppTitleBar" >
            <TextBlock x:Name="AppTitleTextBlock" Text="Duwenlong learn Now App Title"
               TextWrapping="NoWrap" Margin="28,6,0,6"
               Style="{StaticResource CaptionTextBlockStyle}" 
               VerticalAlignment="Center"
               />
            <TextBlock  Margin="28,6,0,6" Text="1 problem to be fixed" Width="220"/>
        </Grid>
    </Grid> 
</Window>

4、系统标题按钮的颜色和透明度

将应用内容扩展到标题栏区域时,可以使标题按钮的背景透明,我默认设置了WindowCaptionBackground为透明色

 <Application
    x:Class="TitleBarCustomizationDemo.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TitleBarCustomizationDemo">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
                <!-- Other merged dictionaries here -->
            </ResourceDictionary.MergedDictionaries>
            <!-- Other app resources here -->
            <SolidColorBrush x:Key="WindowCaptionBackground">Transparent</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionBackgroundDisabled">LightGreen</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionForeground">Red</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionForegroundDisabled">Pink</SolidColorBrush> 
        </ResourceDictionary>
    </Application.Resources>
</Application> 

5、当窗口处于非活动状态时,调暗标题栏

<Application
    x:Class="TitleBarCustomizationDemo.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TitleBarCustomizationDemo">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
                <!-- Other merged dictionaries here -->
            </ResourceDictionary.MergedDictionaries>
            <!-- Other app resources here -->
            <!-- <SolidColorBrush x:Key="WindowCaptionBackground">Transparent</SolidColorBrush> -->
            <SolidColorBrush x:Key="WindowCaptionBackground">Green</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionBackgroundDisabled">LightGreen</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionForeground">Red</SolidColorBrush>
            <SolidColorBrush x:Key="WindowCaptionForegroundDisabled">Pink</SolidColorBrush> 
        </ResourceDictionary>
    </Application.Resources>
</Application>

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace TitleBarCustomizationDemo
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.InitializeComponent(); 
            ExtendsContentIntoTitleBar = true;
            SetTitleBar(AppTitleBar);
            Activated += MainWindow_Activated;
        }

        private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
        {
            if (args.WindowActivationState == WindowActivationState.Deactivated)
            {
                AppTitleTextBlock.Foreground =
                    (SolidColorBrush)App.Current.Resources["WindowCaptionForegroundDisabled"];
            }
            else
            {
                AppTitleTextBlock.Foreground =
                    (SolidColorBrush)App.Current.Resources["WindowCaptionForeground"];
            }
        }
    }
} 

6、重置标题栏

可以在应用运行时调用 SetTitleBar 切换到新的标题栏元素。或者恢复为默认;

<Window
    x:Class="TitleBarCustomizationDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TitleBarCustomizationDemo"
    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 Height="*"/>
        </Grid.RowDefinitions>
        <Grid x:Name="AppTitleBar" > 
            <TextBlock x:Name="AppTitleTextBlock" Text="Duwenlong learn Now App Title"
               TextWrapping="NoWrap" Margin="28,6,0,6" 
               Style="{StaticResource CaptionTextBlockStyle}" 
               VerticalAlignment="Center"
               />
            <TextBlock  Margin="28,6,0,6" Text="1 problem to be fixed" Width="220"/>
        </Grid>
        <Button Grid.Row="1" Content="Click Me" Click="Button_Click"/>
    </Grid> 
</Window>

private void Button_Click(object sender, RoutedEventArgs e)
{ 
    SetTitleBar(null);
    ExtendsContentIntoTitleBar = false;
}

因为使用的是Win10机器,图床又挂了所以不贴图了,Win11下会很好看。

posted @ 2022-10-16 23:51  杜文龙  阅读(1075)  评论(0编辑  收藏  举报