参考
Retrieve Window Size without Windows Shadows
DwmGetWindowAttribute (dwmapi)
代码
// 调用DwmGetWindowAttribute
DwmGetWindowAttribute(this.Handle,
DWMWINDOWATTRIBUTE.ExtendedFrameBounds,
out rect,
Marshal.SizeOf(typeof(RECT)));
// 枚举、结构体、API定义
enum DWMWINDOWATTRIBUTE : uint
{
NCRenderingEnabled = 1,
NCRenderingPolicy,
TransitionsForceDisabled,
AllowNCPaint,
CaptionButtonBounds,
NonClientRtlLayout,
ForceIconicRepresentation,
Flip3DPolicy,
ExtendedFrameBounds,
HasIconicBitmap,
DisallowPeek,
ExcludedFromPeek,
Cloak,
Cloaked,
FreezeRepresentation
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left, Top, Right, Bottom;
public RECT(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public RECT(System.Drawing.Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
public int X
{
get { return Left; }
set { Right -= (Left - value); Left = value; }
}
public int Y
{
get { return Top; }
set { Bottom -= (Top - value); Top = value; }
}
public int Height
{
get { return Bottom - Top; }
set { Bottom = value + Top; }
}
public int Width
{
get { return Right - Left; }
set { Right = value + Left; }
}
public System.Drawing.Point Location
{
get { return new System.Drawing.Point(Left, Top); }
set { X = value.X; Y = value.Y; }
}
public System.Drawing.Size Size
{
get { return new System.Drawing.Size(Width, Height); }
set { Width = value.Width; Height = value.Height; }
}
public static implicit operator System.Drawing.Rectangle(RECT r)
{
return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height);
}
public static implicit operator RECT(System.Drawing.Rectangle r)
{
return new RECT(r);
}
public static bool operator ==(RECT r1, RECT r2)
{
return r1.Equals(r2);
}
public static bool operator !=(RECT r1, RECT r2)
{
return !r1.Equals(r2);
}
public bool Equals(RECT r)
{
return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
}
public override bool Equals(object obj)
{
if (obj is RECT)
return Equals((RECT)obj);
else if (obj is System.Drawing.Rectangle)
return Equals(new RECT((System.Drawing.Rectangle)obj));
return false;
}
public override int GetHashCode()
{
return ((System.Drawing.Rectangle)this).GetHashCode();
}
public override string ToString()
{
return string.Format(System.Globalization.CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom);
}
}
[DllImport("dwmapi.dll")]
static extern int DwmGetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE dwAttribute, out RECT pvAttribute, int cbAttribute);
总结
和GetWindowRect比较,DwmGetWindowAttribute能在Win10下获取窗口的实际尺寸。
从下表的数据比较中可以看出,非最大化时GetWindowRect计算了窗口左、右、下“多余的部分”的尺寸,都是7个像素。最大化时GetWindowRect计算了窗口左、右、上、下“多余的部分”的尺寸,都是8个像素。
非最大化
API | LEFT | TOP | WIDTH | HEIGHT |
---|---|---|---|---|
GetWindowRect | 156 | 156 | 472 | 254 |
DwmGetWindowAttribute | 163 | 156 | 458 | 247 |
最大化
API | LEFT | TOP | WIDTH | HEIGHT |
---|---|---|---|---|
GetWindowRect | -8 | -8 | 1936 | 1015 |
DwmGetWindowAttribute | 0 | 0 | 1920 | 999 |