How to stop flickering when resizing a frameless GUI?

Leonardo 91 Reputation points
2023-02-16T23:39:56.3366667+00:00

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:

devenv_Usvmhr1VFX

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.

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,887 questions
0 comments No comments
{count} vote

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.