WindowChrome ResizeBorderThickness问题 [英] WindowChrome ResizeBorderThickness issue

查看:138
本文介绍了WindowChrome ResizeBorderThickness问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设置窗口的样式,但是我注意到WindowChrome的这种奇怪行为(在.NET FW 4.0中,来自外部Microsoft.Windows.Shell dll )。

I am styling a Window, but I noticed this strange behaviour of WindowChrome (in .NET FW 4.0, from external Microsoft.Windows.Shell dll).

我使用AllowTransparency = true和WindowStyle = None设置WindowChrome

I set the WindowChrome with AllowTransparency = true and WindowStyle = None.

如果我将WindowChrome的ResizeBorderThickness设置为< = 7,则一切正常,但如果我这样做了

If I set the WindowChrome's ResizeBorderThickness <= 7 everything works perfectly, but if I do

ResizeBorderThickness = 8

或更多,当窗口最大化时,我无法将其从最后一个顶部拖动像素靠近屏幕顶部边缘,并且每次+1超过7时,我必须开始从边缘向下拖动1个像素。

or more, when the Window is Maximized I can't drag it from the last top pixel near the top edge of the screen, and for each +1 exceeding 7 I must start dragging 1 pixel more down from the edge.

这很烦人,因为它禁用了关闭窗口时的一种常见行为,迫使我将其设置为7或更小。

This is annoying 'cause it disable a common behaviour when closing a window, forcing me to set it to 7 or less.

有人可以向我解释这种行为吗?

Can someone explain me this behaviour?

谢谢!

推荐答案

窗口没有异常行为。代替它,窗口具有两个奇怪的行为

The window doesn't have a strange behavior. Instead of it, the window has two strange behaviors.


  • (A)第一个奇怪行为

  • (A) First strange behavior:

[...]当窗口最大化时,我无法拖动它来自屏幕顶部附近的最后一个顶部像素[...]

"[...] when the Window is Maximized I can't drag it from the last top pixel near the top edge of the screen [...]"

此行为是由于当窗口更改为其最大化状态时,要调整大小的边缘仍处于活动状态。确实,该边缘始终处于活动状态。设置 ResizeBorderThickness 属性, WindowChrome 保留该像素数量,以控制调整窗口大小的行为。考虑到在最大化模式下,不允许调整大小事件,那么您会注意到这些像素不允许任何行为。正是因为 WindowChrome 仅保留那些控制调整大小行为的像素。

This behavior is due to the edge to resize is still active when the window changes to its maximized state. Indeed, this edge is always active. Setting the ResizeBorderThickness property, WindowChrome reserve that amount of pixels to control the behavior of resizing the window. Given that in maximized mode the resize events aren't allowed, then you will notice that these pixels don't allow any kind of behavior. This is precisely because WindowChrome reserve exclusively those pixels that control the behavior of resizing.

解决方案是什么?您需要通知 WindowChrome 必须更改以在窗口最大化时将 ResizeBorderThickness 属性设置为0。只需在xaml中通过 Trigger 再次设置 WindowChrome 即可完成此操作:

What is the solution? You need to notify WindowChrome must change to establish the ResizeBorderThickness property to 0 when the window is maximized. This can be done simply by setting WindowChrome again by a Trigger in xaml:

<Trigger Property="WindowState" Value="Maximized">
     <Setter Property="WindowChrome.WindowChrome">
          <Setter.Value>
               <WindowChrome ResizeBorderThickness="0" [...] />
          </Setter.Value>
     </Setter>
</Trigger>

注意:这也可以在运行时代码中完成


  • (B)第二种奇怪的行为

  • (B) Second strange behavior:

[...]如果我设置WindowChrome的ResizeBorderThickness< = 7,则一切正常[...]并且对于每+1超过7的我都必须开始拖动1 [...]

"[...] If I set the WindowChrome's ResizeBorderThickness <= 7 everything works perfectly [...] and for each +1 exceeding 7 I must start dragging 1 pixel more down from the edge. [...]"

注意。实际上,这种行为不是由于 ResizeBorderThickness 中设置的值,而是由于设置了属性 WindowStyle = None 。设置此属性后,最大化时窗口会发生奇怪的行为:

Take care. Actually this behavior isn't due to the value set in ResizeBorderThickness but this is due to set the property WindowStyle=None. When this property is set, the window takes on a strange behavior when maximized:


  1. 窗口的左上边缘不是定位在当前屏幕的点(0,0)上,但不规则地变为负数(在您的情况下,在Y轴上,该值似乎为-7)。

  1. The upper left edge of the window is not positioned at the point (0,0) of the current screen, but rather erratically becomes negative (in your case, on the Y axis the value seems to be -7).

