0

I wrote a small program that when WIN + ALT + ARROW are pressed the foreground window in Windows is resized to one of three positions in a column view. I do this using SetWindowPos(). However for some types of windows SetWindowPos() will not set the window to the full size as specified. There is a small empty border space around programs that cause this.

The programs I've tested that cause this: console programs, Windows File Explorer.

The ones I've tested that don't cause this: VS2015, Google Chrome.

Source Code:

#include <math.h>
#include <mutex>
#include <condition_variable>>
#include <Windows.h>
#include <WinUser.h>

#define KeyState(key) ((GetAsyncKeyState(key) & 0x8000) == 0x8000)

void SetWindow(HWND active_window, LONG xx, LONG top, LONG ww, LONG size) {
    SetWindowPos(active_window, NULL, xx, top, ww, size, SWP_SHOWWINDOW);
}

void process_keyboardInput(bool &pr_up, bool &pr_left, bool &pr_right) {
    if ((KeyState(VK_LWIN) || KeyState(VK_RWIN)) && KeyState(VK_MENU)) {
        WINDOWINFO window;
        HWND active_window = GetForegroundWindow();
        GetWindowInfo(active_window, &window);

        if ((window.dwStyle & WS_SIZEBOX) != WS_SIZEBOX)
            return;

        RECT prc;
        GetWindowRect(active_window, &prc);
        HMONITOR monitor = MonitorFromWindow(active_window, MONITOR_DEFAULTTONEAREST);
        MONITORINFO info;
        info.cbSize = sizeof(MONITORINFO);
        GetMonitorInfo(monitor, &info);

        LONG left = info.rcMonitor.left,
            right = info.rcMonitor.right,
            xx = 0, ww = 0, state = 0x0;
        FLOAT size = right - left, win_height = (prc.bottom - prc.top) / 2, win_width = (prc.right - prc.left) / 2;

        if (!KeyState(VK_UP))
            pr_up = false;

        if (!KeyState(VK_LEFT))
            pr_left = false;

        if (!KeyState(VK_RIGHT))
            pr_right = false;

        if (KeyState(VK_LEFT) && KeyState(VK_UP) && !(pr_left && pr_up) && !pr_right) {
            ww = (LONG)(floor(size / 3.0F) + round(size / 3.0F));
            xx = info.rcMonitor.left;
            pr_left = true;
            pr_up = true;

            size = info.rcWork.bottom - info.rcWork.top;
            SetWindowPos(active_window, NULL, xx, info.rcMonitor.top, ww, size, SWP_SHOWWINDOW);
        }

        if (KeyState(VK_RIGHT) && KeyState(VK_UP) && !(pr_right && pr_up) && !pr_left) {
            ww = (LONG)(ceil(size / 3.0F) + round(size / 3.0F));
            xx = info.rcMonitor.left + (size - ww);
            pr_right = true;
            pr_up = true;

            size = info.rcWork.bottom - info.rcWork.top;
            SetWindowPos(active_window, NULL, xx, info.rcMonitor.top, ww, size, SWP_SHOWWINDOW);
        }

        if (KeyState(VK_LEFT) && !pr_left && !pr_up && !pr_right) {
            ww = (LONG)floor(size / 3.0F);
            xx = info.rcMonitor.left;
            pr_left = true;

            size = info.rcWork.bottom - info.rcWork.top;
            SetWindowPos(active_window, NULL, xx, info.rcMonitor.top, ww, size, SWP_SHOWWINDOW);
        }

        if (KeyState(VK_RIGHT) && !pr_right && !pr_up && !pr_left) {
            ww = (LONG)ceil(size / 3.0F);
            xx = info.rcMonitor.left + (size - ww);
            pr_right = true;

            size = info.rcWork.bottom - info.rcWork.top;
            SetWindowPos(active_window, NULL, xx, info.rcMonitor.top, ww, size, SWP_SHOWWINDOW);
        }

        if (KeyState(VK_UP) && !pr_up && !pr_left && !pr_right) {
            ww = (LONG)round(size / 3.0F);
            xx = info.rcMonitor.left + ww;
            pr_up = true;

            size = info.rcWork.bottom - info.rcWork.top;
            SetWindowPos(active_window, NULL, xx, info.rcMonitor.top, ww, size, SWP_SHOWWINDOW);
        }
    }
}

int main() {
    HWND hWnd = GetConsoleWindow();
    ShowWindow(hWnd, SW_HIDE);

    while (true) {
        process_keyboardInput(pr_up, pr_left, pr_right);
        Sleep(10);
    }

    return 0;
}

As a side issue if anyone's interested: The task manager does not seem to prompt any of my code at all, ignoring everything.

Kayle
  • 55
  • 4
  • 1
    Which versions of Windows exhibit the problem? Your code works for me on Win 10. Console and Explorer maximize to the columns perfectly. – zett42 Mar 11 '17 at 20:40
  • @zett42 I can only test on Windows 10 for now. Which is an interesting case--because this is happening to me on Windows 10 and not for you. – Kayle Mar 11 '17 at 20:42
  • 1
    _The task manager does not seem to prompt any of my code at all_ That's normal because task manager runs with higher privileges and can't be controlled from programs running as standard user. – zett42 Mar 11 '17 at 20:42
  • @zett42 Perfect, that fixes the task manager problem! I didn't consider that, but I will in the future. – Kayle Mar 11 '17 at 20:43
  • 1
    I can reproduce your issue now. Turns out I just pressed "Win+Arrow", not "Alt+Win+Arrow". Reading helps ;-) – zett42 Mar 11 '17 at 20:50
  • I think the border space is caused by the window shadow. Spy++ reports the correct coordinates but the shadow seems to be part of the window frame. So you somehow have to get the size of the shadow area and calculate that in. VS2015 uses a custom window and Chrome propably too. VS2015 draws the shadow by creating additional windows that are placed appropriately, so the main window has the right size. – zett42 Mar 11 '17 at 20:55
  • Good to know! I'm not sure what exactly is causing the issue, it just seems that some programs do it and some don't. I'll double check windows with different window styles, but not sure how much that'll help. – Kayle Mar 11 '17 at 20:55
  • 1
    Found an [answer](http://stackoverflow.com/a/34143777/7571258) that may help you. So I think we can mark this question as duplicate. – zett42 Mar 11 '17 at 21:00

0 Answers0