Неправильное поведение окна при рисовании в безрамочном окне Qt (win32)

У меня есть приложение QML (также протестировано с QWidgets, та же проблема), и чтобы сделать его без полей (но при этом поддерживать собственные функции WM, такие как aero snap и т. д.), я следовал это путем реализации QAbstractNativeEventFilter и ответа на сигнал WM_NCCALSIZE нулем:

switch(msg->message) {
  case WM_NCCALCSIZE:
    *r = 0;
    return 1;
    ...
}

Я также установил некоторые флаги окна, которых нет в пространстве имен Qt, с помощью

SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME);

Это отлично работает до тех пор, пока я не перемещу или не изменю размер окна, что приведет к повторному рендерингу Qt, а ширина неокрашенной области будет равна ширине заголовка и границ:

Перед перемещением/изменением размера До

После перемещения/изменения размера После

Я также нашел обходной путь для этого, добавив флаг FramelessWindowHint в Qt:

window->setFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::Dialog);

Но теперь эти поля возникают снова при изменении состояния окна (максимизация, минимизация,...). Например, блокируя событие WM_SIZE, когда SIZE_MAXIMIZED является параметром, поле не отображается, но тогда я также не могу развернуть окно из Qt. Это означает, что это проблема стороны Qt.

Я также заметил, проверив стиль окна с помощью wspector, что после того, как я его максимизировал, появляется новый атом свойства:

скриншот инспектора

Можете ли вы помочь мне исправить это?


person Community    schedule 06.02.2014    source источник
comment
Сорри, это Qt версии 5.2   -  person    schedule 07.02.2014


Ответы (2)


Я думаю, что использование SetWindowLong в вашем дескрипторе окна и использование флагов окна Qt/атрибутов виджета Qt вызывает проблемы. Вы можете пойти и посмотреть исходный код Qt, чтобы увидеть, что происходит при обработке этих флагов окна.

Когда я создавал окна без рамок, я обычно делал это, чтобы предотвратить перемещение и изменение размера, потому что я управляю всем этим отдельно.

Одна проблема, с которой я столкнулся, заключалась в том, что когда экранная клавиатура появлялась и пристыковывалась, она изменяла размер моих окон. Таким образом, помимо вызова resize(), мне также пришлось использовать setFixedSize, чтобы предотвратить манипулирование моим виджетом, когда операционная система пыталась изменить размер окна.

Другими словами, я бы добавил приложение QShortcut для всего приложения, прислушиваясь к быстрым сочетаниям клавиш и изменяя размер вашего окна так, как вы хотите, когда это происходит, если вы управляете безрамочным окном.

Надеюсь, это поможет.

person phyatt    schedule 04.04.2014
comment
Причина, по которой я делаю это таким образом, заключается в том, что я хочу поддерживать встроенные функции платформы, такие как перетаскивание для изменения размера и включение эффекта тени. Тем временем мне удалось заставить его работать, как задумано, но это больше похоже на грязный обходной путь, а на решение. - person ; 08.04.2014

Интересно, было ли это недостатком ретрансляции сообщений Qt, потому что я столкнулся с аналогичной проблемой, которая возникает во вложенных окнах. Если вы нажмете кнопку SIZE_MAXIMIZE или SIZE_MINIMIZE родительского окна, дочернее окно иногда не сможет получить сообщение WM_SIZE. Я полагаю, что есть примерно два решения: 1. Исправить Qt, 2. Обойти это.

Здесь у меня есть дочернее окно рендеринга OGL, иногда даже сообщение WM_SIZE передается неправильно. То есть, если вы измените размер родительского окна, вы получите часть клиентской области черной.

Я просто использую простой обходной путь, чтобы исправить это, который проверяет текущий размер с кешированным и делает своего рода изменение размера вручную.

person Alex    schedule 01.08.2016