【问题标题】:WPF - Maximizing borderless window by taking in account the user taskbarWPF - 通过考虑用户任务栏最大化无边框窗口
【发布时间】:2013-02-10 16:11:40
【问题描述】:

我正在创建一个带有自定义镶边的 WPF 窗口,因此我设置了 ResizeMode="NoResize"WindowStyle="None" 来实现我自己的镶边。但是,在最大化无边框窗口时存在一个问题:它占据了整个屏幕。

我发现了以下技巧来解决部分问题: http://chiafong6799.wordpress.com/2009/02/05/maximizing-a-borderlessno-caption-window/

这成功地限制了窗口大小以防止覆盖任务栏。但是,如果用户的任务栏位于左侧或顶部,这将不起作用,因为窗口位于位置 0,0。

有什么方法可以更准确地检索可用区域,或者查询用户任务栏的位置,以便我可以相应地定位最大化的窗口?

【问题讨论】:

    标签: wpf


    【解决方案1】:

    我快速玩了一下,似乎在使用无边框形式设置 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>
    

    显然你会想要清理这段代码,但它似乎在 Taskbar 所在的任何地方都可以工作,但是你可能需要添加一些逻辑来获得正确的 LeftTop 如果用户字体 DPI大于 100%

    【讨论】:

    • 这正是我所需要的,非常感谢!附带说明,由于 WindowState 被忽略,因此您还需要添加 som 逻辑以防止在最大化时调整大小。由于我使用隐藏的拇指元素手动实现了调整大小,但这对我来说确实不是问题。
    【解决方案2】:

    另一种方法是处理WM_GETMINMAXINFO Win32 消息。代码here 显示了如何做到这一点。

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

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

    【讨论】:

      猜你喜欢
      • 2012-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多