WPF 无边框窗口问题:Aero Snap 和最大化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13422666/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 06:15:21  来源:igfitidea点击:

WPF Borderless Window issues: Aero Snap & Maximizing

c#wpfaerowndproc

提问by Chronicide

I've created a borderless WPF window by setting the following window properties in XAML:

我通过在 XAML 中设置以下窗口属性创建了一个无边框 WPF 窗口:

... WindowStyle="None" AllowsTransparency="True" ...

This causes a number of issues:

这会导致许多问题:

1) Resolved:It no longer has any built-in resize functionality

1) 已解决:它不再具有任何内置的调整大小功能

2) Resolved:It no longer has any built-in drag functionality

2)已解决:它不再具有任何内置拖动功能

3) Resolved:Without the top toolbar, it no longer has minimize/maximize/restore/close buttons

3) 已解决:没有顶部工具栏,它不再有最小化/最大化/恢复/关闭按钮

4) Resolved:Maximizing via aero snap or setting WindowState prevents it from unsnapping.

4) 已解决:通过 aero snap 最大化或设置 WindowState 可防止其取消捕捉。

5)Maximizing via aero snap or setting WindowState will use the whole screen as the boundary, overlapping the windows toolbar.

5)通过aero snap 最大化或设置WindowState 将使用整个屏幕作为边界,与windows 工具栏重叠。

6)Maximizing via aero snap or setting WindowState seems to include a -7 margin, giving the window 7 pixels on each side that are beyond the edges of the window.

6)通过 aero snap 最大化或设置 WindowState 似乎包括 -7 边距,使窗口在超出窗口边缘的每侧有 7 个像素。

1-3 were solved by making a xaml window template. I used invisible rectangles as handle regions, and some code behind that was applied via overriding OnApplyTemplate() to attach functionality via user32.dll SendMessage(...) for resize/move/minimize/maximize/restore/close.

1-3通过制作xaml窗口模板解决。我使用了不可见的矩形作为句柄区域,并通过覆盖 OnApplyTemplate() 应用了一些后面的代码,以通过 user32.dll SendMessage(...) 附加功能,用于调整大小/移动/最小化/最大化/恢复/关闭。

I found the answer to # 4 here

我在这里找到了 #4 的答案

I tried solving 5-6 by intercepting the maximize message via WndProc and setting the size/position manually, but this had the issue of overwriting the RestoreRegion to the maximized size/position, removing the ability to restore the window.

我尝试通过通过 WndProc 拦截最大化消息并手动设置大小/位置来解决 5-6,但这存在将 RestoreRegion 覆盖为最大化大小/位置的问题,从而消除了恢复窗口的能力。

What's really odd is that resizing the window from the top border to the top of the screen triggers the aero full height snap just fine, with no issues at all.

真正奇怪的是,将窗口大小从顶部边框调整到屏幕顶部会触发气动全高捕捉,完全没有问题。

So, I've come a long way, but 5-6 is still an issue... is there a way to manually specify the maximize region? Or, is there a way to set the window size without affecting the restoreregion property?

所以,我已经走了很长一段路,但 5-6 仍然是一个问题......有没有办法手动指定最大化区域?或者,有没有办法在不影响 restoreregion 属性的情况下设置窗口大小?

回答by Alex Fanat

Easiest Full Solution

最简单的完整解决方案

Hello, The following solution fixes all of the issues detailed in your question in the simplest manner possible, and works on Windows 10 using WPF and the latest version of the C# language and .NET framework. This is as of 3/15/2017. Please let me know if it stops working.

您好,以下解决方案以最简单的方式修复了您的问题中详述的所有问题,并且适用于使用 WPF 和最新版本的 C# 语言和 .NET 框架的 Windows 10。这是截至 2017 年 3 月 15 日的数据。如果它停止工作,请告诉我。

Step 1:To address issues 1, 2, and 4, within your <Window ... > </Window>tags in the XAML of your application, paste this in, at the top or bottom:

步骤 1:要解决问题 1、2 和 4,请<Window ... > </Window>在应用程序的 XAML 中的标记内,将其粘贴到顶部或底部:

<WindowChrome.WindowChrome>
    <WindowChrome CaptionHeight="35"/>
