无边框窗口不能正确最大化

7

好的,我已经花了几个小时在Google上搜寻,似乎找不到解决我的问题的直接答案。我有一个自定义窗口,WindowStyle = "None"AllowsTransparency = "True" 当我点击最大化按钮时:

    private void MaximizeButton_Click(object sender, RoutedEventArgs e)
    {
        if(this.WindowState == WindowState.Normal)
        {

            App.Current.MainWindow.WindowState = WindowState.Maximized;
        }
        else
        {
            App.Current.MainWindow.WindowState = WindowState.Normal;
        }
    }

它的最大化功能基本正常,除了窗口的顶部和左侧似乎有一个-6px的边距。
以下是它的外观:enter image description here 我不希望出现白色空间(它是白色的只因为 Google Chrome 在其后面打开,实际上是透明的)。我需要应用程序最大化以适应整个屏幕,不包括任务栏。到目前为止,我唯一发现的解决方法是在按下最大化按钮时设置窗口的边距为Margin = "6, 6, 0, 0"。这是其他相关代码:
<Window x:Class="Expense_Calculator.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"
    xmlns:local="clr-namespace:Expense_Calculator"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525"
    WindowStartupLocation="CenterScreen"
    WindowStyle="None"
    AllowsTransparency="True">
<Grid Name="Container" Background="#323232">
    <Grid.RowDefinitions>
        <RowDefinition Height="33"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid>
        <DockPanel Style="{StaticResource TitleDockPanel}">
            <Label Style="{StaticResource TitleBarTitle}">App Name</Label>
            <Button Name="CloseButton" Click="CloseButton_Click" DockPanel.Dock="Right" Style="{StaticResource TitleBarButtonClose}">
                <Image Source="images/close.png"/>
            </Button>
            <Button Name="MaximizeButton" Click="MaximizeButton_Click" DockPanel.Dock="Right" Style="{StaticResource TitleBarButton}">
                <Image Source="images/maximize.png"/>
            </Button>
            <Button Name="MinimizeButton" Click="MinimizeButton_Click" DockPanel.Dock="Right" Style="{StaticResource TitleBarButton}">
                <Image Source="images/minimize.png"/>
            </Button>
        </DockPanel>
    </Grid>
    <Grid Style="{StaticResource UserArea}" Grid.Row="1">
        <Grid Name="WelcomePage">
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Label Style="{StaticResource Label1}">Welcome to your Expense Calculator!</Label>
            <Button Cursor="Hand" Style="{StaticResource Button1}" Grid.Row="1">Get Started</Button>
        </Grid>
    </Grid>
</Grid>

StartUp.xaml.cs

using System.Windows;

namespace Expense_Calculator
{
    /// <summary>
    /// Interaction logic for StartUp.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.MaxHeight = SystemParameters.WorkArea.Height;
            this.MaxWidth = SystemParameters.WorkArea.Width;
            InitializeComponent();
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        private void MaximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if(this.WindowState == WindowState.Normal)
            {
                App.Current.MainWindow.WindowState = WindowState.Maximized;
            }
            else
            {
                App.Current.MainWindow.WindowState = WindowState.Normal;
            }
        }

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

App.xaml

<Application x:Class="Expense_Calculator.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:Expense_Calculator"
         StartupUri="StartUp.xaml">
