.net - Windows 10 桌面应用程序上的自定义标题栏颜色

标签 .net wpf winforms windows-10 windows-10-desktop

我有一个在 Windows 10 上运行的混合 WinForms/WPF 桌面应用程序,该应用程序仍然面向 .NET 3.5。它有白天模式、黄昏模式和夜间模式。在夜间模式下,所有内容基本上都是黑底红字,但标题栏仍然默认为白色。

在“设置”>“个性化”>“颜色”>“在以下表面上显示强调色”中,您可以选中“标题栏”并获取要用于标题栏的强调色,然后选择深色。但是,并非所有用户都知道此设置。

是否有一种简单的方法可以以编程方式更改从应用程序创建的所有窗口的标题栏背景和前景色?如果需要,我可以使用 p/Invoke。

如果没有,我也会接受一种以编程方式全局更改标题栏颜色(系统上的所有 Windows)的方法,甚至可以提供自动选中该框(标题栏上的强调色)并设置深色的方法强调色。

--

编辑:无需设置 WindowStyle="None"并自定义实现标题栏就可以完成吗?这就是我已经(厌倦了)做的事情。

最佳答案

在 WPF(我假设是 WinForms)中,创建无边框窗口并自己创建标题栏会更容易。这是执行此操作的 WPF 代码,,,

首先是 C#:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();            
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void Notify(params string[] PropertyNames)
    {
        foreach (string PropertyName in PropertyNames)
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }

    public Visibility CanMaximize { get { return WindowState == WindowState.Normal ? Visibility.Visible : Visibility.Collapsed;  } }
    public Visibility CanRestore { get { return WindowState == WindowState.Maximized ? Visibility.Visible : Visibility.Collapsed; } }

    private void CloseWindow(object sender, ExecutedRoutedEventArgs e)
    {
        Application.Current.Shutdown();
    }

    private void CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;            
    }

    private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
    {
        this.WindowState = WindowState.Minimized;            
    }

    private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
    {
        this.WindowState = WindowState.Maximized;
        Notify("CanMaximize", "CanRestore");
    }

    private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
    {
        this.WindowState = WindowState.Normal;
        Notify("CanMaximize", "CanRestore");
    }

    private void TitleBar_MouseMove(object sender, MouseEventArgs e)
    {
        if (Mouse.LeftButton == MouseButtonState.Pressed)            
        {
            if (TitleBar.IsMouseDirectlyOver)
                DragMove();
        }
    }

}

现在是 XAML:

<Window x:Class="WpfApp1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="Segoe UI Symbol" 
    mc:Ignorable="d" x:Name="root"
    Title="MainWindow" Height="450" Width="800" WindowStyle="None">
<Window.CommandBindings>
    <CommandBinding Command="SystemCommands.CloseWindowCommand" Executed="CloseWindow" CanExecute="CanExecute" />
    <CommandBinding Command="SystemCommands.MinimizeWindowCommand" Executed="MinimizeWindow"  CanExecute="CanExecute" />
    <CommandBinding Command="SystemCommands.MaximizeWindowCommand" Executed="MaximizeWindow"  CanExecute="CanExecute" />
    <CommandBinding Command="SystemCommands.RestoreWindowCommand" Executed="RestoreWindow"  CanExecute="CanExecute" />
</Window.CommandBindings>
<DockPanel>
    <DockPanel DockPanel.Dock="Top" Background="#FF000020" x:Name="TitleBar" MouseMove="TitleBar_MouseMove">
        <Image DockPanel.Dock="Left" Source="{Binding ElementName=root, Path=Icon}" Stretch="Uniform" Height="25" Width="25" Margin="2,0"/>
        <Button Command="SystemCommands.CloseWindowCommand" DockPanel.Dock="Right" Margin="0" Padding="0">
            <Grid Width="25" Height="25" Background="{Binding ElementName=TitleBar, Path=Background}">
                <TextBlock  Text="&#xE10A;" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
            </Grid>
        </Button>
        <Button Command="SystemCommands.RestoreWindowCommand" DockPanel.Dock="Right" Visibility="{Binding ElementName=root, Path=CanRestore}">
            <Grid Width="25" Height="25" Background="{Binding ElementName=TitleBar, Path=Background}">
                <TextBlock  Text="&#xE158;" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
            </Grid>
        </Button>
        <Button Command="SystemCommands.MaximizeWindowCommand" DockPanel.Dock="Right" Visibility="{Binding ElementName=root, Path=CanMaximize}">
            <Grid Width="25" Height="25" Background="{Binding ElementName=TitleBar, Path=Background}">
                <TextBlock  Text="&#x10c3f;" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
            </Grid>
        </Button>
        <Button Command="SystemCommands.MinimizeWindowCommand" DockPanel.Dock="Right">
            <Grid Width="25" Height="25" Background="{Binding ElementName=TitleBar, Path=Background}">
                <TextBlock  Text="&#xE108;" HorizontalAlignment="Center" VerticalAlignment="Bottom" Foreground="White" />
            </Grid>
        </Button>
        <TextBlock Text="{Binding ElementName=root, Path=Title, FallbackValue='Application Title'}" Foreground="White" VerticalAlignment="Center"/>
    </DockPanel>
    <Grid>
        <TextBlock Text="Content goes here." VerticalAlignment="Center" HorizontalAlignment="Center"/>
    </Grid>
</DockPanel>

关于.net - Windows 10 桌面应用程序上的自定义标题栏颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51252376/

相关文章:

c# - 尝试在 Visual Studio (C#) 中添加引用,但没有选项卡

c# - MVC : How to manage slahses in URL int the first route parameter

c# - 使用 WM_SETTEXT 设置记事本文本不会影响记事本实例中的 Text_Changed 事件

.net - 签名工具错误 : Access is denied

c# - 仅在 XAML 中将装饰器放置在数据模板上?

c# - 禁用 WPF DataGrid 上的行编辑

c# - Paypal 付款处理

c# - 使用 WPF 和 XAML 以及数据绑定(bind)查看设计 View 中的 UI 更改?

c# - DateTimePicker 更改值不会触发值更改事件 - Winforms

VB.NET datagridview 与组合框的一对一映射