窗口的大小以当前屏幕的大小为准,通常情况下,窗口的大小应以当前工作区域(当前屏幕,但任务栏等除外)。

The size of the window takes the size of the current screen, when the normal behavior should be that the size of the window takes the size of current work area (current screen except task bar, etc...) of the current screen.

这种带有窗口的奇怪行为使得为 WindowChrome保留的7个像素在当前屏幕上不可见(显然, ResizeBorderThickness = 7 ),因此给您的感觉是属性 ResizeBorderThickness = 7 正常运行,否则无法正常运行。实际上,这证明当 ResizeBorderThickness 取值为8或更大时的行为是正确的。

This strange behavior that takes the window makes that 7 pixels reserved for 'WindowChrome' aren't visible in the current screen (with ResizeBorderThickness="7", obviously), and therefore gives you the feeling that the property ResizeBorderThickness="7" works properly, when it isn't. In fact, this justifies the behavior when ResizeBorderThickness takes the value 8 or more.

解决方案是什么?当最大化当前屏幕工作区上的大小和位置时,有必要强制窗口。 警告:如果仅在主屏幕上执行此操作,则对多个屏幕来说,最大化事件将无法正常工作。

What is the solution? It is necessary to force the window when maximizing a size and position on the work area of the current screen. Warning: if you only do it for the primary screen, the maximize event doesn't work properly for multiple screens.

解决问题的代码我通过调用外部API解决了这个问题:

The code that solves this problem I solved by calling an external API:

[DllImport("user32")]
internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[DllImport("user32")]
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);

定义类和结构:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
public class MONITORINFO
{
      public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
      public RECT rcMonitor = new RECT();
      public RECT rcWork = new RECT();
      public int dwFlags = 0;
}

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
      public int left;
      public int top;
      public int right;
      public int bottom;
}

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
      public int x;
      public int y;
      public POINT(int x, int y) { this.x = x; this.y = y; }
}

[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
      public POINT ptReserved;
      public POINT ptMaxSize;
      public POINT ptMaxPosition;
      public POINT ptMinTrackSize;
      public POINT ptMaxTrackSize;
}

最后定义将钩子WndProc添加到窗口的函数:

And finally defining the functions that add the hook WndProc to the window:

public static void CompatibilityMaximizedNoneWindow(Window window)
{
      WindowInteropHelper wiHelper = new WindowInteropHelper(window);
      System.IntPtr handle = wiHelper.Handle;
      HwndSource.FromHwnd(handle).AddHook(
                new HwndSourceHook(CompatibilityMaximizedNoneWindowProc));
}

private static System.IntPtr CompatibilityMaximizedNoneWindowProc(
    System.IntPtr hwnd,
    int msg,
    System.IntPtr wParam,
    System.IntPtr lParam,
    ref bool handled)
{
      switch (msg)
      {
      case 0x0024:    // WM_GETMINMAXINFO
            MINMAXINFO mmi =
                (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));

                // Adjust the maximized size and position
                // to fit the work area of the correct monitor
                // int MONITOR_DEFAULTTONEAREST = 0x00000002;
                System.IntPtr monitor = MonitorFromWindow(hwnd, 0x00000002);

                if (monitor != System.IntPtr.Zero)
                {

                      MONITORINFO monitorInfo = new MONITORINFO();
                      GetMonitorInfo(monitor, monitorInfo);
                      RECT rcWorkArea = monitorInfo.rcWork;
                      RECT rcMonitorArea = monitorInfo.rcMonitor;
                      mmi.ptMaxPosition.x =
                            Math.Abs(rcWorkArea.left - rcMonitorArea.left);
                      mmi.ptMaxPosition.y =
                            Math.Abs(rcWorkArea.top - rcMonitorArea.top);
                      mmi.ptMaxSize.x =
                            Math.Abs(rcWorkArea.right - rcWorkArea.left);
                      mmi.ptMaxSize.y =
                            Math.Abs(rcWorkArea.bottom - rcWorkArea.top);
                }
                Marshal.StructureToPtr(mmi, lParam, true);
                handled = true;
                break;
      }
      return (System.IntPtr)0;
}

使用 CompatibilityMaximizedNoneWindow API,您只需调用该API在窗口的构造函数中,如下所示:

With CompatibilityMaximizedNoneWindow API, you simply call the API in the constructor of the window, something like this:

public MyWindow
{
      [...]
      MyNamespace.CompatibilityMaximizedNoneWindow(this);
}

第二个奇怪的行为必须解决。您会注意到该代码可以正常工作,必须添加引用 PresentationFramework 和名称空间 System.Windows.Interop

And the second strange behavior must be resolved. You will notice that the code to work, you must add reference PresentationFramework and the namespace System.Windows.Interop.

这篇关于WindowChrome ResizeBorderThickness问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