为了回答我的问题,我最终找到了一个解决方案,其中涉及使用
DwmGetWindowAttribute
函数和
DWMWA_EXTENDED_FRAME_BOUNDS
值。
这个答案的灵感来自于
这个源代码,它呈现了一个在所有系统上似乎都能工作的函数。核心是一个函数:
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
{
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
{
public int Left;
public int Top;
public int Right;
public int Bottom;
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();
}
}
FormBorderStyle
时查看 Visual Studio 设计器,你会看到它实际上在缩小。 - Moslem Ben DhaouDwmGetWindowAttribute()
并使用DWMWA_EXTENDED_FRAME_BOUNDS
参数,则会得到与GetWindowRect()
相同的结果,即包括不可见的边框。必须等待窗口被渲染后才能获得正确的结果。 - Ian Goldby