none
窗口resize问题 RRS feed

  • 问题

  • 请问怎样可以使窗口不能被用户resize但是可以最大最小化呢?

    如果设置成noresize的话就连最大最小化的按钮都没有了

    2011年7月19日 8:52

答案

  • 你好!

    1 使用无边框窗体自己实现菜单样,但这样太过繁琐

    2 设置窗体的最小宽、高来避免用户将窗体缩小后界面布局不美观的问题。

    或者尝试默认情况下将窗体的最大、最小宽高都设成一样(这样用户不能改变大小了),在最大化之前去掉最大宽、高的限制,还原窗体后加上最大宽、高的限制。


    知识改变命运,奋斗成就人生!
    2011年7月19日 10:06
    版主
  • 他的方案是可以的,但是我们需要的是要在最大化之前恢复这些属性而不是之后,所以代码这样写:

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                HwndSource source = PresentationSource.FromVisual(thisas HwndSource;
                source.AddHook(WndProc);
            }
     
            const int WM_SYSCOMMAND = 0x0112;
            const int SC_MAXIMIZE = 0xF030;
            const int SC_RESTORE = 0xF120;
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                switch (msg)
                {
                    case WM_SYSCOMMAND:
                        switch (wParam.ToInt32())
                        {
                            case SC_MAXIMIZE:
                                this.ClearValue(Window.MaxHeightProperty);
                                this.ClearValue(Window.MaxWidthProperty);
                                this.ClearValue(Window.MinHeightProperty);
                                this.ClearValue(Window.MinWidthProperty);
                                break;
                            case SC_RESTORE:
                                this.MaxHeight = 480;
                                this.MaxWidth = 640;
                                this.MinHeight = 480;
                                this.MinWidth = 640;
                                break;
                        }
                        break;
                }
                return IntPtr.Zero;
            }

     

    抓Windows消息,当用户点击最大化,抓WM_SYSCOMMAND消息:http://msdn.microsoft.com/en-us/library/ms646360(VS.85).aspx


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 caizhanfei 2011年7月21日 6:32
    2011年7月20日 19:26
    版主
  • 他的方案是可以的,但是我们需要的是要在最大化之前恢复这些属性而不是之后,所以代码这样写:

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                HwndSource source = PresentationSource.FromVisual(thisas HwndSource;
                source.AddHook(WndProc);
            }
     
            const int WM_SYSCOMMAND = 0x0112;
            const int SC_MAXIMIZE = 0xF030;
            const int SC_RESTORE = 0xF120;
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                switch (msg)
                {
                    case WM_SYSCOMMAND:
                        switch (wParam.ToInt32())
                        {
                            case SC_MAXIMIZE:
                                this.ClearValue(Window.MaxHeightProperty);
                                this.ClearValue(Window.MaxWidthProperty);
                                this.ClearValue(Window.MinHeightProperty);
                                this.ClearValue(Window.MinWidthProperty);
                                break;
                            case SC_RESTORE:
                                this.MaxHeight = 480;
                                this.MaxWidth = 640;
                                this.MinHeight = 480;
                                this.MinWidth = 640;
                                break;
                        }
                        break;
                }
                return IntPtr.Zero;
            }

     

    抓Windows消息,当用户点击最大化,抓WM_SYSCOMMAND消息:http://msdn.microsoft.com/en-us/library/ms646360(VS.85).aspx


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    学习了,不过这样有一个问题。就是只有在用户点那个还原的按钮时才会限定min/max width/height. 

    如果用户不是点的按钮而是点着title block拖拽的, 窗口也会还原但是min/max width/height就回不来了


    井=++++
    • 已标记为答案 caizhanfei 2011年7月21日 6:32
    2011年7月21日 2:57
  • 嗯,我也发现了,不过这是一个方向,我继续通过Spy++检测消息,看看能不能还有其他消息可以使用。

    不过,正如肖 所说,方式很多,比如阻止用户的鼠标在边框上发生Resize操作也是可以考虑的。

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
          HwndSource source = PresentationSource.FromVisual(thisas HwndSource;
          source.AddHook(WndProc);
        }
     
        const int WM_NCLBUTTONDOWN = 0x00A1;
     
        const int HTLEFT = 10;
        const int HTRIGHT = 11;
        const int HTTOP = 12;
        const int HTTOPLEFT = 13;
        const int HTTOPRIGHT = 14;
        const int HTBOTTOM = 15;
        const int HTBOTTOMLEFT = 16;
        const int HTBOTTOMRIGHT = 17;
     
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
          switch (msg)
          {
            case WM_NCLBUTTONDOWN:
              switch (wParam.ToInt32())
              {
                case HTLEFT:
                case HTRIGHT:
                case HTTOP:
                case HTTOPLEFT:
                case HTTOPRIGHT:
                case HTBOTTOM:
                case HTBOTTOMLEFT:
                case HTBOTTOMRIGHT:
                  handled = true;
                  break;
              }
              break;
          }
          return IntPtr.Zero;
        }

     

    Sincerely,

     


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 caizhanfei 2011年7月21日 6:32
    2011年7月21日 6:20
    版主

