stdware / qwindowkit

Cross-platform frameless window framework for Qt. Support Windows, macOS, Linux.
Apache License 2.0
490 stars 78 forks source link

Provide a way that can disable user to resize window by dragging borders #45

Closed Ikok9c6s closed 6 months ago

Ikok9c6s commented 6 months ago

What I want is that we can resize the window programmatically, but disable user to resize window by dragging borders. In previous project , I find that setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) works as isWidgetFixedSize(in framelesswidgetshelper.cpp line 133) takes sizePolicy into account. But in current project, the feature disappears, and I don't know how to modify code to achieve the same functionality. Can you restore the logic of FramelessHelper or tell me another way to do it? Thanks for reading and hope for your reply!

image

SineStriker commented 6 months ago

QSizePolicy only works when the widget is in a layout because you can't disable the user from resizing the window by setting a fixed size policy when you use a plain Qt window, so FramelessHelper shouldn't do this as well. It's a mistake that FramelessHelper made, we have removed it in QWindowKit. You should use setFixedSize or set Qt::MSWindowsFixedSizeDialogHint flag.

Ikok9c6s commented 6 months ago

I forget to say that I need to change the feature(whether user can resize window by dragging borders or not) frequently when the window is shown. And after testing two methods you mentioned above, I think neither of the two methods is appropriate. Reasons are as follows. For setFixedSize: after calling it, QWidget::resize can't work, so I need to call resizeor setFixedSize according to property resizable, it's cumbersome and when downstream developers cast the dialog as QWidgetor QDialog, it gets worse. Any way, the feature is not equal to fixedSize, it should be anything like user-fixed. For Qt::MSWindowsFixedSizeDialogHint: if you change windowFlags when the window is visible, it will hide because setParentis called in it. And the worst part is once the flag is set, a resize error occurs in dpi scale when move window between screens(tested in 1920*1080 100% and 150%). image

Ikok9c6s commented 6 months ago

I agree with you that the feature has nothing to do with QSizePolicy, so could you please just add a flag to describe it and expose the api to change it separately?

SineStriker commented 6 months ago

I agree with you that the feature has nothing to do with QSizePolicy, so could you please just add a flag to describe it and expose the api to change it separately?

我认为你应该在正常的Qt窗口里尝试你想要的功能,如果正常窗口都没有这种功能,那么QWK也不会实现,没有必要实现这种多余的功能。

Ikok9c6s commented 6 months ago

我之前就是在WM_NCHITTEST中根据是否允许用户resize的flag,选择性进行HTLEFT等边框的判断。 QWK处理了WM_NCHITTEST并且没有给使用者提供修改的方式,这个功能的确和QWK无关,但是QWK也限制了使用者处理该消息,这是否不太合理呢?

SineStriker commented 6 months ago

Author

你的意思是,你在自己的全局nativeEventFilter或者窗口重写的nativeEventFilter中处理了WM_NCHITTEST,处理结果仍然会被QWK的覆盖是吗?

Ikok9c6s commented 6 months ago

调试下来是这样的,QWKHookedWndProc执行在Qt的qWindowsWndProc之前

SineStriker commented 6 months ago

你说的这个确实是个问题,我想办法做一些修改让你能继续处理你的事件。

SineStriker commented 6 months ago

代码已提交,你可以试试看在你的窗口中重写nativeEvent,类似如下逻辑,应该可以禁止用户调整大小。

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) {
    Q_UNUSED(eventType)

    auto msg = reinterpret_cast<MSG *>(message);
    if (msg->message == WM_NCHITTEST) {
        auto &res = *result;
        if (res >= HTLEFT && res <= HTBOTTOMRIGHT) {
            res = HTBORDER;
            return true;
        }
    }
    return false;
}