<WindowChrome.WindowChrome>

CaptionHeightis the desired height of your window dragging area.

CaptionHeight是窗口拖动区域的所需高度。

Step 2:To address issue 3, you need to create your title bar and caption as well as the window controls. To do this, you simply need to give the desired title bar elements each a VerticalAlignment of Top, or put them into a grid with it's VerticalAlignment set to Top, which will do it for all of them, but make sure that their heights are not greater than the CaptionHeightproperty on the WindowChromeelement declared in the XAML, from step 1. For all the buttons, you must assign them, or their container, the property WindowChrome.IsHitTestVisibleInChrome="True". Here is an example:

步骤 2:要解决问题 3,您需要创建标题栏和标题以及窗口控件。为此,您只需为所需的标题栏元素分别指定一个垂直对齐的顶部,或者将它们放入一个垂直对齐设置为顶部的网格中,这将对所有元素执行此操作,但请确保它们的高度不是大于第 1 步中在 XAML 中声明CaptionHeightWindowChrome元素上的属性。对于所有按钮,您必须为它们或其容器分配属性WindowChrome.IsHitTestVisibleInChrome="True"。下面是一个例子:

<Grid VerticalAlignment="Top" Background="White" Name="TitleBar" Height="35">
    <Label Content="Borderless Window Test" VerticalAlignment="Center" HorizontalAlignment="Left"/>
    <StackPanel WindowChrome.IsHitTestVisibleInChrome="True" VerticalAlignment="Center" HorizontalAlignment="Right" Orientation="Horizontal" Name="WindowControls">
        <Button Height="35" Width="35" Content="-" Padding="0" Name="MinimizeButton"/>
        <Button Height="35" Width="35" Content="+" Padding="0" Name="MaximizeButton"/>
        <Button Height="35" Width="35" Content="x" Padding="0" Name="CloseButton"/>
    </StackPanel>
</Grid>

Now, to add proper functionality to the window control buttons, within the MainWindow()constructor of your codebehind, the C# source code of your application, paste the following in, afterthe call to InitializeComponent();:

现在,要向窗口控制按钮添加适当的功能,在MainWindow()代码隐藏的构造函数中,应用程序的 C# 源代码,调用粘贴以下内容InitializeComponent();

CloseButton.Click += (s, e) => Close();
MaximizeButton.Click += (s, e) => WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
MinimizeButton.Click += (s, e) => WindowState = WindowState.Minimized;

Step 3:To address issues 5 and 6, you need to hook into WmGetMinMaxInfo. To do this, go to your codebehind, then copy and paste everything from this Pastebininto your Window class. Now, within your MainWindow()constructor, paste:

步骤 3:要解决问题 5 和 6,您需要挂钩 WmGetMinMaxInfo。为此,请转到您的代码隐藏,然后将此Pastebin 中的所有内容复制并粘贴到您的 Window 类中。现在,在您的MainWindow()构造函数中,粘贴:

SourceInitialized += (s, e) =>
{
    IntPtr handle = (new WindowInteropHelper(this)).Handle;
    HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc));
};

Via Project > Add Referencesin the file menu, be sure to have references to:

通过Project > Add References在文件菜单中,一定要引用:

System.Management
System.Windows.Interop
System.Security.Principal
System.Runtime.InteropServices
Microsoft.Win32

The best way to check is to click on the Assembliestab in the top left, then select Framework, then use the search box in the top right corner of the window. Now add all of these usings (namespaces) to the top of your codebehind:

最好的检查方法是单击Assemblies左上角的选项卡,然后选择Framework,然后使用窗口右上角的搜索框。现在将所有这些使用(命名空间)添加到代码隐藏的顶部:

using System.Management;
using System.Windows.Interop;
using System.Security.Principal;
using System.Runtime.InteropServices;
using Microsoft.Win32;

That should cover everything. I hope this helps!

那应该涵盖一切。我希望这有帮助!

回答by Michael A. Allen

I just went through this entire thing myself. It was a real chore, because you have to manually account for so much. It's funny, we take so much for granted these days, with something as simple as how a basic window operates. But a look at this sample code that I am providing is a good indication of just how much really goes into this problem.

