Win10下獲取正確的視窗尺寸
阿新 • • 發佈:2021-06-22
參考
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 |