在Windows 8上创建一个表单边框样式设置为Sizable
的WinForms表单,DesktopBounds
property告诉正确的值:
相反,当表单边框样式为FixedDialog
时,值是错误的:
在Windows XP上,值始终是正确的:
我的问题是:
如何获得包含完整非客户区域的窗口的实际大小?
更新1:
似乎与this SO question有关。我会试着看看这是否能在这里解决我的问题。
更新2:
为了完整起见,以下是VMware Windows 7的结果:
更新3:
最后找到了一个解决方案,其中涉及将DwmGetWindowAttribute
function与DWMWA_EXTENDED_FRAME_BOUNDS
value一起使用。我将在下面发布一个答案。
答案 0 :(得分:7)
为了回答我自己的问题,我终于找到了一个解决方案,其中涉及将DwmGetWindowAttribute
function与DWMWA_EXTENDED_FRAME_BOUNDS
value一起使用
答案的灵感来自于this source code,它提供了一个似乎适用于所有系统的功能。核心是一个功能:
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);
}
}
以下提供完整代码:
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();
}
}
答案 1 :(得分:-3)
我不认为“错误”是说得对的正确方法..你看到的是你不理解的价值观,但这并不总是与错误相同。真正的问题是你试图通过获取窗口边界来解决的实际问题是什么?
您是否尝试过Win32 GetWindowRect
方法?我不知道那是什么。
你可以尝试的一个黑客就是检测操作系统并解释这些问题。
要确定C#中的操作系统:http://support.microsoft.com/kb/304283(该示例未特别提及Windows 8,但我认为SDK已针对它进行了更新)