How to stop flickering when resizing a frameless GUI?
I'm working with Qt/C++ on Windows 10, I'm building a frameless window and after a lot of research I partially fixed all flickering issues when resizing it.
In the code below, the GUI starts flickering when it get partially maximized, generally when this transparent rectangle thing appears and you release the button:
I recorded a video that demonstrate the flickering issue:
https://www.youtube.com/watch?v=7_mHYxfA7LM
Full working compilable example:
//main.cpp
#include "MainWindow.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
//mainwindow.h
#include <QtWidgets>
#include "ui_MainWindow.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindowClass; };
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
LONG mainwindow_border_width = 10;
bool resizable = true;
private:
Ui::MainWindowClass *ui;
protected:
virtual bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
};
// mainwindow.cpp
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindowClass()) {
ui->setupUi(this);
QGridLayout* layout = new QGridLayout(ui->centralWidget);
QLabel* label = new QLabel(this);
label->setScaledContents(true);
label->setPixmap(QPixmap("C:/Users/dog.jpg"));
layout->addWidget(label);
}
bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) {
MSG* msg = static_cast<MSG*>(message);
switch (msg->message) {
case WM_NCCALCSIZE: {
NCCALCSIZE_PARAMS& params =
if (params.rgrc[0].top != 0)
params.rgrc[0].top -= 1;
// This kills the window frame and title bar.
*result = WVR_REDRAW;
return true;
}
case WM_NCHITTEST:
{
*result = 0;
short x = msg->lParam & 0x0000FFFF;
short y = (msg->lParam & 0xFFFF0000) >> 16;
RECT winrect;
GetWindowRect(HWND(this->winId()), &winrect);
if(resizable) {
bool resizeWidth = minimumWidth() != maximumWidth();
bool resizeHeight = minimumHeight() != maximumHeight();
if(resizeWidth) {
if (x >= winrect.left && x < winrect.left + mainwindow_border_width)
*result = HTLEFT; //left border
if (x < winrect.right && x >= winrect.right - mainwindow_border_width)
*result = HTRIGHT; //right border
}
if(resizeHeight) {
if (y < winrect.bottom && y >= winrect.bottom - mainwindow_border_width)
*result = HTBOTTOM; //bottom border
if (y >= winrect.top && y < winrect.top + mainwindow_border_width)
*result = HTTOP; //top border
}
if(resizeWidth && resizeHeight) {
if (x >= winrect.left && x < winrect.left + mainwindow_border_width &&
y < winrect.bottom && y >= winrect.bottom - mainwindow_border_width)
*result = HTBOTTOMLEFT; //bottom left corner
if (x < winrect.right && x >= winrect.right - mainwindow_border_width &&
y < winrect.bottom && y >= winrect.bottom - mainwindow_border_width)
*result = HTBOTTOMRIGHT; //bottom right corner
if (x >= winrect.left && x < winrect.left + mainwindow_border_width &&
y >= winrect.top && y < winrect.top + mainwindow_border_width)
*result = HTTOPLEFT; //top left corner
if (x < winrect.right && x >= winrect.right - mainwindow_border_width &&
y >= winrect.top && y < winrect.top + mainwindow_border_width)
*result = HTTOPRIGHT; //top right corner
}
}
if (0 != *result)
return true;
return false;
}
default:
return QMainWindow::nativeEvent(eventType, message, result);
}
return QWidget::nativeEvent(eventType, message, result);
}
I think the problem is inside the case WM_NCCALCSIZE:
when params.rgrc[0].top
is 0.
I'm using Qt 6.3, compiling on Visual Studio 2022. The code is compilable in any recently Qt version.
I tried getting help with this issue on Qt forum, but i didn't got any reply, as this is mostly WINAPI
, I wonder if I could ask for help on this task here.