none
WPF在自定义窗口样式时,如何处理最大化时边框溢出屏幕外侧的问题? RRS feed

  • 问题

  • 我在WPF(4.0)中使用以下代码创建自定义窗口样式:

    <shell:WindowChrome.WindowChrome>
        <shell:WindowChrome GlassFrameThickness="1" CaptionHeight="96" CornerRadius="0"/>
    </shell:WindowChrome.WindowChrome>

    然后自己添加了最小化/最大化/还原/关闭按钮,但发现在窗口最大化时,窗口会溢出到屏幕以外,也就是说窗体最外边框会超出屏幕看不见,我目前的解决办法就是当最大化时给窗口根级Grid设置一个Margin,但这种办法显然不是很好,不知正确的方法应该如何解决?

    未最大化的截图:



    最大化的截图(屏幕边缘溢出了,请注意左侧导航菜单选中项和右上角关闭等按钮):


    2017年3月6日 16:23

答案

  • 多谢回答,我用令一种方法解决了,就是给窗口根级Grid设定MaxWidth和MaxHeight为桌面工作区的高度和宽度,构造方法里加代码:

    LayoutRoot.MaxWidth = SystemParameters.WorkArea.Width;
    LayoutRoot.MaxHeight = SystemParameters.WorkArea.Height;

    • 已标记为答案 jesse hao 2017年3月7日 8:57
    2017年3月7日 8:57

