Максимальный размер окна без рамки Qt + WinAPI больше, чем доступная геометрия()C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Максимальный размер окна без рамки Qt + WinAPI больше, чем доступная геометрия()

Сообщение Anonymous »

Я пытаюсь решить следующую проблему. Верхний левый угол моего окна имеет отрицательные координаты при максимизации (и x, и y равны -9), и его размер на самом деле больше, чем доступная область.
Я использую WinAPI, чтобы получить некоторые специфичные для платформы функции, такие как Aero snap, поэтому становится сложно понять, почему именно возникает эта проблема.
В моем окне установлены следующие стили и атрибуты:

Код: Выделить всё

setFlags(Qt::Window | Qt::FramelessWindowHint);
SetWindowLongPtr((HWND)winId(), GWL_STYLE, WS_POPUPWINDOW | WS_CAPTION | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_CLIPCHILDREN);

Код: Выделить всё

WS_CAPTION
аналогичен WS_BORDER | WS_DLGFRAME, поэтому, если я удалю WS_DLGFRAME, максимальный размер будет в порядке, и я вижу, что встроенная анимация максимизации исчезает, но при изменении размера я получаю мерцающую белую рамку из-за WS_SIZEBOX (так же, как WS_THICKFRAME). Без WS_SIZEBOX я теряю аэропривязку.
Я подумал, что, возможно, смогу сделать что-нибудь с максимальным размером в NativeEvent, поэтому попробовал следующее:

Код: Выделить всё

bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result)
{
if (auto* msg = static_cast(message); msg->message == WM_NCCALCSIZE)
{
NCCALCSIZE_PARAMS& params = *reinterpret_cast(msg->lParam);
if (params.rgrc[0].top != 0)
{
--params.rgrc[0].top;
}
*result = WVR_REDRAW;
return true; //this removes the native border and title
}
else if (msg->message == WM_GETMINMAXINFO)
{
if (IsMaximized((HWND)winId()))
{
MINMAXINFO* mmi = (MINMAXINFO*)msg->lParam;
auto g = screen()->availableGeometry();
mmi->ptMaxTrackSize.x = g.width() * devicePixelRatio();
mmi->ptMaxTrackSize.y = g.height() * devicePixelRatio();
*result = 0;
return true;
}
}

return QQuickWindow::nativeEvent(eventType, message, result);
}
По какой-то причине перегрузка MINMAXINFO ничего не дает, пока я не установлю mmi->ptMaxTrackSize.x = g.width() * devicePixelRatio() - 1;. В данном случае размер почти хороший, за исключением того, что между правой границей экрана и окном есть пустой зазор в 1 пиксель. Поэтому я не могу получить правильный размер, изменив MINMAXINFO, потому что реальный правильный размер должен быть таким же, как в приведенном выше коде. Начальный ptMaxTrackSize довольно странный: 3462, 1462 в mmi против 3440, 1390 в AvailableGeometry).
Я могу сделать что-то подобное, но я бы мне нравится сохранять состояние QWindow::Maximized, которое сбрасывается, когда я вызываю setGeometry.

Код: Выделить всё

bool FramelessWindow::eventFilter(QObject* watched, QEvent* event)
{
if (event->type() == QEvent::WindowStateChange && QWindow::visibility() == QWindow::Maximized)
{
setGeometry(screen()->availableGeometry()); //the window is no longer maximized
return true;
}

return QQuickWindow::eventFilter(watched, event);
}
Поскольку я не могу использовать QWindow::Maximized в подходе setGeometry, этот подход эквивалентен реализации моего собственного максимизации, нормализации и т. д., что нежелательно и не влияет на развертывание с помощью aero.
Я также пытался добавить поля в развернутом состоянии, но создание макета вызывает уродливое мерцание при изменении размера, поскольку экземпляр моего окна создается в QML. И я не могу использовать setLayout и попытаться добавить поля в код C++, потому что мой класс унаследовал QQuickWindow.
Я что-то упустил?
UPD:
Теперь я обнаружил, что эта проблема в основном связана с безфреймовостью WinAPI+, а не с Qt, так что не только у пользователей Qt возникают "расширения окон" за пределами экрана при максимизации".
Это немного помогает, по крайней мере, теперь я могу протестировать уже существующие решения WinAPI, но проблема в том, что они не работают должным образом.
Я пробовал изменить NCCALCSIZE_PARAMS при обработке сообщения WM_NCCALCSIZE:
Вот что я получил в rgrc[0]:< /p>
Изображение

Что я пробовал по коду melak47:

Код: Выделить всё

void adjustMaximized(HWND hwnd, RECT& rect)
{
auto monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
if (!monitor)
{
return;
}
MONITORINFO monitor_info{};
monitor_info.cbSize = sizeof(monitor_info);
if (!::GetMonitorInfoW(monitor, &monitor_info))
{
return;
}
rect = monitor_info.rcWork;
}

bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result)
{
if (auto* msg = static_cast(message); msg->message == WM_NCCALCSIZE)
{
NCCALCSIZE_PARAMS& params = *reinterpret_cast(msg->lParam);
if (params.rgrc[0].top != 0)
{
--params.rgrc[0].top;
}
if (IsMaximized(hwnd_))
{
adjustMaximized(hwnd_, params.rgrc[0]);
}
return true;
}
...
}
Мой верхний правый угол становится еще хуже:
Изображение


Подробнее здесь: https://stackoverflow.com/questions/782 ... legeometry
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»