#include "ElaDockWidget.h" #include #include #include #include #include #include #include "ElaApplication.h" #include "ElaDockWidgetPrivate.h" #include "ElaDockWidgetTitleBar.h" #include "ElaTheme.h" #include "ElaWinShadowHelper.h" ElaDockWidget::ElaDockWidget(QWidget* parent, Qt::WindowFlags flags) : QDockWidget(parent, flags), d_ptr(new ElaDockWidgetPrivate()) { Q_D(ElaDockWidget); d->q_ptr = this; setObjectName("ElaDockWidget"); d->_titleBar = new ElaDockWidgetTitleBar(this); setTitleBarWidget(d->_titleBar); // 主题变更动画 d->_themeMode = eTheme->getThemeMode(); connect(eTheme, &ElaTheme::themeModeChanged, d, &ElaDockWidgetPrivate::onThemeModeChanged); d->_windowDisplayMode = eApp->getWindowDisplayMode(); connect(eApp, &ElaApplication::pWindowDisplayModeChanged, this, [=]() { d->_windowDisplayMode = eApp->getWindowDisplayMode(); update(); }); connect(this, &ElaDockWidget::topLevelChanged, this, [=](bool topLevel) { if (eApp->getWindowDisplayMode() == ElaApplicationType::WindowDisplayMode::ElaMica) { eApp->syncWindowDisplayMode(this, topLevel); } }); } ElaDockWidget::ElaDockWidget(const QString& title, QWidget* parent, Qt::WindowFlags flags) : ElaDockWidget(parent, flags) { this->setWindowTitle(title); } ElaDockWidget::~ElaDockWidget() { } void ElaDockWidget::paintEvent(QPaintEvent* event) { Q_D(ElaDockWidget); if (isFloating()) { QPainter painter(this); painter.save(); painter.setRenderHints(QPainter::Antialiasing); #ifdef Q_OS_WIN // 背景 if (d->_windowDisplayMode != ElaApplicationType::WindowDisplayMode::ElaMica) { painter.setPen(Qt::NoPen); painter.setBrush(ElaThemeColor(d->_themeMode, DialogBase)); painter.drawRect(rect()); } #else // 背景 painter.setPen(Qt::NoPen); painter.setBrush(d->_windowDisplayMode == ElaApplicationType::WindowDisplayMode::ElaMica ? Qt::transparent : ElaThemeColor(d->_themeMode, DialogBase)); QRect foregroundRect(d->_shadowBorderWidth, d->_shadowBorderWidth, width() - 2 * d->_shadowBorderWidth, height() - 2 * d->_shadowBorderWidth); painter.drawRect(rect()); #endif painter.restore(); } QDockWidget::paintEvent(event); } #ifdef Q_OS_WIN bool ElaDockWidget::event(QEvent* event) { Q_D(ElaDockWidget); switch (event->type()) { case QEvent::Show: case QEvent::MouseButtonRelease: { HWND hwnd = (HWND)d->_currentWinID; DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE); ::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME); ElaWinShadowHelper::getInstance()->setWindowShadow(d->_currentWinID); #if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 3) && QT_VERSION <= QT_VERSION_CHECK(6, 6, 1)) bool hasCaption = (style & WS_CAPTION) == WS_CAPTION; if (!hasCaption) { ::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_CAPTION); } #endif break; } default: { break; } } return QDockWidget::event(event); } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) bool ElaDockWidget::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) #else bool ElaDockWidget::nativeEvent(const QByteArray& eventType, void* message, long* result) #endif { Q_D(ElaDockWidget); if ((eventType != "windows_generic_MSG") || !message) { return false; } const auto msg = static_cast(message); const HWND hwnd = msg->hwnd; if (!hwnd || !msg) { return false; } d->_currentWinID = (qint64)hwnd; const UINT uMsg = msg->message; const WPARAM wParam = msg->wParam; const LPARAM lParam = msg->lParam; switch (uMsg) { case WM_WINDOWPOSCHANGING: { WINDOWPOS* wp = reinterpret_cast(lParam); if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0) { wp->flags |= SWP_NOCOPYBITS; *result = ::DefWindowProcW(hwnd, uMsg, wParam, lParam); return true; } return false; } case WM_NCACTIVATE: { *result = TRUE; return true; } case WM_NCHITTEST: { POINT nativeLocalPos{GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; ::ScreenToClient(hwnd, &nativeLocalPos); RECT clientRect{0, 0, 0, 0}; ::GetClientRect(hwnd, &clientRect); auto clientWidth = clientRect.right - clientRect.left; auto clientHeight = clientRect.bottom - clientRect.top; bool left = nativeLocalPos.x < d->_margins; bool right = nativeLocalPos.x > clientWidth - d->_margins; bool top = nativeLocalPos.y < d->_margins; bool bottom = nativeLocalPos.y > clientHeight - d->_margins; *result = 0; if (!window()->isFullScreen() && !window()->isMaximized()) { if (left && top) { *result = HTTOPLEFT; } else if (left && bottom) { *result = HTBOTTOMLEFT; } else if (right && top) { *result = HTTOPRIGHT; } else if (right && bottom) { *result = HTBOTTOMRIGHT; } else if (left) { *result = HTLEFT; } else if (right) { *result = HTRIGHT; } else if (top) { *result = HTTOP; } else if (bottom) { *result = HTBOTTOM; } } if (0 != *result) { return true; } *result = HTCLIENT; return true; } case WM_NCCALCSIZE: { if (wParam == FALSE) { return false; } *result = 0; return true; } } return QDockWidget::nativeEvent(eventType, message, result); } #endif