问题描述
在 Windows 8 上,将表单边框样式设置为 Sizable
的 WinForms 表单,有关.我会尝试看看这是否也能解决我的问题.
更新 2:
为了完整起见,以下是 VMware Windows 7 的结果:
更新 3:
终于找到了一个解决方案,涉及使用 DwmGetWindowAttribute
函数 与 DWMWA_EXTENDED_FRAME_BOUNDS
值.我将在下面发布答案.
为了回答我自己的问题,我终于找到了一个解决方案,涉及使用 DwmGetWindowAttribute
函数和DWMWA_EXTENDED_FRAME_BOUNDS
值
答案的灵感来自 此来源代码 提供了一个似乎适用于所有系统的功能.核心是一个函数:
public static Rectangle GetWindowRectangle(IntPtr handle){if (Environment.OSVersion.Version.Major <6){返回GetWindowRect(句柄);}别的{矩形矩形;返回 DWMWA_EXTENDED_FRAME_BOUNDS(句柄,出矩形)?长方形: GetWindowRect(句柄);}}
完整代码如下:
公共静态类 WindowHelper{//https://code.google.com/p/zscreen/source/browse/trunk/ZScreenLib/Global/GraphicsCore.cs?r=1349///<总结>///获取实际窗口大小,无论是 Win XP、Win Vista、7 还是 8.///</总结>公共静态矩形GetWindowRectangle(IntPtr句柄){if (Environment.OSVersion.Version.Major <6){返回GetWindowRect(句柄);}别的{矩形矩形;返回 DWMWA_EXTENDED_FRAME_BOUNDS(手柄,出矩形)?矩形:GetWindowRect(句柄);}}[DllImport(@"dwmapi.dll")]private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute);私有枚举 Dwmwindowattribute{DwmwaExtendedFrameBounds = 9}[可序列化,结构布局(LayoutKind.Sequential)]私有结构 Rect{//ReSharper 禁用 MemberCanBePrivate.Local//ReSharper 禁用 FieldCanBeMadeReadOnly.Local公共 int 左;公共int顶部;公共 int 权利;公共 int 底部;//ReSharper 恢复 FieldCanBeMadeReadOnly.Local//ReSharper 恢复 MemberCanBePrivate.Local公共矩形 ToRectangle(){return Rectangle.FromLTRB(Left, Top, Right, Bottom);}}private static bool DWMWA_EXTENDED_FRAME_BOUNDS(IntPtr 句柄,出矩形矩形){矩形矩形;var 结果 = DwmGetWindowAttribute(handle, (int)Dwmwindowattribute.DwmwaExtendedFrameBounds,出矩形,Marshal.SizeOf(typeof(Rect)));矩形 = rect.ToRectangle();返回结果>= 0;}[DllImport(@"user32.dll")][返回:MarshalAs(UnmanagedType.Bool)]private static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);私有静态矩形 GetWindowRect(IntPtr 句柄){矩形矩形;GetWindowRect(handle, out rect);返回 rect.ToRectangle();}}
Having a WinForms form with form border style set to Sizable
on Windows 8, the DesktopBounds
property tells the correct values:
In contrast, when having a form border style of FixedDialog
, the values are wrong:
On Windows XP, the values are always correct:
My question is:
How to get the real size of a Window including the complete non-client area?
Update 1:
Seems that it is related to this SO question. I'll try and see whether this would solve my issue here, too.
Update 2:
Just for completeness, here are the results from a VMware Windows 7:
Update 3:
Finally found a solution which involves using the DwmGetWindowAttribute
function together with the DWMWA_EXTENDED_FRAME_BOUNDS
value. I'll post an answer below.
To answer my own question, I finally found a solution which involves using the DwmGetWindowAttribute
function together with the DWMWA_EXTENDED_FRAME_BOUNDS
value
The answer was inspired by this source code which presents a function that seems to work on all system. The core is a function:
public static Rectangle GetWindowRectangle(IntPtr handle)
{
if (Environment.OSVersion.Version.Major < 6)
{
return GetWindowRect(handle);
}
else
{
Rectangle rectangle;
return DWMWA_EXTENDED_FRAME_BOUNDS(handle, out rectangle)
? rectangle
: GetWindowRect(handle);
}
}
Full code is provided below:
public static class WindowHelper
{
// https://code.google.com/p/zscreen/source/browse/trunk/ZScreenLib/Global/GraphicsCore.cs?r=1349
/// <summary>
/// Get real window size, no matter whether Win XP, Win Vista, 7 or 8.
/// </summary>
public static Rectangle GetWindowRectangle(IntPtr handle)
{
if (Environment.OSVersion.Version.Major < 6)
{
return GetWindowRect(handle);
}
else
{
Rectangle rectangle;
return DWMWA_EXTENDED_FRAME_BOUNDS(handle, out rectangle) ? rectangle : GetWindowRect(handle);
}
}
[DllImport(@"dwmapi.dll")]
private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out Rect pvAttribute, int cbAttribute);
private enum Dwmwindowattribute
{
DwmwaExtendedFrameBounds = 9
}
[Serializable, StructLayout(LayoutKind.Sequential)]
private struct Rect
{
// ReSharper disable MemberCanBePrivate.Local
// ReSharper disable FieldCanBeMadeReadOnly.Local
public int Left;
public int Top;
public int Right;
public int Bottom;
// ReSharper restore FieldCanBeMadeReadOnly.Local
// ReSharper restore MemberCanBePrivate.Local
public Rectangle ToRectangle()
{
return Rectangle.FromLTRB(Left, Top, Right, Bottom);
}
}
private static bool DWMWA_EXTENDED_FRAME_BOUNDS(IntPtr handle, out Rectangle rectangle)
{
Rect rect;
var result = DwmGetWindowAttribute(handle, (int)Dwmwindowattribute.DwmwaExtendedFrameBounds,
out rect, Marshal.SizeOf(typeof(Rect)));
rectangle = rect.ToRectangle();
return result >= 0;
}
[DllImport(@"user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);
private static Rectangle GetWindowRect(IntPtr handle)
{
Rect rect;
GetWindowRect(handle, out rect);
return rect.ToRectangle();
}
}
这篇关于窗体在 Windows 8 上显示错误的尺寸 - 如何获得真实尺寸?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!