Qt/Windows, resizable frameless window

前端 未结 1 1633
灰色年华
灰色年华 2021-01-14 09:51

I need to create a frameless Qt Windows app that supports resizing.

If I use

setWindowFlags(Qt::FramelessWindowHint);

then I can r

1条回答
  •  执笔经年
    2021-01-14 10:14

    Solved it using WM_NCHITTEST, based on code from https://bugreports.qt.io/browse/QTBUG-40578 (bug report not related to this).

    .h

    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    ......
    protected:
        bool nativeEvent(const QByteArray& eventType, void* message, long* result) override;
    };
    

    .cpp

    bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result)
    {
        MSG* msg = static_cast(message);
    
        if (msg->message == WM_NCHITTEST)
        {
            if (isMaximized())
            {
                return false;
            }
    
            *result = 0;
            const LONG borderWidth = 8;
            RECT winrect;
            GetWindowRect(reinterpret_cast(winId()), &winrect);
    
            // must be short to correctly work with multiple monitors (negative coordinates)
            short x = msg->lParam & 0x0000FFFF;
            short y = (msg->lParam & 0xFFFF0000) >> 16;
    
            bool resizeWidth = minimumWidth() != maximumWidth();
            bool resizeHeight = minimumHeight() != maximumHeight();
            if (resizeWidth)
            {
                //left border
                if (x >= winrect.left && x < winrect.left + borderWidth)
                {
                    *result = HTLEFT;
                }
                //right border
                if (x < winrect.right && x >= winrect.right - borderWidth)
                {
                    *result = HTRIGHT;
                }
            }
            if (resizeHeight)
            {
                //bottom border
                if (y < winrect.bottom && y >= winrect.bottom - borderWidth)
                {
                    *result = HTBOTTOM;
                }
                //top border
                if (y >= winrect.top && y < winrect.top + borderWidth)
                {
                    *result = HTTOP;
                }
            }
            if (resizeWidth && resizeHeight)
            {
                //bottom left corner
                if (x >= winrect.left && x < winrect.left + borderWidth &&
                    y < winrect.bottom && y >= winrect.bottom - borderWidth)
                {
                    *result = HTBOTTOMLEFT;
                }
                //bottom right corner
                if (x < winrect.right && x >= winrect.right - borderWidth &&
                    y < winrect.bottom && y >= winrect.bottom - borderWidth)
                {
                    *result = HTBOTTOMRIGHT;
                }
                //top left corner
                if (x >= winrect.left && x < winrect.left + borderWidth &&
                    y >= winrect.top && y < winrect.top + borderWidth)
                {
                    *result = HTTOPLEFT;
                }
                //top right corner
                if (x < winrect.right && x >= winrect.right - borderWidth &&
                    y >= winrect.top && y < winrect.top + borderWidth)
                {
                    *result = HTTOPRIGHT;
                }
            }
    
            if (*result != 0)
                return true;
    
            QWidget *action = QApplication::widgetAt(QCursor::pos());
            if (action == this){
                *result = HTCAPTION;
                return true;
            }
        }
    
        return false;
    }
    

    implementation from Qt: Resize borderless widget did not work well: sometimes the window is moved during resizing (even in the first version without dragging)

    0 讨论(0)
提交回复
热议问题