我自己刚刚经历了这整个事情。这是一项真正的苦差事,因为您必须手动考虑这么多。有趣的是,这些天我们认为很多事情都是理所当然的,就像基本窗口的操作一样简单。但是看看我提供的这个示例代码,可以很好地表明这个问题到底有多少。

I hope this helps, as it took me a little time to get here myself.

我希望这会有所帮助,因为我自己花了一点时间才到达这里。

MainWindow.Xaml

主窗口.Xaml

<Window x:Class="WpfApp1.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:WpfApp1"
    Background="Transparent"
    WindowStartupLocation="CenterScreen"
    ResizeMode="CanResizeWithGrip"
    AllowsTransparency="True"
    WindowStyle="None"
    mc:Ignorable="d"
    Title="Test Window Behavior" Height="768" Width="1024" StateChanged="Window_StateChanged" PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown">

<Grid>
    <DockPanel Grid.Column="1" Grid.Row="1">
        <DockPanel x:Name="titleBar" Background="White" DockPanel.Dock="Top">
            <Rectangle Width="32" Height="32" DockPanel.Dock="Left" Fill="Red" Margin="2"/>
            <StackPanel Orientation="Horizontal" DockPanel.Dock="Right" Margin="2">

                <!-- Minimize Button -->
                <Border Width="24" Height="24" Margin="2" HorizontalAlignment="Right" MouseLeftButtonUp="OnMinimizeWindow" Grid.Column="2">
                    <Border.Style>
                        <Style TargetType="Border">
                            <Setter Property="Background" Value="Transparent" />
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="#FFD0D0D0" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <TextBlock FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center" Text="0" FontFamily="Webdings" />
                </Border>

                <!-- Maximize Button -->
                <Border Width="24" Height="24" Margin="2" HorizontalAlignment="Right" MouseLeftButtonUp="OnMaximizeWindow" Grid.Column="3">
                    <Border.Style>
                        <Style TargetType="Border">
                            <Setter Property="Background" Value="Transparent" />
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="#FFD0D0D0" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <TextBlock x:Name="IsMaximized" FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Webdings">
                        <TextBlock.Style>
                            <Style TargetType="TextBlock">
                                <Setter Property="Text" Value="1" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=InternalWindowState, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="Maximized">
                                        <Setter Property="Text" Value="2" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </TextBlock.Style>
                    </TextBlock>
                </Border>

                <!-- Close Button -->
                <Border Width="24" Height="24" Margin="2" HorizontalAlignment="Right" MouseLeftButtonUp="OnCloseWindow" Grid.Column="4">
                    <Border.Style>
                        <Style TargetType="Border">
                            <Setter Property="Background" Value="Transparent" />
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" Value="Red" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                    <TextBlock FontSize="14" HorizontalAlignment="Center" VerticalAlignment="Center" Text="r" FontFamily="Webdings" />
                </Border>
            </StackPanel>

            <Label MouseLeftButtonDown="OnDragMoveWindow" MouseDoubleClick="OnMaximizeWindow" Margin="8 0 0 0" FontSize="12" VerticalContentAlignment="Center" Content="{Binding Path=Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, FallbackValue='Main Window'}" />
        </DockPanel>

        <Grid Background="White" DockPanel.Dock="Bottom" Height="32">
            <Label VerticalContentAlignment="Center" Content="Statusbar Text Goes Here ..." />
        </Grid>

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="100" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="100" />
                <RowDefinition Height="*" />
                <RowDefinition Height="100" />
            </Grid.RowDefinitions>

            <!-- Top 3 -->
            <Border Background="Gray" Grid.Row="0" Grid.Column="0" />
            <Border Background="Gray" Grid.Row="0" Grid.Column="1" BorderBrush="Black" BorderThickness="0 0 0 1" />
            <Border Background="Gray" Grid.Row="0" Grid.Column="2" />

            <!-- Middle 2 -->
            <Border Background="Gray" Grid.Row="1" Grid.Column="0" BorderBrush="Black" BorderThickness="0 0 1 0" />
            <Border Background="Gray" Grid.Row="1" Grid.Column="2" BorderBrush="Black" BorderThickness="1 0 0 0" />

            <!-- Bottom 3 -->
            <Border Background="Gray" Grid.Row="2" Grid.Column="0" />
            <Border Background="Gray" Grid.Row="2" Grid.Column="1" BorderBrush="Black" BorderThickness="0 1 0 0" />
            <Border Background="Gray" Grid.Row="2" Grid.Column="2" />
        </Grid>
    </DockPanel>
    <Grid>
        <Grid.Resources>
            <Style TargetType="Thumb">
                <Style.Setters>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Border Background="Transparent" />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style.Setters>
            </Style>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="25" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="25" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="25" />
            <RowDefinition Height="*" />
            <RowDefinition Height="25" />
        </Grid.RowDefinitions>

        <!-- Top/Left -->
        <DockPanel LastChildFill="False" Grid.Row="0" Grid.Column="0">
            <Thumb DockPanel.Dock="Left" Width="4" Cursor="SizeNWSE" Tag="0" DragDelta="Thumb_DragDelta" />
            <Thumb DockPanel.Dock="Top" Height="4" Cursor="SizeNWSE" Tag="0" DragDelta="Thumb_DragDelta" />
        </DockPanel>

        <!-- Top/Right -->
        <DockPanel LastChildFill="False" Grid.Row="0" Grid.Column="2">
            <Thumb DockPanel.Dock="Right" Width="4" Cursor="SizeNESW" Tag="0" DragDelta="Thumb_DragDelta" />
            <Thumb DockPanel.Dock="Top" Height="4" Cursor="SizeNESW" Tag="0" DragDelta="Thumb_DragDelta" />
        </DockPanel>

        <!-- Bottom/Left -->
        <DockPanel LastChildFill="False" Grid.Row="2" Grid.Column="0">
            <Thumb DockPanel.Dock="Left" Width="4" Cursor="SizeNESW" Tag="1" DragDelta="Thumb_DragDelta" />
            <Thumb DockPanel.Dock="Bottom" Height="4" Cursor="SizeNESW" Tag="1" DragDelta="Thumb_DragDelta" />
        </DockPanel>

        <!-- Bottom/Right -->
        <DockPanel LastChildFill="False" Grid.Row="2" Grid.Column="2">
            <Thumb DockPanel.Dock="Right" Width="4" Cursor="SizeNWSE" Tag="1" DragDelta="Thumb_DragDelta" />
            <Thumb DockPanel.Dock="Bottom" Height="4" Cursor="SizeNWSE" Tag="1" DragDelta="Thumb_DragDelta" />
        </DockPanel>

        <!-- Left -->
        <Thumb Grid.Row="1" Grid.Column="0" Width="4" Cursor="SizeWE" Tag="0" HorizontalAlignment="Left" DragDelta="Thumb_DragDelta" />

        <!-- Top -->
        <Thumb Grid.Row="0" Grid.Column="1" Height="4" Cursor="SizeNS" Tag="0" VerticalAlignment="Top" DragDelta="Thumb_DragDelta" />

        <!-- Right -->
        <Thumb Grid.Row="1" Grid.Column="2" Width="4" Cursor="SizeWE" Tag="1" HorizontalAlignment="Right" DragDelta="Thumb_DragDelta" />

        <!-- Bottom -->
        <Thumb Grid.Row="2" Grid.Column="1" Height="4" Cursor="SizeNS" Tag="1" VerticalAlignment="Bottom" DragDelta="Thumb_DragDelta" />
    </Grid>
