examples/shared/widgetframe/windowbar.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/core/contexts/win32windowcontext.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/widgets/widgetwindowagent.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/widgets/widgetwindowagent_p.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
examples/shared/widgetframe/windowbar.cpp
@@ -248,23 +248,26 @@ QLabel *label = titleLabel(); QAbstractButton *maxBtn = maxButton(); switch (event->type()) { case QEvent::WindowIconChange: case QEvent::WindowIconChange: { if (d_ptr->autoIcon && iconBtn) { iconBtn->setIcon(w->windowIcon()); iconChanged(w->windowIcon()); } break; case QEvent::WindowTitleChange: } case QEvent::WindowTitleChange: { if (d_ptr->autoTitle && label) { label->setText(w->windowTitle()); titleChanged(w->windowTitle()); } break; case QEvent::WindowStateChange: } case QEvent::WindowStateChange: { if (maxBtn) { maxBtn->setChecked(w->isMaximized()); } break; } default: break; } src/core/contexts/win32windowcontext.cpp
@@ -749,33 +749,13 @@ return ::DefWindowProcW(hWnd, message, wParam, lParam); } switch (message) { case WM_NCCALCSIZE: { // Since Qt does the necessary processing of the WM_NCCALCSIZE message, we need to // forward it right away and process it in our native event filter. WindowsNativeEventFilter::lastMessageContext = ctx; LRESULT result = ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam); WindowsNativeEventFilter::lastMessageContext = nullptr; return result; } case WM_WINDOWPOSCHANGING: { // When toggling the "Show theme color in title bar and window border" setting in // Windows Settings, or calling `DrawMenuBar()`, Windows sends a message of // WM_WINDOWPOSCHANGING with flags 0x37. If we do not process this message, // the client area as a whole will shift to the left, which looks very abnormal if // we don't repaint it. This exception disappears if we add SWP_NOCOPYBITS flag. // But I don't know what caused the problem, or why this would solve it. const auto windowPos = reinterpret_cast<LPWINDOWPOS>(lParam); if (windowPos->flags == (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED)) { windowPos->flags |= SWP_NOCOPYBITS; } return ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam); } default: break; // Since Qt does the necessary processing of the WM_NCCALCSIZE message, we need to // forward it right away and process it in our native event filter. if (message == WM_NCCALCSIZE) { WindowsNativeEventFilter::lastMessageContext = ctx; LRESULT result = ::CallWindowProcW(g_qtWindowProc, hWnd, message, wParam, lParam); WindowsNativeEventFilter::lastMessageContext = nullptr; return result; } // Try hooked procedure and save result @@ -1250,6 +1230,7 @@ } break; } case WM_NCHITTEST: { // 原生Win32窗口只有顶边是在窗口内部resize的,其余三边都是在窗口 // 外部进行resize的,其原理是,WS_THICKFRAME这个窗口样式会在窗 @@ -1538,9 +1519,27 @@ return true; } } case WM_WINDOWPOSCHANGING: { // ### FIXME: How does this problem happen and why is it solved? // When toggling the "Show theme color in title bar and window border" setting in // Windows Settings, or calling `DrawMenuBar()`, Windows sends a message of // WM_WINDOWPOSCHANGING with flags 0x37. If we do not process this message, // the client area as a whole will shift to the left, which looks very abnormal if // we don't repaint it. This exception disappears if we add SWP_NOCOPYBITS flag. // But I don't know what caused the problem, or why this would solve it. const auto windowPos = reinterpret_cast<LPWINDOWPOS>(lParam); if (windowPos->flags == (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED)) { windowPos->flags |= SWP_NOCOPYBITS; } break; } default: break; } if (!isWin10OrGreater()) { switch (message) { case WM_NCUAHDRAWCAPTION: src/widgets/widgetwindowagent.cpp
@@ -3,25 +3,38 @@ #include <QtGui/QtEvents> #include <QtGui/QPainter> #include <QtCore/QDebug> #include "widgetitemdelegate_p.h" namespace QWK { class WidgetPaintFilter : public QObject { class WidgetBorderHandler : public QObject { public: WidgetPaintFilter(QWidget *widget, AbstractWindowContext *ctx) : widget(widget), ctx(ctx) { WidgetBorderHandler(QWidget *widget, AbstractWindowContext *ctx) : widget(widget), ctx(ctx) { widget->installEventFilter(this); } void updateMargins() { if (widget->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) { widget->setContentsMargins({}); } else { widget->setContentsMargins({0, 1, 0, 0}); } } protected: bool eventFilter(QObject *obj, QEvent *event) override { switch (event->type()) { case QEvent::Paint: { auto pe = static_cast<QPaintEvent *>(event); if (widget->windowState() & (Qt::WindowMaximized | Qt::WindowFullScreen)) break; auto paintEvent = static_cast<QPaintEvent *>(event); QPainter painter(widget); QRect rect = pe->rect(); QRegion region = pe->region(); QRect rect = paintEvent->rect(); QRegion region = paintEvent->region(); void *args[] = { &painter, &rect, @@ -29,6 +42,11 @@ }; ctx->virtual_hook(AbstractWindowContext::DrawBordersHook, args); return true; } case QEvent::WindowStateChange: { updateMargins(); break; } default: break; @@ -79,13 +97,10 @@ if (bool needPaintBorder = false; d->context->virtual_hook(AbstractWindowContext::NeedsDrawBordersHook, &needPaintBorder), needPaintBorder) { d->paintFilter = std::make_unique<WidgetPaintFilter>(w, d->context.get()); auto borderHandler = std::make_unique<WidgetBorderHandler>(w, d->context.get()); borderHandler->updateMargins(); d->borderHandler = std::move(borderHandler); } if (d->context->key() == "win32") { w->setContentsMargins(0, 1, 0, 0); } return true; } src/widgets/widgetwindowagent_p.h
@@ -6,6 +6,8 @@ namespace QWK { class WidgetBorderHandler; class WidgetWindowAgentPrivate : public WindowAgentBasePrivate { Q_DECLARE_PUBLIC(WidgetWindowAgent) public: @@ -17,7 +19,7 @@ // Host QWidget *hostWidget{}; std::unique_ptr<QObject> paintFilter; std::unique_ptr<WidgetBorderHandler> borderHandler; }; }