Reputation:
I want to move and resize an application's window (ex: Notepad).
I tried both MoveWindow
and SetWindowPos
, and both has the exact same issue. The new position/size is always inaccurate.
MoveWindow(handle, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, true);
SetWindowPos(handle, IntPtr.Zero, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, 0);
I tested this on different PCs (both running Windows 10) and I noticed a pattern. On the first PC, the "drift" was X:+7, Y:0, W: -14, H: -7. On the second PC, the "drift" was X:+8, Y:0, W:-16, H-8.
I did test it on a third PC, but the result was way worse which I'm guessing it has something to do with it having 2 monitors.
I can see the "drift" with my own eyes, it's especially clear when I feed it X:0 and Y:0. I don't understand why this is happening though or how I can fix it.
This is the function I use to get a Window's (ex: Notepad) position and dimensions:
public static Rectangle GetWindowRectangle(IntPtr handle)
{
Rect rect = new Rect();
if (Environment.OSVersion.Version.Major >= 6)
{
int size = Marshal.SizeOf(typeof(Rect));
DwmGetWindowAttribute(handle, (int)DwmWindowAttribute.DWMWA_EXTENDED_FRAME_BOUNDS, out rect, size);
}
else if (Environment.OSVersion.Version.Major < 6 || rect.ToRectangle().Width == 0)
{
GetWindowRect(handle, out rect);
}
return rect.ToRectangle();
}
Upvotes: 1
Views: 2404
Reputation: 7170
You've ignored the shadow of the window. In win10, you will use DwmGetWindowAttribute
+ DWMWA_EXTENDED_FRAME_BOUNDS
in GetWindowRectangle
, and according to the documentation, this will get the window bounds excluding the drop shadow.
And in Windows Vista and later, the Window Rect now includes the area occupied by the drop shadow. So, function MoveWindow
and SetWindowPos
think that the position/size you pass includes the shadow.
if you want to move and resize the area that excludes the shadow, then you need to first calculate the size of the shadow (C++ sample):
RECT exclude_shadow = {}, include_shadow = {};
GetWindowRectangle(hwnd,&exclude_shadow);
GetWindowRect(hwnd, &include_shadow);
RECT shadow = {};
shadow.left = include_shadow.left - exclude_shadow.left; // -7
shadow.right = include_shadow.right - exclude_shadow.right; // +7
shadow.top = include_shadow.top - exclude_shadow.top; //0
shadow.bottom = include_shadow.bottom - exclude_shadow.bottom; // +7
LONG Width = include_shadow.right - include_shadow.left;
LONG Height = include_shadow.bottom - include_shadow.top;
//SetWindowPos(hwnd, NULL, 0 + shadow.left, 0 + shadow.top, Width, Height, 0);
SetWindowPos(hwnd, NULL, 0 + shadow.left, 0 + shadow.top, 0, 0, SWP_NOSIZE); // use SWP_NOSIZE if you want to keep the size.
Upvotes: 4