</Grid>

MainWindow.xaml.cs

主窗口.xaml.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        #region --- Declarations ---
        private Rect _location { get; set; }
        #endregion

        #region --- Constructors ---
        public MainWindow()
        {
            InitializeComponent();
        }
        #endregion

        #region --- Properties ---
        private Rect DesktopArea
        {
            get
            {
                var c = System.Windows.Forms.Cursor.Position;
                var s = System.Windows.Forms.Screen.FromPoint(c);
                var a = s.WorkingArea;
                return new Rect(a.Left, a.Top, a.Width, a.Height);
            }
        }
        #endregion

        #region --- Dependency Properties ---
        public static readonly DependencyProperty InternalWindowStateProperty = DependencyProperty.Register("InternalWindowState", typeof(WindowState), typeof(MainWindow), new PropertyMetadata(WindowState.Normal, new PropertyChangedCallback(OnInternalWindowStateChanged)));

        public WindowState InternalWindowState
        {
            get { return (WindowState)GetValue(InternalWindowStateProperty); }
            set { SetValue(InternalWindowStateProperty, value); }
        }

        private static void OnInternalWindowStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MainWindow instance = (MainWindow)d;
            instance.SetInternalWindowState((WindowState)e.NewValue);
        }
        #endregion

        #region --- Private Methods ---
        private void StoreLocation()
        {
            _location = new Rect(this.Left, this.Top, this.Width, this.Height);
        }

        private void RestoreLocation()
        {
            this.Width = _location.Width;
            this.Height = _location.Height;
            this.Top = _location.Top >= 0 ? _location.Top : 0;
            this.Left = _location.Left;
        }

        private void SetMaximizedState()
        {
            this.Width = DesktopArea.Width;
            this.Height = DesktopArea.Height;
            this.Top = DesktopArea.Top;
            this.Left = DesktopArea.Left;
        }

        private void SetInternalWindowState(WindowState state)
        {
            InternalWindowState = state;

            switch (InternalWindowState)
            {
                case WindowState.Normal:
                    this.WindowState = WindowState.Normal;
                    RestoreLocation();
                    break;
                case WindowState.Maximized:
                    this.WindowState = WindowState.Normal;
                    SetMaximizedState();
                    break;
                case WindowState.Minimized:
                    this.WindowState = WindowState.Minimized;
                    break;
            }
        }
        #endregion

        #region --- Sizing Routines --- 
        private void Thumb_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
        {
            Thumb thumb = (Thumb)sender;
            int tag = Convert.ToInt32(thumb.Tag);
            if (thumb.Cursor == Cursors.SizeWE) HandleSizeWE(tag, e);
            if (thumb.Cursor == Cursors.SizeNS) HandleSizeNS(tag, e);
            if (thumb.Cursor == Cursors.SizeNESW) HandleSizeNESW(tag, e);
            if (thumb.Cursor == Cursors.SizeNWSE) HandleSizeNWSE(tag, e);
        }

        private void HandleSizeNWSE(int tag, DragDeltaEventArgs e)
        {
            if (tag == 0)
            {
                this.Top += e.VerticalChange;
                this.Height -= e.VerticalChange;
                this.Left += e.HorizontalChange;
                this.Width -= e.HorizontalChange;
            }
            else
            {
                this.Width += e.HorizontalChange;
                this.Height += e.VerticalChange;
            }
        }

        private void HandleSizeNESW(int tag, DragDeltaEventArgs e)
        {
            if (tag == 0)
            {
                this.Top += e.VerticalChange;
                this.Height -= e.VerticalChange;
                this.Width += e.HorizontalChange;
            }
            else
            {
                this.Left += e.HorizontalChange;
                this.Width -= e.HorizontalChange;
                this.Height += e.VerticalChange;
            }
        }

        private void HandleSizeNS(int tag, DragDeltaEventArgs e)
        {
            if (tag == 0)
            {
                this.Top += e.VerticalChange;
                this.Height -= e.VerticalChange;
            }
            else
                this.Height += e.VerticalChange;
        }

        private void HandleSizeWE(int tag, DragDeltaEventArgs e)
        {
            if (tag == 0)
            {
                this.Left += e.HorizontalChange;
                this.Width -= e.HorizontalChange;
            }
            else
                this.Width += e.HorizontalChange;
        }
        #endregion

        #region --- Event Handlers ---
        private void OnDragMoveWindow(Object sender, MouseButtonEventArgs e)
        {
            if (this.InternalWindowState == WindowState.Maximized)
            {
                var c = System.Windows.Forms.Cursor.Position;
                this.InternalWindowState = WindowState.Normal;
                this.Height = _location.Height;
                this.Width = _location.Width;
                this.Top = c.Y - (titleBar.ActualHeight / 2);
                this.Left = c.X - (_location.Width / 2);
            }
            this.DragMove();
        }

        private void OnMaximizeWindow(Object sender, MouseButtonEventArgs e)
        {
            if (this.InternalWindowState == WindowState.Maximized)
                this.InternalWindowState = WindowState.Normal;
            else
                this.InternalWindowState = WindowState.Maximized;
        }

        private void OnMinimizeWindow(Object sender, MouseButtonEventArgs e)
        {
            this.InternalWindowState = WindowState.Minimized;
        }

        private void OnCloseWindow(Object sender, MouseButtonEventArgs e)
        {
            Application.Current.Shutdown();
        }

        private void Window_StateChanged(object sender, EventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
            {
                this.InternalWindowState = WindowState.Maximized;
            }
        }

        private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (this.InternalWindowState != WindowState.Maximized)
                StoreLocation();
        }
        #endregion
    }
}