<Application.Resources>

    <!--Title Bar-->
    <Style x:Key="TitleDockPanel" TargetType="DockPanel">
        <Setter Property="VerticalAlignment" Value="Top"/>
        <Setter Property="Background" Value="#323232"/>
        <Setter Property="Height" Value="33"/>
    </Style>
    <Style x:Key="TitleBarTitle" TargetType="Label">
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="FontSize" Value="13"/>
        <Setter Property="FontWeight" Value="DemiBold"/>
        <Setter Property="Padding" Value="10, 0"/>
    </Style>
    <Style x:Key="TitleBarButton" TargetType="Button">
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="HorizontalAlignment" Value="Right"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border x:Name="border" Background="#323232" Height="33" Width="33">
                        <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Width="15" Height="15"></ContentPresenter>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="0:0:.1"/>
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color" To="#464646" Duration="0"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color" To="#3774FF" Duration="0"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="TitleBarButtonClose" TargetType="Button">
        <Setter Property="Cursor" Value="Hand"/>
        <Setter Property="HorizontalAlignment" Value="Right"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border x:Name="border" Background="#323232" Height="33" Width="33">
                        <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" Width="15" Height="15"></ContentPresenter>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="0:0:.1"/>
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color" To="Firebrick" Duration="0"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color" To="#781414" Duration="0"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <!--End - Title Bar-->

    <!--Welcome Page-->
    <Style x:Key="UserArea" TargetType="Grid">
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
    </Style>
    <Style x:Key="Label1" TargetType="Label">
        <Setter Property="FontSize" Value="20"/>
        <Setter Property="Foreground" Value="White"/>
        <Setter Property="Margin" Value="0, 0, 0, 25"/>
    </Style>
    <Style x:Key="Button1" TargetType="Button">
        <Setter Property="Width" Value="Auto"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="HorizontalAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border x:Name="border" Background="#323232" CornerRadius="16" BorderBrush="#505050" BorderThickness="1" Padding="15, 6">
                        <ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center">
                            <TextBlock.Foreground>
                                <SolidColorBrush Color="#7D7D7D"/>
                            </TextBlock.Foreground>
                            <TextBlock.FontSize>14</TextBlock.FontSize>
                        </ContentPresenter>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="0:0:0.15"/>
                                </VisualStateGroup.Transitions>
                                <VisualState x:Name="Normal"/>
                                <VisualState x:Name="MouseOver">
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color" To="#3C3C3C" Duration="0"/>
                                        <ColorAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(TextBlock.Foreground).Color" To="White" Duration="0"/>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="BorderBrush.Color" To="#C8C8C8" Duration="0"/>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="Background.Color" To="#282828" Duration="0"/>
                                        <ColorAnimation Storyboard.TargetName="content" Storyboard.TargetProperty="(TextBlock.Foreground).Color" To="White" Duration="0"/>
                                        <ColorAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="BorderBrush.Color" To="#C8C8C8" Duration="0"/>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="border" Property="Opacity" Value=".25"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <!--End - Welcome Page-->
</Application.Resources>
</Application>

