Files
cbh/ElaWidgetTools/ElaAppBar.cpp
2025-09-19 22:40:52 +08:00

920 lines
29 KiB
C++

#include "ElaAppBar.h"
#include <QApplication>
#include <QDebug>
#include "ElaText.h"
#include "ElaToolButton.h"
#include "ElaWinShadowHelper.h"
#ifndef Q_OS_WIN
#include <QDateTime>
#include <QWindow>
#endif
#include <QGuiApplication>
#include <QHBoxLayout>
#include <QLabel>
#include <QMouseEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <QScreen>
#include <QTimer>
#include <QVBoxLayout>
#include "ElaDef.h"
#include "ElaEventBus.h"
#include "ElaIconButton.h"
#include "ElaTheme.h"
#include "private/ElaAppBarPrivate.h"
Q_PROPERTY_CREATE_Q_CPP(ElaAppBar, bool, IsStayTop)
Q_PROPERTY_CREATE_Q_CPP(ElaAppBar, bool, IsDefaultClosed)
Q_PROPERTY_CREATE_Q_CPP(ElaAppBar, bool, IsOnlyAllowMinAndClose)
ElaAppBar::ElaAppBar(QWidget* parent)
: QWidget{parent}, d_ptr(new ElaAppBarPrivate())
{
Q_D(ElaAppBar);
d->_buttonFlags = ElaAppBarType::RouteBackButtonHint | ElaAppBarType::StayTopButtonHint | ElaAppBarType::ThemeChangeButtonHint | ElaAppBarType::MinimizeButtonHint | ElaAppBarType::MaximizeButtonHint | ElaAppBarType::CloseButtonHint;
window()->setAttribute(Qt::WA_Mapped);
d->_pAppBarHeight = 45;
setFixedHeight(d->_pAppBarHeight);
window()->setContentsMargins(0, this->height(), 0, 0);
d->q_ptr = this;
d->_pIsStayTop = false;
d->_pIsFixedSize = false;
d->_pIsDefaultClosed = true;
d->_pIsOnlyAllowMinAndClose = false;
d->_pCustomMenu = nullptr;
d->_pCustomWidget = nullptr;
d->_pCustomWidgetMaximumWidth = 550;
window()->installEventFilter(this);
#ifdef Q_OS_WIN
if (!eWinHelper->getIsWinVersionGreater10())
{
d->_win7Margins = 8;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 3) && QT_VERSION <= QT_VERSION_CHECK(6, 6, 1))
window()->setWindowFlags((window()->windowFlags()) | Qt::WindowMinimizeButtonHint | Qt::FramelessWindowHint);
#endif
#else
window()->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint | Qt::WindowFullscreenButtonHint | Qt::WindowSystemMenuHint);
#endif
setMouseTracking(true);
setObjectName("ElaAppBar");
setStyleSheet("#ElaAppBar{background-color:transparent;}");
d->_routeBackButton = new ElaToolButton(this);
d->_routeBackButton->setElaIcon(ElaIconType::ArrowLeft);
d->_routeBackButton->setFixedSize(40, 30);
d->_routeBackButton->setEnabled(false);
// 路由跳转
connect(d->_routeBackButton, &ElaIconButton::clicked, this, &ElaAppBar::routeBackButtonClicked);
// 导航栏展开按钮
d->_navigationButton = new ElaToolButton(this);
d->_navigationButton->setElaIcon(ElaIconType::Bars);
d->_navigationButton->setFixedSize(40, 30);
d->_navigationButton->setObjectName("NavigationButton");
d->_navigationButton->setVisible(false);
// 展开导航栏
connect(d->_navigationButton, &ElaIconButton::clicked, this, &ElaAppBar::navigationButtonClicked);
// 设置置顶
d->_stayTopButton = new ElaToolButton(this);
d->_stayTopButton->setElaIcon(ElaIconType::ArrowUpToArc);
d->_stayTopButton->setFixedSize(40, 30);
connect(d->_stayTopButton, &ElaIconButton::clicked, this, [=]() {
this->setIsStayTop(!this->getIsStayTop());
});
connect(this, &ElaAppBar::pIsStayTopChanged, d, &ElaAppBarPrivate::onStayTopButtonClicked);
//图标
d->_iconLabel = new QLabel(this);
d->_iconLabelLayout = d->_createVLayout(d->_iconLabel);
if (parent->windowIcon().isNull())
{
d->_iconLabel->setVisible(false);
}
else
{
d->_iconLabel->setPixmap(parent->windowIcon().pixmap(18, 18));
d->_iconLabelLayout->setContentsMargins(10, 0, 0, 0);
}
connect(parent, &QWidget::windowIconChanged, this, [=](const QIcon& icon) {
d->_iconLabel->setPixmap(icon.pixmap(18, 18));
d->_iconLabel->setVisible(!icon.isNull());
d->_iconLabelLayout->setContentsMargins(icon.isNull() ? 0 : 10, 0, 0, 0);
});
//标题
d->_titleLabel = new ElaText(this);
d->_titleLabel->setIsWrapAnywhere(false);
d->_titleLabel->setTextPixelSize(13);
d->_titleLabelLayout = d->_createVLayout(d->_titleLabel);
if (parent->windowTitle().isEmpty())
{
d->_titleLabel->setVisible(false);
}
else
{
d->_titleLabel->setText(parent->windowTitle());
d->_titleLabelLayout->setContentsMargins(10, 0, 0, 0);
}
connect(parent, &QWidget::windowTitleChanged, this, [=](const QString& title) {
d->_titleLabel->setText(title);
d->_titleLabel->setVisible(!title.isEmpty());
d->_titleLabelLayout->setContentsMargins(title.isEmpty() ? 0 : 10, 0, 0, 0);
});
// 主题变更
d->_themeChangeButton = new ElaToolButton(this);
d->_themeChangeButton->setElaIcon(ElaIconType::MoonStars);
d->_themeChangeButton->setFixedSize(40, 30);
connect(d->_themeChangeButton, &ElaIconButton::clicked, this, &ElaAppBar::themeChangeButtonClicked);
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
d->_onThemeModeChange(themeMode);
});
d->_minButton = new ElaToolButton(this);
d->_minButton->setElaIcon(ElaIconType::Dash);
d->_minButton->setFixedSize(40, 30);
connect(d->_minButton, &ElaIconButton::clicked, d, &ElaAppBarPrivate::onMinButtonClicked);
d->_maxButton = new ElaToolButton(this);
d->_maxButton->setIconSize(QSize(18, 18));
d->_maxButton->setElaIcon(ElaIconType::Square);
d->_maxButton->setFixedSize(40, 30);
connect(d->_maxButton, &ElaIconButton::clicked, d, &ElaAppBarPrivate::onMaxButtonClicked);
d->_closeButton = new ElaIconButton(ElaIconType::Xmark, 18, 40, 30, this);
d->_closeButton->setLightHoverColor(QColor(0xE8, 0x11, 0x23));
d->_closeButton->setDarkHoverColor(QColor(0xE8, 0x11, 0x23));
d->_closeButton->setLightHoverIconColor(Qt::white);
d->_closeButton->setDarkHoverIconColor(Qt::white);
connect(d->_closeButton, &ElaIconButton::clicked, d, &ElaAppBarPrivate::onCloseButtonClicked);
d->_mainLayout = new QHBoxLayout(this);
d->_mainLayout->setContentsMargins(0, 0, 0, 0);
d->_mainLayout->setSpacing(0);
d->_mainLayout->addLayout(d->_createVLayout(d->_routeBackButton));
d->_mainLayout->addLayout(d->_createVLayout(d->_navigationButton));
d->_mainLayout->addLayout(d->_iconLabelLayout);
d->_mainLayout->addLayout(d->_titleLabelLayout);
d->_mainLayout->addStretch();
d->_mainLayout->addStretch();
d->_mainLayout->addLayout(d->_createVLayout(d->_stayTopButton));
d->_mainLayout->addLayout(d->_createVLayout(d->_themeChangeButton));
d->_mainLayout->addLayout(d->_createVLayout(d->_minButton));
d->_mainLayout->addLayout(d->_createVLayout(d->_maxButton));
d->_mainLayout->addLayout(d->_createVLayout(d->_closeButton));
#ifdef Q_OS_WIN
for (int i = 0; i < qApp->screens().count(); i++)
{
connect(qApp->screens().at(i), &QScreen::logicalDotsPerInchChanged, this, [=] {
if (d->_pIsFixedSize)
{
HWND hwnd = (HWND)(d->_currentWinID);
SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_FRAMECHANGED);
}
});
}
//主屏幕变更处理
connect(qApp, &QApplication::primaryScreenChanged, this, [=]() {
HWND hwnd = (HWND)(d->_currentWinID);
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
::RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
});
d->_lastScreen = qApp->screenAt(window()->geometry().center());
#endif
d->_themeMode = eTheme->getThemeMode();
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) {
d->_themeMode = themeMode;
update();
});
}
ElaAppBar::~ElaAppBar()
{
}
void ElaAppBar::setAppBarHeight(int height)
{
Q_D(ElaAppBar);
d->_pAppBarHeight = height;
setFixedHeight(d->_pAppBarHeight);
window()->setContentsMargins(0, this->height(), 0, 0);
Q_EMIT pAppBarHeightChanged();
}
int ElaAppBar::getAppBarHeight() const
{
Q_D(const ElaAppBar);
return d->_pAppBarHeight;
}
void ElaAppBar::setCustomWidget(ElaAppBarType::CustomArea customArea, QWidget* widget)
{
Q_D(ElaAppBar);
if (!widget || widget == this)
{
return;
}
widget->setMinimumHeight(0);
widget->setMaximumHeight(height());
widget->setMaximumWidth(d->_pCustomWidgetMaximumWidth);
widget->setParent(this);
if (d->_pCustomWidget)
{
d->_mainLayout->removeWidget(d->_pCustomWidget);
}
switch (customArea)
{
case ElaAppBarType::LeftArea:
{
d->_mainLayout->insertWidget(4, widget);
break;
}
case ElaAppBarType::MiddleArea:
{
d->_mainLayout->insertWidget(5, widget);
break;
}
case ElaAppBarType::RightArea:
{
d->_mainLayout->insertWidget(6, widget);
break;
}
}
d->_pCustomWidget = widget;
Q_EMIT customWidgetChanged();
}
QWidget* ElaAppBar::getCustomWidget() const
{
Q_D(const ElaAppBar);
return d->_pCustomWidget;
}
void ElaAppBar::setCustomMenu(QMenu* customMenu)
{
Q_D(ElaAppBar);
d->_pCustomMenu = customMenu;
Q_EMIT customMenuChanged();
}
QMenu* ElaAppBar::getCustomMenu() const
{
Q_D(const ElaAppBar);
return d->_pCustomMenu;
}
void ElaAppBar::setCustomWidgetMaximumWidth(int width)
{
Q_D(ElaAppBar);
d->_pCustomWidgetMaximumWidth = width;
if (d->_pCustomWidget)
{
d->_pCustomWidget->setMaximumWidth(width);
}
Q_EMIT pCustomWidgetMaximumWidthChanged();
}
int ElaAppBar::getCustomWidgetMaximumWidth() const
{
Q_D(const ElaAppBar);
return d->_pCustomWidgetMaximumWidth;
}
void ElaAppBar::setIsFixedSize(bool isFixedSize)
{
Q_D(ElaAppBar);
d->_pIsFixedSize = isFixedSize;
#ifdef Q_OS_WIN
HWND hwnd = (HWND)d->_currentWinID;
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
if (d->_pIsFixedSize)
{
//切换DPI处理
style &= ~WS_THICKFRAME;
::SetWindowLongPtr(hwnd, GWL_STYLE, style);
}
else
{
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
}
#else
bool isVisible = window()->isVisible();
window()->setWindowFlags((window()->windowFlags()) | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
if (!isFixedSize)
{
window()->setWindowFlag(Qt::WindowMaximizeButtonHint);
}
if (isVisible)
{
window()->show();
}
#endif
Q_EMIT pIsFixedSizeChanged();
}
bool ElaAppBar::getIsFixedSize() const
{
Q_D(const ElaAppBar);
return d->_pIsFixedSize;
}
void ElaAppBar::setWindowButtonFlag(ElaAppBarType::ButtonType buttonFlag, bool isEnable)
{
Q_D(ElaAppBar);
if (isEnable)
{
setWindowButtonFlags(d->_buttonFlags | buttonFlag);
}
else
{
setWindowButtonFlags(d->_buttonFlags & ~buttonFlag);
}
}
void ElaAppBar::setWindowButtonFlags(ElaAppBarType::ButtonFlags buttonFlags)
{
Q_D(ElaAppBar);
d->_buttonFlags = buttonFlags;
if (d->_buttonFlags.testFlag(ElaAppBarType::NoneButtonHint))
{
d->_routeBackButton->setVisible(false);
d->_navigationButton->setVisible(false);
d->_stayTopButton->setVisible(false);
d->_themeChangeButton->setVisible(false);
d->_minButton->setVisible(false);
d->_maxButton->setVisible(false);
d->_closeButton->setVisible(false);
}
else
{
d->_routeBackButton->setVisible(d->_buttonFlags.testFlag(ElaAppBarType::RouteBackButtonHint));
d->_navigationButton->setVisible(d->_buttonFlags.testFlag(ElaAppBarType::NavigationButtonHint));
d->_stayTopButton->setVisible(d->_buttonFlags.testFlag(ElaAppBarType::StayTopButtonHint));
d->_themeChangeButton->setVisible(d->_buttonFlags.testFlag(ElaAppBarType::ThemeChangeButtonHint));
d->_minButton->setVisible(d->_buttonFlags.testFlag(ElaAppBarType::MinimizeButtonHint));
d->_maxButton->setVisible(d->_buttonFlags.testFlag(ElaAppBarType::MaximizeButtonHint));
d->_closeButton->setVisible(d->_buttonFlags.testFlag(ElaAppBarType::CloseButtonHint));
}
}
ElaAppBarType::ButtonFlags ElaAppBar::getWindowButtonFlags() const
{
return d_ptr->_buttonFlags;
}
void ElaAppBar::setRouteBackButtonEnable(bool isEnable)
{
Q_D(ElaAppBar);
d->_routeBackButton->setEnabled(isEnable);
}
void ElaAppBar::closeWindow()
{
Q_D(ElaAppBar);
QPropertyAnimation* closeOpacityAnimation = new QPropertyAnimation(window(), "windowOpacity");
connect(closeOpacityAnimation, &QPropertyAnimation::finished, this, [=]() {
window()->close();
});
closeOpacityAnimation->setStartValue(1);
closeOpacityAnimation->setEndValue(0);
closeOpacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
closeOpacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
if (window()->isMaximized() || window()->isFullScreen() || d->_pIsFixedSize)
{
return;
}
QPropertyAnimation* geometryAnimation = new QPropertyAnimation(window(), "geometry");
QRect geometry = window()->geometry();
geometryAnimation->setStartValue(geometry);
qreal targetWidth = (geometry.width() - d->_lastMinTrackWidth) * 0.7 + d->_lastMinTrackWidth;
qreal targetHeight = (geometry.height() - window()->minimumHeight()) * 0.7 + window()->minimumHeight();
geometryAnimation->setEndValue(QRectF(geometry.center().x() - targetWidth / 2, geometry.center().y() - targetHeight / 2, targetWidth, targetHeight));
geometryAnimation->setEasingCurve(QEasingCurve::InOutSine);
geometryAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
#ifdef Q_OS_WIN
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
int ElaAppBar::takeOverNativeEvent(const QByteArray& eventType, void* message, qintptr* result)
#else
int ElaAppBar::takeOverNativeEvent(const QByteArray& eventType, void* message, long* result)
#endif
{
Q_D(ElaAppBar);
if ((eventType != "windows_generic_MSG") || !message)
{
return 0;
}
const auto msg = static_cast<const MSG*>(message);
const HWND hwnd = msg->hwnd;
if (!hwnd || !msg)
{
return 0;
}
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<WINDOWPOS*>(lParam);
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
{
wp->flags |= SWP_NOCOPYBITS;
*result = ::DefWindowProcW(hwnd, uMsg, wParam, lParam);
return 1;
}
return 0;
}
case WM_NCPAINT:
{
if (!eWinHelper->getIsCompositionEnabled())
{
*result = FALSE;
return 1;
}
else
{
return -1;
}
}
case WM_NCACTIVATE:
{
if (eWinHelper->getIsCompositionEnabled())
{
*result = ::DefWindowProcW(hwnd, WM_NCACTIVATE, wParam, -1);
}
else
{
*result = TRUE;
}
return 1;
}
case WM_SIZE:
{
if (wParam == SIZE_RESTORED)
{
d->_changeMaxButtonAwesome(false);
}
else if (wParam == SIZE_MAXIMIZED)
{
d->_changeMaxButtonAwesome(true);
}
return 0;
}
#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0)
case WM_SHOWWINDOW:
{
if (wParam == FALSE)
{
return 0;
}
RECT windowRect{};
::GetWindowRect(hwnd, &windowRect);
int windowWidth = windowRect.right - windowRect.left;
int windowHeight = windowRect.bottom - windowRect.top;
static UINT swpFlags = SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE;
::SetWindowPos(hwnd, nullptr, 0, 0, windowWidth + 1, windowHeight, swpFlags);
::SetWindowPos(hwnd, nullptr, 0, 0, windowWidth, windowHeight, swpFlags);
return -1;
}
#endif
case WM_NCCALCSIZE:
{
if (wParam == FALSE)
{
return 0;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 3) && QT_VERSION <= QT_VERSION_CHECK(6, 6, 1))
if (::IsZoomed(hwnd))
{
this->move(7, 7);
window()->setContentsMargins(8, 8 + height(), 8, 8);
}
else
{
this->move(0, 0);
window()->setContentsMargins(0, height(), 0, 0);
}
*result = 0;
return 1;
#else
RECT* clientRect = &((NCCALCSIZE_PARAMS*)(lParam))->rgrc[0];
if (eWinHelper->getIsWinVersionGreater10())
{
const LONG originTop = clientRect->top;
const LRESULT hitTestResult = ::DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
if ((hitTestResult != HTERROR) && (hitTestResult != HTNOWHERE))
{
*result = static_cast<long>(hitTestResult);
return 1;
}
clientRect->top = originTop;
}
if (::IsZoomed(hwnd))
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
auto geometry = window()->screen()->geometry();
#else
QScreen* screen = qApp->screenAt(window()->geometry().center());
QRect geometry;
if (!screen)
{
screen = qApp->screenAt(QCursor::pos());
}
geometry = screen->geometry();
#endif
clientRect->top = geometry.top();
if (!eWinHelper->getIsWinVersionGreater10())
{
quint32 borderThickness = eWinHelper->getResizeBorderThickness(hwnd);
clientRect->left = geometry.left();
clientRect->bottom -= borderThickness;
clientRect->right -= borderThickness;
}
}
*result = WVR_REDRAW;
return 1;
#endif
}
case WM_MOVE:
{
QScreen* currentScreen = qApp->screenAt(window()->geometry().center());
if (currentScreen && currentScreen != d->_lastScreen)
{
if (d->_lastScreen)
{
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
::RedrawWindow(hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
}
d->_lastScreen = currentScreen;
}
break;
}
case WM_NCHITTEST:
{
if (d->_containsCursorToItem(d->_maxButton))
{
if (*result == HTNOWHERE)
{
if (!d->_isHoverMaxButton)
{
d->_isHoverMaxButton = true;
d->_maxButton->setIsSelected(true);
d->_maxButton->update();
}
*result = HTZOOM;
}
return 1;
}
else
{
if (d->_isHoverMaxButton)
{
d->_isHoverMaxButton = false;
d->_maxButton->setIsSelected(false);
d->_maxButton->update();
}
}
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->_win7Margins;
bool right = nativeLocalPos.x > clientWidth - d->_win7Margins;
bool top = nativeLocalPos.y < d->_margins;
bool bottom = nativeLocalPos.y > clientHeight - d->_win7Margins;
*result = HTNOWHERE;
if (!d->_pIsOnlyAllowMinAndClose && !d->_pIsFixedSize && !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 1;
}
if (d->_containsCursorToItem(this) && !window()->isFullScreen())
{
*result = HTCAPTION;
return 1;
}
*result = HTCLIENT;
return 1;
}
case WM_GETMINMAXINFO:
{
MINMAXINFO* minmaxInfo = reinterpret_cast<MINMAXINFO*>(lParam);
RECT rect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
d->_lastMinTrackWidth = d->_calculateMinimumWidth();
minmaxInfo->ptMinTrackSize.x = d->_lastMinTrackWidth * qApp->devicePixelRatio();
minmaxInfo->ptMinTrackSize.y = parentWidget()->minimumHeight() * qApp->devicePixelRatio();
minmaxInfo->ptMaxPosition.x = rect.left;
minmaxInfo->ptMaxPosition.y = rect.top;
return 1;
}
case WM_LBUTTONDBLCLK:
{
QVariantMap postData;
postData.insert("WMClickType", ElaAppBarType::WMLBUTTONDBLCLK);
ElaEventBus::getInstance()->post("WMWindowClicked", postData);
return 0;
}
case WM_LBUTTONDOWN:
{
QVariantMap postData;
postData.insert("WMClickType", ElaAppBarType::WMLBUTTONDOWN);
ElaEventBus::getInstance()->post("WMWindowClicked", postData);
return 0;
}
case WM_LBUTTONUP:
{
QVariantMap postData;
postData.insert("WMClickType", ElaAppBarType::WMLBUTTONUP);
ElaEventBus::getInstance()->post("WMWindowClicked", postData);
return 0;
}
case WM_NCLBUTTONDOWN:
{
QVariantMap postData;
postData.insert("WMClickType", ElaAppBarType::WMNCLBUTTONDOWN);
ElaEventBus::getInstance()->post("WMWindowClicked", postData);
if (d->_containsCursorToItem(d->_maxButton) || d->_pIsOnlyAllowMinAndClose)
{
return 1;
}
break;
}
case WM_NCLBUTTONUP:
{
QVariantMap postData;
postData.insert("WMClickType", ElaAppBarType::WMNCLBUTTONDOWN);
ElaEventBus::getInstance()->post("WMWindowClicked", postData);
if (d->_containsCursorToItem(d->_maxButton) && !d->_pIsOnlyAllowMinAndClose)
{
d->onMaxButtonClicked();
return 1;
}
break;
}
case WM_NCLBUTTONDBLCLK:
{
if (!d->_pIsOnlyAllowMinAndClose && !d->_pIsFixedSize)
{
return 0;
}
return 1;
}
case WM_NCRBUTTONDOWN:
{
if (wParam == HTCAPTION && !d->_pIsOnlyAllowMinAndClose)
{
d->_showAppBarMenu(QCursor::pos());
}
break;
}
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
if ((GetAsyncKeyState(VK_MENU) & 0x8000) && (GetAsyncKeyState(VK_SPACE) & 0x8000) && !d->_pIsOnlyAllowMinAndClose)
{
auto pos = window()->geometry().topLeft();
d->_showAppBarMenu(QPoint(pos.x(), pos.y() + this->height()));
}
break;
}
}
return -1;
}
#endif
bool ElaAppBar::eventFilter(QObject* obj, QEvent* event)
{
Q_D(ElaAppBar);
switch (event->type())
{
case QEvent::Resize:
{
QSize size = parentWidget()->size();
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 3) && QT_VERSION <= QT_VERSION_CHECK(6, 6, 1))
if (::IsZoomed((HWND)d->_currentWinID))
{
this->resize(size.width() - 14, this->height());
}
else
{
this->resize(size.width(), this->height());
}
#else
this->resize(size.width(), this->height());
#endif
break;
}
#ifdef Q_OS_WIN
case QEvent::Show:
{
if (!d->_pIsFixedSize && !d->_pIsOnlyAllowMinAndClose)
{
HWND hwnd = (HWND)d->_currentWinID;
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
style &= ~WS_SYSMENU;
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_MAXIMIZEBOX | WS_THICKFRAME);
if (!eWinHelper->getIsWinVersionGreater10())
{
SetClassLong(hwnd, GCL_STYLE, GetClassLong(hwnd, GCL_STYLE) | CS_DROPSHADOW);
}
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 3) && QT_VERSION <= QT_VERSION_CHECK(6, 6, 1))
HWND hwnd = (HWND)d->_currentWinID;
ElaWinShadowHelper::getInstance()->setWindowShadow(d->_currentWinID);
DWORD style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
bool hasCaption = (style & WS_CAPTION) == WS_CAPTION;
if (!hasCaption)
{
::SetWindowLongPtr(hwnd, GWL_STYLE, style | WS_CAPTION);
}
#endif
break;
}
#endif
case QEvent::Close:
{
QCloseEvent* closeEvent = dynamic_cast<QCloseEvent*>(event);
if (!d->_pIsDefaultClosed && closeEvent->spontaneous())
{
event->ignore();
if (window()->isMinimized())
{
window()->showNormal();
}
d->onCloseButtonClicked();
return true;
}
else
{
break;
}
}
#ifndef Q_OS_WIN
case QEvent::MouseButtonPress:
{
if (d->_edges != 0)
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton)
{
d->_updateCursor(d->_edges);
window()->windowHandle()->startSystemResize(Qt::Edges(d->_edges));
}
}
else
{
if (d->_containsCursorToItem(this))
{
qint64 clickTimer = QDateTime::currentMSecsSinceEpoch();
qint64 offset = clickTimer - d->_clickTimer;
d->_clickTimer = clickTimer;
if (offset > 300)
{
window()->windowHandle()->startSystemMove();
}
}
}
break;
}
case QEvent::MouseButtonDblClick:
{
if (d->_containsCursorToItem(this))
{
if (window()->isMaximized())
{
window()->showNormal();
}
else
{
window()->showMaximized();
}
}
break;
}
case QEvent::MouseButtonRelease:
{
d->_edges = 0;
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::RightButton)
{
d->_showAppBarMenu(QCursor::pos());
}
break;
}
case QEvent::HoverMove:
{
if (window()->isMaximized() || window()->isFullScreen())
{
break;
}
if (d->_pIsFixedSize)
{
break;
}
QHoverEvent* mouseEvent = static_cast<QHoverEvent*>(event);
QPoint p =
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
mouseEvent->pos();
#else
mouseEvent->position().toPoint();
#endif
if (p.x() >= d->_margins && p.x() <= (window()->width() - d->_margins) && p.y() >= d->_margins && p.y() <= (window()->height() - d->_margins))
{
if (d->_edges != 0)
{
d->_edges = 0;
d->_updateCursor(d->_edges);
}
break;
}
d->_edges = 0;
if (p.x() < d->_margins)
{
d->_edges |= Qt::LeftEdge;
}
if (p.x() > (window()->width() - d->_margins))
{
d->_edges |= Qt::RightEdge;
}
if (p.y() < d->_margins)
{
d->_edges |= Qt::TopEdge;
}
if (p.y() > (window()->height() - d->_margins))
{
d->_edges |= Qt::BottomEdge;
}
d->_updateCursor(d->_edges);
break;
}
#endif
default:
{
break;
}
}
return QObject::eventFilter(obj, event);
}
#ifdef Q_OS_WIN
void ElaAppBar::paintEvent(QPaintEvent* event)
{
if (eWinHelper->getIsWinVersionGreater10() && !eWinHelper->getIsWinVersionGreater11())
{
Q_D(ElaAppBar);
QPainter painter(this);
painter.save();
painter.setRenderHints(QPainter::Antialiasing);
auto borderWidth = eWinHelper->getSystemMetricsForDpi((HWND)d->_currentWinID, SM_CXBORDER);
painter.setPen(QPen(window()->isActiveWindow() ? ElaThemeColor(d->_themeMode, Win10BorderActive) : ElaThemeColor(d->_themeMode, Win10BorderInactive), borderWidth));
painter.drawLine(QPoint(0, 0), QPoint(window()->width(), 0));
painter.restore();
}
}
#endif