回答by ExtremeProgrammer

For Point number 5, use this:

对于第 5 点,请使用:

public WindowName() // Constructor for your window
{
this.MaxHeight = SystemParameters.WorkArea.Height;
this.MaxWidth = SystemParameters.WorkArea.Width;
}

This will ensure that the window will not overlap the taskbar when maximized.

这将确保窗口在最大化时不会与任务栏重叠。

回答by user2465452

You can specify the maximize region by handling the WM_GETMINMAXINFOWin32 message. The code hereshows how to do that. It will solve issues #5 and #6.

您可以通过处理WM_GETMINMAXINFOWin32 消息来指定最大化区域。这里的代码展示了如何做到这一点。它将解决问题#5 和#6。

Note that there are a few things that I would do differently, such as returning IntPtr.Zeroinstead of (System.IntPtr)0 in WindowProc and making MONITOR_DEFAULTTONEARESTa constant. But that's just coding style changes, and doesn't affect the net result.

请注意,有几件事我会做不同的事情,例如IntPtr.Zero在 WindowProc 中返回而不是 (System.IntPtr)0 并创建MONITOR_DEFAULTTONEAREST一个常量。但这只是编码风格的变化,不会影响最终结果。

Also make sure to pay attention to the update where the WindowProcis hooked during the SourceInitializedevent instead of OnApplyTemplate. That's the better place to do it. If you're implementing a class derived from Window, then another option is to override OnSourceInitializedto hook the WindowProcinstead of attaching to the event. That's what I normally do.