尝试从构造函数中移除 this.MaxHeight = SystemParameters.WorkArea.Height 和 this.MaxWidth = SystemParameters.WorkArea.Width;。 - Evk
当我这样做时,应用程序会最大化以适应整个屏幕。因此它覆盖了任务栏。虽然它确实消除了所有的白色空间,但它似乎也重叠了侧面,你可以在这里看到:[http://imgur.com/1HDswCV] - Benjamen Kuhman
5个回答

7

我之前也遇到过同样的问题,但是通过关闭窗口大小调整功能解决了它。可以使用以下代码:

Me.ResizeMode = ResizeMode.NoResize 

在将窗口状态更改为最大化时,问题已解决。

谢谢你! 另外,如果你覆盖了事件,你可以在恢复窗口大小时将其改回来。 - Avius

6
按设计(为什么,我不知道),当您将WindowStyle="None"并将窗口最大化时,它将超出屏幕实际边缘几个像素。

在您的代码中,您将窗口的实际大小限制为工作区的确切尺寸。由于窗口的最大化仍将窗口的左上角放置在工作区的左上角左侧和上方的那些几个像素处,因此窗口的可见部分必然小于工作区的整个宽度,因此右侧和底部会暴露出来。

正如评论者Evk所指出的,通过删除窗口上的大小限制(如果您喜欢,只能在窗口最大化时这样做),窗口可以扩展到WPF想要的完整尺寸,从而确保完全覆盖工作区。

在您的后续评论中,不清楚您是否真的希望任务栏被覆盖。在任一情况下,您可能会发现以下链接对解决相关特定需求有用:
最大化窗口与WindowState问题(应用程序将隐藏窗口任务栏)
最大化窗口(使用WindowStyle = None)考虑任务栏

或者,您仍然可以设置大小限制,但考虑WPF在窗口最大化时坚持的额外像素边距,设置尺寸比所需的大,以便没有暴露的区域。

值得一提的是,这里有一个简化的代码示例,专注于此处的特定行为:

<Window x:Class="TestSO39578992MaximizeBorderless.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:p="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"
        xmlns:local="clr-namespace:TestSO39578992MaximizeBorderless"
        mc:Ignorable="d" Background="Yellow" 
        WindowStyle="None" AllowsTransparency="True"
        Title="MainWindow" Height="350" Width="525">
  <Window.Style>
    <p:Style TargetType="Window">
      <Setter Property="WindowState" Value="Normal"/>
      <!-- Uncomment "Topmost" setters to experiment with its effect on the task bar visibility -->
      <!--<Setter Property="Topmost" Value="False"/>-->
      <p:Style.Triggers>
        <DataTrigger Binding="{Binding IsChecked, ElementName=checkBox1}" Value="True">
          <Setter Property="WindowState" Value="Maximized"/>
          <!--<Setter Property="Topmost" Value="True"/>-->
        </DataTrigger>
      </p:Style.Triggers>
    </p:Style>
  </Window.Style>
  <!-- set the margin here, to account for the extra space WPF is adding -->
  <!-- <Grid Margin="6"> -->
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition/>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <CheckBox x:Name="checkBox1" Content="Maximized" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <TextBlock Text="Upper Right" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top"/>
    <TextBlock Text="Lower Left" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
    <TextBlock Text="Lower Right" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Bottom" Grid.Column="1"/>
  </Grid>
</Window>

当然,还有:
public partial class MainWindow : Window
{
    public MainWindow()
    {
        this.MaxHeight = SystemParameters.WorkArea.Height;
        this.MaxWidth = SystemParameters.WorkArea.Width;

        // Compensate for the extra space WPF adds by increasing the max width and height here
        //this.MaxHeight = SystemParameters.WorkArea.Height + 12;
        //this.MaxWidth = SystemParameters.WorkArea.Width + 12;

        InitializeComponent();
    }
}

我在四个角落都加入了TextBlock元素,以便更容易看到窗口大小受各种属性值影响的情况。


我不是很理解你的第二个链接,主要是因为我不知道如何使用它。但是当我使用你的代码时,结果还是一样的。每当我使用this.MaxHeight = SystemParameters.WorkArea.Height + 6;(宽度也是同样)时,它确实覆盖了整个屏幕。但工作区仍然似乎没有居中。顶部和左侧仍然被切掉了。它似乎只是将工作区向上和向左移动了6像素。此外,我正在尝试不覆盖任务栏。 - Benjamen Kuhman
需要明确的是:我上面的代码不是解决方案,只是一种在没有原始示例中的所有额外内容的情况下重现问题的方法。请注意,除了通过添加补偿来设置最大高度和宽度以使窗口更大之外,您还需要为窗口的内容元素设置“Margin”,以便窗口内容布局本身也考虑到WPF添加的额外边距。我将编辑代码示例并添加注释行以显示我的意思。 - Peter Duniho
好的,我理解错了你的回答。非常感谢你详细的解答。这确实解决了我的问题,所以我会接受你的答案。谢谢;) - Benjamen Kuhman
好的,这些是我使用过并且有效的值: this.MaxHeight = SystemParameters.WorkArea.Height + 7; this.MaxWidth = SystemParameters.WorkArea.Width + 12;Container.Margin = new Thickness(6, 6, 5, 0); <- 这是网格边距。我不明白为什么它有效。 - Benjamen Kuhman
Container 网格对象设置边距会告诉 WPF 需要在网格对象周围指定空间(例如,在您的示例中,左侧和顶部各 6 像素,右侧 5 像素,底部 0 像素)。这反过来迫使网格大小足够小,以便在窗口中容纳它,并在窗口外缘之间留出一定的空间。 - Peter Duniho
根据其他解决方案,这可能是为了防止用户意外调整窗口大小。奇怪的解决方法。 - Avius

1
这是另一种解决它的简单方法:

private void Window_StateChanged(object sender, EventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
            {
                this.BorderThickness = new Thickness(8);
            }
            else
            {
                this.BorderThickness = new Thickness(0);
            }
        }

0
这个可以实现,将其添加到主视图的构造函数中,并在 WindowState 更改时创建一个事件。
    private void UpdateMarginOnWindowState()
    {
        if (this.WindowState == WindowState.Maximized)
        {
            this.MainContainer.Margin = new Thickness(6);
            return;
        }

        this.MainContainer.Margin = new Thickness(0);
    }

0

检查后,我为我的窗口添加了最大尺寸限制

MaxWidth="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}"
MaxHeight="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}"

然后,对于被触发最大化的函数,我像Glen Howard所说的那样关闭了CanResize。

    private void Maximize()
    {
        if (App.Current.MainWindow.WindowState == WindowState.Normal)
        {
            App.Current.MainWindow.ResizeMode = ResizeMode.NoResize;
            MaximizeButton.Style = (Style)App.Current.Resources["RestoreButton"];
            App.Current.MainWindow.WindowState = WindowState.Maximized;
        }
        else
        {
            App.Current.MainWindow.ResizeMode = ResizeMode.CanResize;
            MaximizeButton.Style = (Style)App.Current.Resources["MaximizeButton"];
            App.Current.MainWindow.WindowState = WindowState.Normal;
        }
    }

(风格)App.Current.Resources["RestoreButton"] 会改变我的按钮图标,如果你不想实现它,就不要看它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接