全部回复

  • 你好!

    1 使用无边框窗体自己实现菜单样,但这样太过繁琐

    2 设置窗体的最小宽、高来避免用户将窗体缩小后界面布局不美观的问题。

    或者尝试默认情况下将窗体的最大、最小宽高都设成一样(这样用户不能改变大小了),在最大化之前去掉最大宽、高的限制,还原窗体后加上最大宽、高的限制。


    知识改变命运,奋斗成就人生!
    2011年7月19日 10:06
    版主
  • 第二点觉得不错,楼主你可以试试


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年7月20日 2:18
    版主
  • 你好!

    1 使用无边框窗体自己实现菜单样,但这样太过繁琐

    2 设置窗体的最小宽、高来避免用户将窗体缩小后界面布局不美观的问题。

    或者尝试默认情况下将窗体的最大、最小宽高都设成一样(这样用户不能改变大小了),在最大化之前去掉最大宽、高的限制,还原窗体后加上最大宽、高的限制。


    知识改变命运,奋斗成就人生!

    多谢你的回复,试了下第二种办法

    MaxWidth和MaxHeight的默认值都是infinity.

        private void onStateChanged(object sender, EventArgs e)
        {
          if (Window.WindowState == WindowState.Maximized)
          {
            this.MaxHeight = 1.0/0.0;
            this.MaxWidth = 1.0/0.0;
          }
          else if (Window.WindowState == WindowState.Normal)
          {
            this.MaxHeight = 480;
            this.MaxWidth = 640;
            this.MinHeight = 480;
            this.MinWidth = 640;
          }
        }
    

    这么写的话窗口会像最大化了一样到屏幕左上角但是大小并没有变化

    在最大化时候MaxHeight和MaxWidth应该设多少呢?

    2011年7月20日 3:32
  • 他的方案是可以的,但是我们需要的是要在最大化之前恢复这些属性而不是之后,所以代码这样写:

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                HwndSource source = PresentationSource.FromVisual(thisas HwndSource;
                source.AddHook(WndProc);
            }
     
            const int WM_SYSCOMMAND = 0x0112;
            const int SC_MAXIMIZE = 0xF030;
            const int SC_RESTORE = 0xF120;
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                switch (msg)
                {
                    case WM_SYSCOMMAND:
                        switch (wParam.ToInt32())
                        {
                            case SC_MAXIMIZE:
                                this.ClearValue(Window.MaxHeightProperty);
                                this.ClearValue(Window.MaxWidthProperty);
                                this.ClearValue(Window.MinHeightProperty);
                                this.ClearValue(Window.MinWidthProperty);
                                break;
                            case SC_RESTORE:
                                this.MaxHeight = 480;
                                this.MaxWidth = 640;
                                this.MinHeight = 480;
                                this.MinWidth = 640;
                                break;
                        }
                        break;
                }
                return IntPtr.Zero;
            }

     

    抓Windows消息,当用户点击最大化,抓WM_SYSCOMMAND消息:http://msdn.microsoft.com/en-us/library/ms646360(VS.85).aspx


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 caizhanfei 2011年7月21日 6:32
    2011年7月20日 19:26
    版主
  • 他的方案是可以的,但是我们需要的是要在最大化之前恢复这些属性而不是之后,所以代码这样写:

            private void Window_Loaded(object sender, RoutedEventArgs e)
            {
                HwndSource source = PresentationSource.FromVisual(thisas HwndSource;
                source.AddHook(WndProc);
            }
     
            const int WM_SYSCOMMAND = 0x0112;
            const int SC_MAXIMIZE = 0xF030;
            const int SC_RESTORE = 0xF120;
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                switch (msg)
                {
                    case WM_SYSCOMMAND:
                        switch (wParam.ToInt32())
                        {
                            case SC_MAXIMIZE:
                                this.ClearValue(Window.MaxHeightProperty);
                                this.ClearValue(Window.MaxWidthProperty);
                                this.ClearValue(Window.MinHeightProperty);
                                this.ClearValue(Window.MinWidthProperty);
                                break;
                            case SC_RESTORE:
                                this.MaxHeight = 480;
                                this.MaxWidth = 640;
                                this.MinHeight = 480;
                                this.MinWidth = 640;
                                break;
                        }
                        break;
                }
                return IntPtr.Zero;
            }

     

    抓Windows消息,当用户点击最大化,抓WM_SYSCOMMAND消息:http://msdn.microsoft.com/en-us/library/ms646360(VS.85).aspx


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    学习了,不过这样有一个问题。就是只有在用户点那个还原的按钮时才会限定min/max width/height. 

    如果用户不是点的按钮而是点着title block拖拽的, 窗口也会还原但是min/max width/height就回不来了


    井=++++
    • 已标记为答案 caizhanfei 2011年7月21日 6:32
    2011年7月21日 2:57
  • 你好!

    解决问题的方法有很多种,很多时候并没有什么完美的方案,建议折中一下选择简单一点的方案,不要太纠结。比如我觉得下面的方式就比较好,而也不不需要付出更多的代码成本。

    2 设置窗体的最小宽、高来避免用户将窗体缩小后界面布局不美观的问题。

     


    知识改变命运,奋斗成就人生!
    2011年7月21日 5:09
    版主
  • 嗯,我也发现了,不过这是一个方向,我继续通过Spy++检测消息,看看能不能还有其他消息可以使用。

    不过,正如肖 所说,方式很多,比如阻止用户的鼠标在边框上发生Resize操作也是可以考虑的。

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
          HwndSource source = PresentationSource.FromVisual(thisas HwndSource;
          source.AddHook(WndProc);
        }
     
        const int WM_NCLBUTTONDOWN = 0x00A1;
     
        const int HTLEFT = 10;
        const int HTRIGHT = 11;
        const int HTTOP = 12;
        const int HTTOPLEFT = 13;
        const int HTTOPRIGHT = 14;
        const int HTBOTTOM = 15;
        const int HTBOTTOMLEFT = 16;
        const int HTBOTTOMRIGHT = 17;
     
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
          switch (msg)
          {
            case WM_NCLBUTTONDOWN:
              switch (wParam.ToInt32())
              {
                case HTLEFT:
                case HTRIGHT:
                case HTTOP:
                case HTTOPLEFT:
                case HTTOPRIGHT:
                case HTBOTTOM:
                case HTBOTTOMLEFT:
                case HTBOTTOMRIGHT:
                  handled = true;
                  break;
              }
              break;
          }
          return IntPtr.Zero;
        }

     

    Sincerely,

     


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 caizhanfei 2011年7月21日 6:32
    2011年7月21日 6:20
    版主