Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Window positioning results in space around windows on Windows 10

Tags:

windows

winapi

I have some code that positions windows to screen quadrants. It works fine on Windows XP, 7, and 8/8.1. However, on Windows 10, there is a weird gap between windows. The extra space surrounds the window on all 4 sides. I presume it has something to do with window borders, but can't figure out how to correct the problem. Any input would be highly appreciated. The code is as follows:

// Get monitor info
HMONITOR hm = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi;
mi.cbSize = sizeof(mi);
GetMonitorInfo(hm, &mi);

// Set screen coordinates and dimensions of monitor's work area
DWORD x = mi.rcWork.left;
DWORD y = mi.rcWork.top;
DWORD w = mi.rcWork.right - x;
DWORD h = mi.rcWork.bottom - y;

switch (corner) {
case 0: // Left top
    SetWindowPos(hWnd, HWND_TOP, x, y, w / 2, h / 2, SWP_NOZORDER);
    break;
case 1: // Right top
    SetWindowPos(hWnd, HWND_TOP, x + w / 2, y, w / 2, h / 2, SWP_NOZORDER);
    break;
case 2: // Right bottom
    SetWindowPos(hWnd, HWND_TOP, x + w / 2, y + h / 2, w / 2, h / 2, SWP_NOZORDER);
    break;
case 3: // Left bottom
    SetWindowPos(hWnd, HWND_TOP, x, y + h / 2, w / 2, h / 2, SWP_NOZORDER);
    break;
}
like image 940
Paul Avatar asked Sep 24 '15 03:09

Paul


1 Answers

I managed to correct this effect by inflating target rectangle by a calculated margin like this:

static RECT GetSystemMargin(IntPtr handle) {
    HResult success = DwmGetWindowAttribute(handle, DwmApi.DWMWINDOWATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS,
        out var withMargin, Marshal.SizeOf<RECT>());
    if (!success.Succeeded) {
        Debug.WriteLine($"DwmGetWindowAttribute: {success.GetException()}");
        return new RECT();
    }

    if (!GetWindowRect(handle, out var noMargin)) {
        Debug.WriteLine($"GetWindowRect: {new Win32Exception()}");
        return new RECT();
    }

    return new RECT {
        left = withMargin.left - noMargin.left,
        top = withMargin.top - noMargin.top,
        right = noMargin.right - withMargin.right,
        bottom = noMargin.bottom - withMargin.bottom,
    };
}

And then doing

RECT systemMargin = GetSystemMargin(this.Handle);
targetBounds.X -= systemMargin.left;
targetBounds.Y -= systemMargin.top;
targetBounds.Width += systemMargin.left + systemMargin.right;
targetBounds.Height += systemMargin.top + systemMargin.bottom;

That worked for all windows I could test it with, except Explorer windows, which I hardcoded to exclude. If I'd do that expansion on Explorer near the screen edge, window ends up spilling a large area past it to the adjacent monitor.

like image 99
LOST Avatar answered Nov 16 '22 02:11

LOST