全部回复


  • Hi jesse hao,

    你可以尝试下面的方法来最大化和还原窗体。 边框溢出的问题不会出现。

      bool Maxbool = false;
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                if (Maxbool==false)
                {
                    MaximizeWindow();
                    Maxbool = true;
                }
                else
                {
                    Restore();
                    Maxbool = false;
                }
            }
    
            private Rect _restoreLocation;
    
            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;
            }
    
    


    Best Regards,

    Yohann Lu



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年3月7日 5:11
    版主
  • 多谢回答,我用令一种方法解决了,就是给窗口根级Grid设定MaxWidth和MaxHeight为桌面工作区的高度和宽度,构造方法里加代码:

    LayoutRoot.MaxWidth = SystemParameters.WorkArea.Width;
    LayoutRoot.MaxHeight = SystemParameters.WorkArea.Height;

    • 已标记为答案 jesse hao 2017年3月7日 8:57
    2017年3月7日 8:57
  • hi, jesse ,

    请教您最大化时,如何漏出 window任务栏?谢谢。

    2017年7月18日 7:28
  • 如果窗口的WindowStyle设置为None的话,全屏会挡住任务栏,
    所以我的窗口并没有设置WindowStyle为None!这一点很关键,

    将WindowStyle保持默认值,在window标记下输入以下代码(.net4.5以上)即可隐藏窗口自带边框:
        <WindowChrome.WindowChrome>
            <WindowChrome GlassFrameThickness="1" CaptionHeight="96" CornerRadius="0"/>
        </WindowChrome.WindowChrome>

    .net4.0的话,可以引用【Microsoft.Windows.Shell.dll,自行百度】,然后引入命名空间:
    xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"
    加入代码:
        <shell:WindowChrome.WindowChrome>
            <shell:WindowChrome GlassFrameThickness="1" CaptionHeight="96" CornerRadius="0"/>
        </shell:WindowChrome.WindowChrome>
    2017年7月19日 5:02
  • Hi, jesse,

    我之前是用“WindowChrome,同时将窗口的WindowStyle设置为None,再采用您的“设置LayoutRoot.MaxWidth,MaxHeight”的方法,结果在最大化后,标题栏上方会一个白条且下方会遮住任务栏。

    现在WindowStyle保持默认值SingleBorderWindow,最大化已能正常显示。可是我又遇到一个新问题。感觉原来的“标题栏”仍然在,只是在自定义标题栏的背后,且“原标题栏的最小,最大/复原,关闭”按钮仍然有效。这样在操作自定义标题栏上的自定义按钮时就会误动作。想到的思路是调用user32.dll中的API将原有的标题栏按钮去掉。

    想请教您有遇到类似问题吗?解决方案是怎样?非常感谢。

    我的测试代码如下:               

    <Window x:Class="LinkConfig.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:LinkConfig"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525" WindowChrome.WindowChrome="{DynamicResource WindowChromeKey}" Loaded="Window_Loaded"  >

        <Window.Resources>
            <WindowChrome x:Key="WindowChromeKey" CaptionHeight="0" ResizeBorderThickness="5" />
        </Window.Resources>

        <Grid x:Name="LayoutRoot" >
            <Grid.RowDefinitions>
                <RowDefinition Height="43" />
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <Grid Grid.Row=" 0" x:Name="TitleBar"  Background="Gray" MouseMove="TitleBar_MouseMove" MouseDown="TitleBar_MouseDown">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="auto"/>
                    <ColumnDefinition Width="auto"/>
                    <ColumnDefinition Width="auto"/>
                </Grid.ColumnDefinitions>

            <TextBlock Name="txtTitle" Grid.Column="0" Margin="1,0,0,0"  Padding="0,0,0,0" Text="My title bar" 
                       HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="16" FontFamily="微软雅黑" FontWeight="Bold" Foreground="White"/>

                <Button x:Name="btn_min" Grid.Column="1" Click="btn_min_Click">Min</Button>
                <Button x:Name="btn_max" Grid.Column="2" Click="btn_max_Click">Max</Button>
                <Button x:Name="btn_close" Content="Close" Grid.Column="3" Click="btn_close_Click"></Button>

            </Grid>
            <Grid  Grid.Row="1" Background="White">

            </Grid>

        </Grid>
    </Window>

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    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 LinkConfig
    {
        /// <summary>
        /// MainWindow.xaml 的交互逻辑
        /// </summary>
        public partial class MainWindow : Window
        {
            private const int GWL_STYLE = -16;
            private const int WS_SYSMENU = 0x80000;
            [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
            private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
            [System.Runtime.InteropServices.DllImport("user32.dll")]
            private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);


            public MainWindow()
            {
                InitializeComponent();

                LayoutRoot.MaxWidth = SystemParameters.WorkArea.Width;
                LayoutRoot.MaxHeight = SystemParameters.WorkArea.Height;


            }

            #region 标题栏事件

            /// <summary>
            /// 窗口移动事件
            /// </summary>
            private void TitleBar_MouseMove(object sender, MouseEventArgs e)
            {
                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    this.DragMove();
                }
            }

            int i = 0;
            /// <summary>
            /// 标题栏双击事件
            /// </summary>
            private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
            {
                i += 1;
                System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
                timer.Interval = new TimeSpan(0, 0, 0, 0, 300);
                timer.Tick += (s, e1) => { timer.IsEnabled = false; i = 0; };
                timer.IsEnabled = true;

                if (i % 2 == 0)
                {
                    timer.IsEnabled = false;
                    i = 0;
                    this.WindowState = this.WindowState == WindowState.Maximized ?
                                  WindowState.Normal : WindowState.Maximized;
                }
            }

            /// <summary>
            /// 窗口最小化
            /// </summary>
            private void btn_min_Click(object sender, RoutedEventArgs e)
            {
                this.WindowState = WindowState.Minimized; //设置窗口最小化
            }

            /// <summary>
            /// 窗口最大化与还原
            /// </summary>
            private void btn_max_Click(object sender, RoutedEventArgs e)
            {
                if (this.WindowState == WindowState.Maximized)
                {
                    this.WindowState = WindowState.Normal; //设置窗口还原
                }
                else
                {
                    this.WindowState = WindowState.Maximized; //设置窗口最大化
                }
            }

            /// <summary>
            /// 窗口关闭
            /// </summary>
            private void btn_close_Click(object sender, RoutedEventArgs e)
            {
                this.Close();
            }

            #endregion 标题栏事件

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                var hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle;
                SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
            }
        }
    }

    2017年7月20日 1:17
  •  没错,使用【WindowChrome】【WindowStyle设为默认值】的方法,虽然标题栏隐藏了,但标题栏的【最大化/最小化/关闭】的功能仍然存在,所以我添加了我自定义的【最大化/最小化/关闭】按钮覆盖到原标题栏右上角,并设置【WindowChrome.IsHitTestVisibleInChrome="True"】属性,代码如下:

    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="1" CaptionHeight="32" CornerRadius="0"/>
    </WindowChrome.WindowChrome>
    
    <Grid>
        <StackPanel Orientation="Horizontal" HorizontalContentAlignment="Right" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True">
            <Button x:Name="minimizeButton"/>
            <Button x:Name="maximizeButton"/>
            <Button x:Name="closeWindowButton"/>
        </StackPanel>
    </Grid>

    通过设置【WindowChrome.IsHitTestVisibleInChrome="True"】属性,可以让【StackPanel】覆盖掉原来的【最大化/最小化/关闭】按钮,我的自定义标题栏高度是32,所以我的【CaptionHeight="32"】,

    2017年7月20日 5:38
  • 明白了,非常感谢您的指教。
    2017年7月21日 1:19