2
votes

I am trying to make a borderless window in Qt5.6.0, with aero-snap functionality. Everything works, except when I maximize the window : it is too big.

My screen resolution is 2560x1440, so the window should be sized 2560x1400 (40 Pixels for the Taskbar), but in the WM_SIZE message, the new size is 2576x1416. So the window is exactly 8 pixels too big in every direction. This also means that the window is not aligned in the top-left corner, it is exactly 8 pixels off-screen in both directions.

I can't find a solution for this problem, everything I have tried doesn't work and causes bugs.

The only thing that fixes this is to remove the WS_CAPTION and WS_THICKFRAME styles, but then I lose the areo snap functionality.

I somehow have to tell Qt or DWM to make the window 16 pixels smaller and move it 8 pixels right, and bottom. Does anybody have an idea on how to do that?

3

3 Answers

0
votes

I somehow have to tell Qt or DWM to make the window 16 pixels smaller and move it 8 pixels right, and bottom. Does anybody have an idea on how to do that?

DWM is Desktop Window Manager? Then the platform is Windows then.

As long as it is about Qt 5.6 and you very likely talking about the widget with Qt::CustomizeWindowHint attribute set then there is a known bug in Qt which is not fixed yet:

https://bugreports.qt.io/browse/QTBUG-4362

I stumbled upon that bug a couple of times and the workaround proposed by BiTOk at the link above worked for me.

0
votes

My first try, was setting the window geometry to the available geometry:

QRect rect = QApplication::desktop()->availableGeometry();
setGeometry(rect.left() , rect.top(), rect.right(), rect.bottom());

The only Problem is that the window is a pixel too small on the right and bottom side and

setGeometry(rect.left() , rect.top(), rect.right() + 1, rect.bottom() + 1);

gives me an error:

QWindowsWindow::setGeometry: Unable to set geometry 2560x1400+0+0 on QWidgetWindow/'MainWindowWindow'. Resulting geometry:  2576x1416+-8+-8 (frame: 0, 0, 0, 0, custom margin: 0, 0, 0, 0, minimum size: 45x13, maximum size: 16777215x16777215)

Then I looked at the rectangle coordinates of Visual Studio 2015 and they are the same size as my implementation of a borderless window, 8 pixels larger in every direction.

I can give the contents of my window a margin of 8 so it doesn't clip out of the screen if the window is maximized and set the window region:

setContentsMargins({ 8, 8, 8, 8 });

HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);

When the window gets restored, we need to reset the previous changes. The result is:

case WM_SIZE:
    WINDOWPLACEMENT wp;
    wp.length = sizeof(WINDOWPLACEMENT);
    GetWindowPlacement(hwnd, &wp);
    if (wp.showCmd == SW_MAXIMIZE) {
        setContentsMargins({ 8, 8, 8, 8 });

        HRGN WinRgn;
        RECT winrect;
        GetClientRect(hwnd, &winrect);
        WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
        SetWindowRgn(hwnd, WinRgn, true);
        UpdateWindow(hwnd);

        is_fullscreen = true;

    } else {
        if (is_fullscreen) {
            setContentsMargins({ 0, 0, 0, 0 });
            SetWindowRgn(hwnd, NULL, true);

            is_fullscreen = false;
        }
    }
    break;
0
votes

Other posts have already answered the question, but I would just like to add that it might be a good idea to use GetSystemMetrics rather than a hard-coded value of 8.

Example

#include <Windows.h>

void MyWindow::changeEvent(QEvent* ev) {
  if (ev->type() == QEvent::WindowStateChange) {
    const auto state = windowState();
    if(state & Qt::WindowMaximized) {
      const int x = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
      const int y = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
      setContentsMargins({x, y, x, y});
    }
    else {
      setContentsMargins({0, 0, 0, 0});
    }
}