WPF - 考虑用户任务栏,最大化无边框窗口

4
我正在创建一个带有自定义边框的WPF窗口,所以我将ResizeMode="NoResize"WindowStyle="None"设置为实现自己的边框。然而,在最大化无边框窗口时会出现问题:它会占据整个屏幕。
我找到了以下技巧来解决部分问题:http://chiafong6799.wordpress.com/2009/02/05/maximizing-a-borderlessno-caption-window/ 这成功地限制了窗口大小,以防止其覆盖任务栏。但是,如果用户将任务栏放在左侧或顶部,则这种方法不起作用,因为窗口位于位置0,0。
是否有更准确地检索可用区域或查询用户任务栏位置的方法,以便可以相应地定位最大化的窗口?
2个回答

5

我进行了简单的尝试,似乎在设置无边框窗体的WindowState.Maximized时忽略了Windows LeftTop属性。

一个解决方法是忽略WindowState函数并创建自己的Maximize/Restore函数。

下面是一个简单的示例。

public partial class MainWindow : Window
{
    private Rect _restoreLocation;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void MaximizeWindow()
    {
        _restoreLocation = new Rect { Width = Width, Height = Height, X = Left, Y = Top };
        System.Windows.Forms.Screen currentScreen;
        currentScreen = System.Windows.Forms.Screen.FromPoint(System.Windows.Forms.Cursor.Position);
        Height = currentScreen.WorkingArea.Height;
        Width = currentScreen.WorkingArea.Width;
        Left = currentScreen.WorkingArea.X;
        Top = currentScreen.WorkingArea.Y;
    }

    private void Restore()
    {
        Height = _restoreLocation.Height;
        Width = _restoreLocation.Width;
        Left = _restoreLocation.X;
        Top = _restoreLocation.Y;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        MaximizeWindow();
    }

    private void Button_Click_2(object sender, RoutedEventArgs e)
    {
        Restore();
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            DragMove();
        }
        base.OnMouseMove(e);
    }
}

Xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="74.608" Width="171.708" ResizeMode="NoResize" WindowStyle="None">
    <Grid>
        <Button Content="Max" HorizontalAlignment="Left" Margin="0,29,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
        <Button Content="Restore" HorizontalAlignment="Left" Margin="80,29,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_2"/>
    </Grid>
</Window>

显然,您希望清理这段代码,但它似乎可以在任何任务栏位置工作。但是,如果用户的字体DPI大于100%,则可能需要添加一些逻辑来获取正确的LeftTop


这正是我所需要的,非常感谢!另外一件事,由于WindowState被忽略了,当最大化时你还需要添加一些逻辑来防止调整大小。但由于我使用隐藏的拇指元素手动实现了调整大小,所以这对我来说并不是问题。 - Kaz

2
另一种方法是通过处理WM_GETMINMAXINFO Win32消息来实现。代码here展示了如何实现这一点。
请注意,我会做一些不同的事情,例如在WindowProc中返回IntPtr.Zero而不是(System.IntPtr)0,并将MONITOR_DEFAULTTONEAREST设置为常量。但这只是编码风格上的改变,不影响最终结果。
还要注意更新,在SourceInitialized事件期间挂钩WindowProc,而不是在OnApplyTemplate中进行。那是更好的做法。如果您正在实现一个派生自Window的类,则另一种选择是重写OnSourceInitialized以挂钩WindowProc,而不是附加到事件。那是我通常做的事情。

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