920 lines
29 KiB
C++
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
|