Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
None
-
6.6.2
-
None
Description
I'm implementing a custom window on Windows with a custom title bar. To do this, I'm handling WM_NCCALCSIZE, which removes the window frame (see example below).
When dragging this window across screens with different DPI (multiple times back and forth), the size of the window slowly grows. This doesn't happen if NCCALCSIZE isn't handled.
From debugging, I found that AdjustWindowRectExForDpi, which is called in QWindowsGeometryHint::frame, returns the "bad" margins for the window.
Adding the check for manually overridden margins from QTBUG-117704 in QWindowsGeometryHint::frame yields the correct result:
QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, DWORD exStyle) { if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style)) return {}; RECT windowRect{}; RECT clientRect{}; GetWindowRect(hwnd, &windowRect); GetClientRect(hwnd, &clientRect); if (qrectFromRECT(windowRect).size() == qrectFromRECT(clientRect).size()) return {}; // ...
I'm not sure if that's a correct fix though.
Debug Logs (without the patch):
qt.qpa.window: >QWindowsGeometryHint::applyToMinMaxInfo< min=0,0 max=16777215,16777215 margins=QMargins(0, 0, 0, 0) in MINMAXINFO(maxSize=POINT(x=1936, y=1096), maxpos=POINT(x=-8, y=-8), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=136, y=39)) qt.qpa.window: <QWindowsGeometryHint::applyToMinMaxInfo out MINMAXINFO(maxSize=POINT(x=1936, y=1096), maxpos=POINT(x=-8, y=-8), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=136, y=39)) qt.qpa.window: QWindowsWindow::getSizeHints QWidgetWindow(0x1e624f97c40, name="QWidgetClassWindow") MINMAXINFO(maxSize=POINT(x=1936, y=1096), maxpos=POINT(x=-8, y=-8), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=136, y=39)) qt.qpa.window: QWindowsGeometryHint::frame style=0x96cf0000 exStyle=0x100 dpi=120 RECT(left=-9, top=-38, right=9, bottom=9 (18x47)) QMargins(9, 38, 9, 9) qt.qpa.window: QWindowsWindow::checkForScreenChanged QWidgetWindow(0x1e624f97c40, name=QWidgetClassWindow) "ASUS VX278"->"SyncMaster" qt.qpa.window: QWindowsGeometryHint::frame style=0x96cf0000 exStyle=0x100 dpi=120 RECT(left=-9, top=-38, right=9, bottom=9 (18x47)) QMargins(9, 38, 9, 9) qt.qpa.window: QWindowsWindow::setFullFrameMargins QWidgetWindow(0x1e624f97c40, name="QWidgetClassWindow") QMargins(0, 0, 0, 0) -> QMargins(9, 38, 9, 9) qt.qpa.window: QWindowsGeometryHint::frame style=0x96cf0000 exStyle=0x100 dpi=120 RECT(left=-9, top=-38, right=9, bottom=9 (18x47)) QMargins(9, 38, 9, 9) qt.qpa.window: >QWindowsGeometryHint::applyToMinMaxInfo< min=0,0 max=16777215,16777215 margins=QMargins(9, 38, 9, 9) in MINMAXINFO(maxSize=POINT(x=1938, y=1098), maxpos=POINT(x=-9, y=-9), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=166, y=47)) qt.qpa.window: <QWindowsGeometryHint::applyToMinMaxInfo out MINMAXINFO(maxSize=POINT(x=1938, y=1098), maxpos=POINT(x=-9, y=-9), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=166, y=47)) qt.qpa.window: QWindowsWindow::getSizeHints QWidgetWindow(0x1e624f97c40, name="QWidgetClassWindow") MINMAXINFO(maxSize=POINT(x=1938, y=1098), maxpos=POINT(x=-9, y=-9), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=166, y=47)) qt.qpa.window: qWindowsWndProc WM_NCCALCSIZE for 0x3e0998 QMargins(0, 0, 0, 0) qt.qpa.window: QWindowsWindow::setFullFrameMargins QWidgetWindow(0x1e624f97c40, name="QWidgetClassWindow") QMargins(9, 38, 9, 9) -> QMargins(0, 0, 0, 0) RESIZED 268 x 172 qt.qpa.window: qWindowsWndProc WM_NCCALCSIZE for 0x3e0998 QMargins(0, 0, 0, 0) qt.qpa.window: >QWindowsGeometryHint::applyToMinMaxInfo< min=0,0 max=16777215,16777215 margins=QMargins(0, 0, 0, 0) in MINMAXINFO(maxSize=POINT(x=1938, y=1098), maxpos=POINT(x=-9, y=-9), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=166, y=47)) qt.qpa.window: <QWindowsGeometryHint::applyToMinMaxInfo out MINMAXINFO(maxSize=POINT(x=1938, y=1098), maxpos=POINT(x=-9, y=-9), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=166, y=47)) qt.qpa.window: QWindowsWindow::getSizeHints QWidgetWindow(0x1e624f97c40, name="QWidgetClassWindow") MINMAXINFO(maxSize=POINT(x=1938, y=1098), maxpos=POINT(x=-9, y=-9), maxtrack=POINT(x=3220, y=1108), mintrack=POINT(x=166, y=47))
Code:
#define WIN32_LEAN_AND_MEAN #include <QApplication> #include <QLabel> #include <QWidget> #include <Windows.h> class RootWidget : public QWidget { protected: bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override { MSG *msg = reinterpret_cast<MSG *>(message); switch (msg->message) { case WM_NCCALCSIZE: *result = 0; return true; case WM_NCHITTEST: // just to be able to move it around *result = HTCAPTION; return true; case WM_SIZE: { UINT width = LOWORD(msg->lParam); UINT height = HIWORD(msg->lParam); qDebug() << "RESIZED" << width << "x" << height; } break; } QWidget::nativeEvent(eventType, message, result); return false; } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); RootWidget root; QLabel lbl("Hello world!", &root); lbl.resize(200, 100); root.show(); return QApplication::exec(); }