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.