还要确保注意WindowProcSourceInitialized事件期间挂钩的更新而不是OnApplyTemplate. 那是最好的地方。如果您正在实现从 Window 派生的类,则另一个选项是覆盖OnSourceInitialized以挂钩WindowProc而不是附加到事件。这就是我通常所做的。

回答by punker76

for all these problems, I can only recommend this:

对于所有这些问题,我只能推荐这个:

MahApps.Metro: http://mahapps.com/MahApps.Metro/

MahApps.Metro:http://mahaps.com/MahApps.Metro/

Sourcecode: https://github.com/MahApps/MahApps.Metro

源代码:https: //github.com/MahApps/MahApps.Metro

it's a nice library with a nice theme and easy to use!

这是一个不错的库,主题不错,易于使用!

hope that helps

希望有帮助

回答by andidegn

I know this is a late response, but I was dealing with these exact issues a couple of years back, especially #6.

我知道这是一个迟到的回应,但几年前我正在处理这些确切的问题,尤其是#6。

For #6, this is an issue if you have ResizeState set to CanResize or CanResizeWithGrip, CanMinimize and NoResize fullscreens with no overscan. What I have done is I created my own titlebar with minimize, maximize, close and DragMove (with unsnapping support) functionality and I have created a thumb as the resize grip to allow resizing.

对于 #6,如果您将 ResizeState 设置为 CanResize 或 CanResizeWithGrip、CanMinimize 和 NoResize 全屏且没有过扫描,则这是一个问题。我所做的是我创建了自己的标题栏,具有最小化、最大化、关闭和 DragMove(具有取消捕捉支持)功能,并且我创建了一个拇指作为调整大小的手柄以允许调整大小。

This still have a few drawbacks like only being able to resize from the bottom right corner and having to deal with #5. I haven't found an elegant solution for this one yet.

这仍然有一些缺点,例如只能从右下角调整大小并且必须处理 #5。我还没有找到一个优雅的解决方案。