#include "WindowsFramelessWidget.h" #include "WindowsWindowEffect.h" #include "titlebar/TitleBar.h" #include "utils/Win32Utils.h" #include #include #include #include #include constexpr int BORDER_WIDTH = 5; WindowsFramelessWidget::WindowsFramelessWidget(QWidget *parent) : QWidget(parent) { Q_INIT_RESOURCE(qframelesswindow); windowEffect = new WindowsWindowEffect(this); titleBar = new TitleBar(this); isResizeEnabled = true; // remove window border if (!Win32Utils::isWin7()) { setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint); } else { setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint); } // add DWM shadow and window animation windowEffect->addWindowAnimation((HWND)this->winId()); if (effectType() == "AcrylicWindow") { windowEffect->addShadowEffect((HWND)this->winId()); } connect(this->windowHandle(), &QWindow::screenChanged, this, &WindowsFramelessWidget::onScreenChanged); resize(500, 500); titleBar->raise(); } void WindowsFramelessWidget::setTitleBar(TitleBar *tBar) { if (tBar != titleBar) { titleBar->deleteLater(); titleBar = tBar; titleBar->setParent(this); titleBar->raise(); } } void WindowsFramelessWidget::setResizeEnabled(bool isEnabled) { isResizeEnabled = isEnabled; } bool WindowsFramelessWidget::getResizeEnabled() const { return isResizeEnabled; } WindowsWindowEffect *WindowsFramelessWidget::getWindowEffect() const { return windowEffect; } TitleBar *WindowsFramelessWidget::getTitleBar() const { return titleBar; } void WindowsFramelessWidget::onScreenChanged(QScreen * /*screen*/) { HWND hWnd = (HWND)this->windowHandle()->winId(); SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); } void WindowsFramelessWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); titleBar->resize(this->width(), titleBar->height()); } /// Handle the Windows message bool WindowsFramelessWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) { MSG *msg = static_cast(message); if (!msg->hwnd) { return QWidget::nativeEvent(eventType, message, result); } switch (msg->message) { case WM_NCHITTEST: { if (isResizeEnabled) { QPoint pos = QCursor::pos(); int xPos = pos.x() - this->x(); int yPos = pos.y() - this->y(); int w = this->width(); int h = this->height(); bool lx = (xPos < BORDER_WIDTH); bool rx = (xPos > w - BORDER_WIDTH); bool ty = (yPos < BORDER_WIDTH); bool by = (yPos > h - BORDER_WIDTH); if (lx && ty) { *result = HTTOPLEFT; return true; } else if (rx && by) { *result = HTBOTTOMRIGHT; return true; } else if (rx && ty) { *result = HTTOPRIGHT; return true; } else if (lx && by) { *result = HTBOTTOMLEFT; return true; } else if (ty) { *result = HTTOP; return true; } else if (by) { *result = HTBOTTOM; return true; } else if (lx) { *result = HTLEFT; return true; } else if (rx) { *result = HTRIGHT; return true; } } } break; case WM_NCCALCSIZE: { RECT rc; if (msg->wParam) { rc = ((LPNCCALCSIZE_PARAMS)msg->lParam)->rgrc[0]; } else { rc = *(LPRECT)msg->lParam; } bool isMax = Win32Utils::isMaximized(msg->hwnd); bool isFull = Win32Utils::isFullScreen(msg->hwnd); // adjust the size of client rect if (isMax && !isFull) { int ty = Win32Utils::getResizeBorderThickness(msg->hwnd, false); rc.top += ty; rc.bottom -= ty; int tx = Win32Utils::getResizeBorderThickness(msg->hwnd, true); rc.left += tx; rc.right -= tx; } // handle the situation that an auto-hide taskbar is enabled if ((isMax || isFull) && Win32Utils::Taskbar::isAutoHide()) { Win32Utils::Taskbar::Position position = Win32Utils::Taskbar::getPosition(msg->hwnd); if (position == Win32Utils::Taskbar::TOP) { rc.top += Win32Utils::Taskbar::AUTO_HIDE_THICKNESS; } else if (position == Win32Utils::Taskbar::BOTTOM) { rc.bottom -= Win32Utils::Taskbar::AUTO_HIDE_THICKNESS; } else if (position == Win32Utils::Taskbar::LEFT) { rc.left += Win32Utils::Taskbar::AUTO_HIDE_THICKNESS; } else if (position == Win32Utils::Taskbar::RIGHT) { rc.right -= Win32Utils::Taskbar::AUTO_HIDE_THICKNESS; } } if (!msg->wParam) { *result = 0; } else { *result = WVR_REDRAW; } return true; } break; } return QWidget::nativeEvent(eventType, message, result); }