首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在.net Avalonia中更容易改变窗口系统顶栏的背景颜色?

在.net Avalonia中更容易改变窗口系统顶栏的背景颜色?
EN

Stack Overflow用户
提问于 2020-12-17 08:23:10
回答 1查看 1.6K关注 0票数 1

在dotnet的Avalonia-UI框架中。我使用的是一个深色的用户界面,我设法按照this example把所有的东西都变暗了,但有一件事是这样的: Windows操作系统的系统顶栏。

我在this issue in github中看到,我可以设置属性HasSystemDecorations="false"使其消失,但随后我必须实现自己的顶部栏,并使用拖动功能、标题、关闭、最大化、最小化等,当我只想要更改背景颜色时,这是一件痛苦的事情。

将窗口顶部栏更改为深色背景色更简单的方法是什么?

如果唯一的方法是使用HasSystemDecorations,那么实现带有关闭/最小化/最大化/拖动的常见功能的深色顶部栏的最小示例是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-19 17:15:25

是的,你必须设置HasSystemDecorations="false"并实现你自己的标题栏。我在Github上有一个基本的模板,告诉你如何使用0.10版本和流畅的主题来做这件事。

这实际上非常简单,因为Avalonia提供了许多方便的方法来实现这一点。

概述:

设置

代码语言:javascript
运行
复制
ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaTitleBarHeightHint="-1"

然后实现一个标题栏。例如,close按钮可能如下所示:

代码语言:javascript
运行
复制
<Button Width="46"
        VerticalAlignment="Stretch"
        BorderThickness="0"
        Name="CloseButton"
        ToolTip.Tip="Close">
    <Button.Resources>
      <CornerRadius x:Key="ControlCornerRadius">0</CornerRadius>
    </Button.Resources>
    <Button.Styles>
      <Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
        <Setter Property="Background" Value="Red"/>
      </Style>
      <Style Selector="Button:not(:pointerover) /template/ ContentPresenter#PART_ContentPresenter">
        <Setter Property="Background" Value="Transparent"/>
      </Style>
      <Style Selector="Button:pointerover > Path">
        <Setter Property="Fill" Value="White"/>
      </Style>
      <Style Selector="Button:not(:pointerover) > Path">
        <Setter Property="Fill" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/>
      </Style>
    </Button.Styles>
    <Path Margin="10,0,10,0"
          Stretch="Uniform"
          Data="M1169 1024l879 -879l-145 -145l-879 879l-879 -879l-145 145l879 879l-879 879l145 145l879 -879l879 879l145 -145z"></Path>
  </Button>

如果在控件上设置了IsHitTestVisible="False",则可以在该区域中拖动下面的窗口。因此,将整个标题栏包装在例如DockPanel中:

代码语言:javascript
运行
复制
<DockPanel Background="Black"
           IsHitTestVisible="False"
           Name="TitleBarBackground"></DockPanel>

现在,您显然仍然需要模仿按钮的行为。这在原则上可以这样做(同样,对于具体的示例,请查看上面的Github存储库):

代码语言:javascript
运行
复制
minimizeButton = this.FindControl<Button>("MinimizeButton");
maximizeButton = this.FindControl<Button>("MaximizeButton");
maximizeIcon = this.FindControl<Path>("MaximizeIcon");
maximizeToolTip = this.FindControl<ToolTip>("MaximizeToolTip");
closeButton = this.FindControl<Button>("CloseButton");
windowIcon = this.FindControl<Image>("WindowIcon");

minimizeButton.Click += MinimizeWindow;
maximizeButton.Click += MaximizeWindow;
closeButton.Click += CloseWindow;
windowIcon.DoubleTapped += CloseWindow;

private void CloseWindow(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
      Window hostWindow = (Window)this.VisualRoot;
      hostWindow.Close();
}

private void MaximizeWindow(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
     Window hostWindow = (Window)this.VisualRoot;

     if (hostWindow.WindowState == WindowState.Normal)
     {
           hostWindow.WindowState = WindowState.Maximized;
     }
     else
     {
           hostWindow.WindowState = WindowState.Normal;
     }
}

private void MinimizeWindow(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
      Window hostWindow = (Window)this.VisualRoot;
      hostWindow.WindowState = WindowState.Minimized;
}

现在,最后一步是您需要根据窗口状态更改最大化按钮的图标。例如,如果您拖动最大化的窗口,它将自动向下恢复,并且最大化按钮的图标需要更改。因此,您需要订阅主机窗口的窗口状态,这可以像这样完成:

代码语言:javascript
运行
复制
private async void SubscribeToWindowState()
{
        Window hostWindow = (Window)this.VisualRoot;

        while (hostWindow == null)
        {
            hostWindow = (Window)this.VisualRoot;
            await Task.Delay(50);
        }

        hostWindow.GetObservable(Window.WindowStateProperty).Subscribe(s =>
        {
            if (s != WindowState.Maximized)
            {
                maximizeIcon.Data = Avalonia.Media.Geometry.Parse("M2048 2048v-2048h-2048v2048h2048zM1843 1843h-1638v-1638h1638v1638z");
                hostWindow.Padding = new Thickness(0,0,0,0);
                maximizeToolTip.Content = "Maximize";
            }
            if (s == WindowState.Maximized)
            {
                maximizeIcon.Data = Avalonia.Media.Geometry.Parse("M2048 1638h-410v410h-1638v-1638h410v-410h1638v1638zm-614-1024h-1229v1229h1229v-1229zm409-409h-1229v205h1024v1024h205v-1229z");
                hostWindow.Padding = new Thickness(7,7,7,7);
                maximizeToolTip.Content = "Restore Down";
            }
        });
    }

实际上,在上面的代码片段中,还有一个细节需要注意。至少在windows上,最大化的窗口实际上比屏幕要大。如果你不想让你的内容超出屏幕的边界,你需要在窗口内的主控件上添加一个边距。因此,hostWindowPadding会相应地改变。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65333019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档