Exclude shadows when using GetWindowRect

Use DwmGetWindowAttribute instead of GetWindowRect when in Windows Vista and above.

Using GetWindowRect in Windows 10.

shadow

Using DwmGetWindowAttribute in Windows 10.

no-shadow

[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

[DllImport("dwmapi.dll")]
static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, IntPtr pvAttribute, int cbAttribute);

public static RECT GetWindowBounds(IntPtr handle)
{
    RECT rect;
    if (Environment.OSVersion.Version.Major < 6)
    {
        //Is Below Vista (exclusive)
        if (!GetWindowRect(handle, out rect))
            throw new Win32Exception(Marshal.GetLastWin32Error());
        return rect;
    }
    //Vista (inclusive) and above will include shadows in GetWindowRect.
    IntPtr ptrFrame = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(RECT)));
    int ret = DwmGetWindowAttribute(handle, (int)DWMWA.EXTENDED_FRAME_BOUNDS/*9*/, ptrFrame, Marshal.SizeOf(typeof(RECT)));
    if (ret != 0)
        throw new Win32Exception(ret);
    rect = (RECT)Marshal.PtrToStructure(ptrFrame, typeof(RECT));
    Marshal.FreeHGlobal(ptrFrame);
    return rect;
}

Further Reading

  1. Getting a window rectangle without the drop shadow | Cyotek
  2. GetWindowRect returns a size including “invisible” borders | Stack Overflow

Posted:

Comments