Настраиваемый цвет строки заголовка в настольном приложении Windows 10

У меня есть гибридное настольное приложение WinForms / WPF, работающее в Windows 10, которое по-прежнему ориентировано на .NET 3.5. У него есть дневной режим, сумеречный режим и ночной режим. В ночном режиме все в основном становится красным на черном, но строки заголовка по-прежнему белые.

В меню «Настройки»> «Персонализация»> «Цвета»> «Показывать акцентный цвет на следующих поверхностях» вы можете установить флажок «Строки заголовка» и выбрать основной цвет, который будет использоваться для строк заголовка, а затем выбрать темный цвет. Однако не все наши пользователи знают об этой настройке.

Есть ли простой способ программно изменить цвет фона и цвета переднего плана строки заголовка для всех окон, созданных из приложения? Если нужно, я могу использовать p / Invoke.

Если нет, я бы также принял способ программно изменить цвета строки заголовка глобально (для всех Windows в системе) или даже что-то, что могло бы предложить автоматически установить этот флажок (цвет акцента на строках заголовка) и установить темный цвет акцента.

--

Изменить: можно ли это сделать, не устанавливая WindowStyle = "None" и настраивая панели заголовков? Это то, чем я (устал) уже занимаюсь.


person Jason    schedule 09.07.2018    source источник


Ответы (1)


В 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>

person Stephen Lee Parker    schedule 09.07.2018
comment
Это (WindowStyle = None) действительно работает, и это то, что мы уже делаем для многих наших окон. Сложно добиться, чтобы все детали (внешний вид и поведение) точно соответствовали системным строкам заголовка. И везде, где мы используем MessageBox.Show, по-прежнему имеет границу и заголовок Windows. Тем не менее, ваш пример выглядит обстоятельно. - person Jason; 10.07.2018
comment
После публикации ответа он мне так понравился, что я создал шаблон проекта и добавил некоторые свойства зависимостей, чтобы облегчить себе жизнь. Мне нравится, что это дает мне контроль над всеми кнопками, и я также добавил кнопку справки. Итак, я рад, что вы задали вопрос, хотя он у вас не сработал, он побудил меня задуматься над проблемой и найти решение для себя. - person Stephen Lee Parker; 10.07.2018
comment
Привет - нет, спасибо, ваш ответ правильный и работает хорошо. Мне просто было интересно, единственный ли это вариант. Даже Office и Visual Studio, кажется, настраивают свою строку заголовка. - person Jason; 10.07.2018