3

I am using Qt5.

When I resize the window I would like to keep the aspect ratio of the window, so the height have to be equal to the width.

I am not using layout, I have implemented my own resizeEvent in the MainWindow class, when I resize the window everything resize with it.

I have read the following stackoverflow questions, but they did not help me:

1 Answers1

0

We got a solution by intercepting the nativeEvent:

#include <Windows.h>

// Utility Functions
int rectWidth(RECT* r)
{
    return r->right - r->left;
}

int rectHeight(RECT *r)
{
    return r->bottom - r->top;
}

// these functions should have the same resulting aspect ratio
int MainWindow::heightForWidth(int width) const
{
    return width / 1 / 1; // /aspect ratio
}

// these functions should have the same resulting aspect ratio
int MainWindow::widthForHeight(int height) const
{
    return height * 1 / 1; // *aspectRatio
}

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    // Intercept Windows event
    if(eventType == "windows_generic_MSG")
    {
        MSG* msg = static_cast<MSG*>(message);

        if(msg->message == WM_SIZING)
        {
            RECT *rect = (RECT*)(msg->lParam);

            // Overwrite the right parameter with the calculated value:
            switch(msg->wParam)
            {
            case WMSZ_BOTTOMRIGHT:
                if(rectWidth(rect) < rectHeight(rect)) goto wmsz_bottom;
                else goto wmsz_right; // Always wanted to use goto
                break;
            case WMSZ_BOTTOM:
                wmsz_bottom:
                rect->right = rect->left + widthForHeight(rectHeight(rect));
                break;
            case WMSZ_RIGHT:
                wmsz_right:
                rect->bottom = rect->top + heightForWidth(rectWidth(rect));
                break;
            case WMSZ_TOPLEFT:
                if(rectWidth(rect) < rectHeight(rect)) goto wmsz_top;
                else goto wmsz_left; // goto away, wheeeeee
                break;
            case WMSZ_TOP:
                wmsz_top:
                rect->left = rect->right - widthForHeight(rectHeight(rect));
                break;
            case WMSZ_LEFT:
                wmsz_left:
                rect->top = rect->bottom - heightForWidth(rectWidth(rect));
                break;
            }
        }
    }

    // Pass the modified Windows Message to the original event handler
    return QMainWindow::nativeEvent(eventType, message, result);
}

Tested with Qt5.15.2 and Windows 10. But since the Windows API and Qt5 API are very stable this should work with all reasonably old versions.

Baumflaum
  • 749
  • 7
  • 20
  • 1
    It keeps the aspect ration of the window, but the hight not equal to the width. –  Jul 30 '21 at 15:24
  • 1
    Then change the `heightForWidth()` and `widthForHeight()` constraints. – Baumflaum Jul 30 '21 at 15:26
  • 2
    I know that, just edit your answare, and you forget to mention that to include `windows.h`, if you edit your answare I will mark this as the answare. –  Jul 30 '21 at 15:31