When the window resize keep the aspect ratio

Viewed 367
1 Answers

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.

Related