简体   繁体   English

Aero Snap的无边界窗口在最大化状态下过大

[英]Borderless window with Aero Snap too large in maximized state

I am trying to make a borderless window in Qt5.6.0, with aero-snap functionality. 我试图在Qt5.6.0中制作一个无边框窗口,并具有航空捕捉功能。 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 . 我的屏幕分辨率为2560x1440 ,因此窗口的大小应为2560x1400 (任务栏为40像素),但是在WM_SIZE消息中,新大小为2576x1416 So the window is exactly 8 pixels too big in every direction. 因此,窗口在每个方向上都正好大于8个像素。 This also means that the window is not aligned in the top-left corner, it is exactly 8 pixels off-screen in both directions. 这也意味着该窗口未在左上角对齐,在两个方向上都离屏幕正好8像素。

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. 解决此问题的唯一方法是删除WS_CAPTIONWS_THICKFRAME样式,但是随后我失去了areo snap功能。

I somehow have to tell Qt or DWM to make the window 16 pixels smaller and move it 8 pixels right, and bottom. 我必须以某种方式告诉Qt或DWM将窗口缩小16个像素,并将其向右下方移动8个像素。 Does anybody have an idea on how to do that? 是否有人对此有想法?

I somehow have to tell Qt or DWM to make the window 16 pixels smaller and move it 8 pixels right, and bottom. 我必须以某种方式告诉Qt或DWM将窗口缩小16个像素,并将其向右下方移动8个像素。 Does anybody have an idea on how to do that? 是否有人对此有想法?

DWM is Desktop Window Manager? DWM是桌面窗口管理器吗? Then the platform is Windows then. 然后该平台就是Windows。

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: 只要是关于Qt 5.6的,并且您很可能在谈论设置了Qt :: CustomizeWindowHint属性的小部件,那么Qt中就有一个已知的错误尚未修复:

https://bugreports.qt.io/browse/QTBUG-4362 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. 我偶然发现了该错误几次, BiTOk在上面的链接中提出的解决方法对我来说很有效。

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. 然后,我查看了Visual Studio 2015的矩形坐标,它们的大小与我实现的无边界窗口的大小相同,在每个方向上都增加了8个像素。

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: 我可以将窗口的内容的边距设置为8,这样在最大化窗口并设置窗口区域的情况下,它不会从屏幕上裁剪出来:

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;

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 . 其他帖子已经回答了这个问题,但是我想补充一点,使用GetSystemMetrics而不是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});
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM