#include "TaoFrameLessView.h" #include #include #include #include #include #include #include #include // Fixes error C2504: 'IUnknown' : base class undefined #include #include #include #pragma comment(lib, "Dwmapi.lib") // Adds missing library, fixes error LNK2019: unresolved #pragma comment(lib, "User32.lib") #pragma comment(lib, "Gdi32.lib") // we cannot just use WS_POPUP style // WS_THICKFRAME: without this the window cannot be resized and so aero snap, de-maximizing and minimizing won't work // WS_SYSMENU: enables the context menu with the move, close, maximize, minize... commands (shift + right-click on the task bar item) // WS_CAPTION: enables aero minimize animation/transition // WS_MAXIMIZEBOX, WS_MINIMIZEBOX: enable minimize/maximize enum class Style : DWORD { windowed = WS_OVERLAPPEDWINDOW | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, aero_borderless = WS_POPUP | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, basic_borderless = WS_POPUP | WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX }; static bool isCompositionEnabled() { BOOL composition_enabled = FALSE; bool success = ::DwmIsCompositionEnabled(&composition_enabled) == S_OK; return composition_enabled && success; } static Style selectBorderLessStyle() { return isCompositionEnabled() ? Style::aero_borderless : Style::basic_borderless; } static void setShadow(HWND handle, bool enabled) { if (isCompositionEnabled()) { static const MARGINS shadow_state[2] { { 0, 0, 0, 0 }, { 1, 1, 1, 1 } }; ::DwmExtendFrameIntoClientArea(handle, &shadow_state[enabled]); } } static long hitTest(RECT winrect, long x, long y, int borderWidth) { // 鼠标区域位于窗体边框,进行缩放 if ((x >= winrect.left) && (x < winrect.left + borderWidth) && (y >= winrect.top) && (y < winrect.top + borderWidth)) { return HTTOPLEFT; } else if (x < winrect.right && x >= winrect.right - borderWidth && y >= winrect.top && y < winrect.top + borderWidth) { return HTTOPRIGHT; } else if (x >= winrect.left && x < winrect.left + borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth) { return HTBOTTOMLEFT; } else if (x < winrect.right && x >= winrect.right - borderWidth && y < winrect.bottom && y >= winrect.bottom - borderWidth) { return HTBOTTOMRIGHT; } else if (x >= winrect.left && x < winrect.left + borderWidth) { return HTLEFT; } else if (x < winrect.right && x >= winrect.right - borderWidth) { return HTRIGHT; } else if (y >= winrect.top && y < winrect.top + borderWidth) { return HTTOP; } else if (y < winrect.bottom && y >= winrect.bottom - borderWidth) { return HTBOTTOM; } else { return 0; } } static bool isMaxWin(QWindow* win) { return win->windowState() == Qt::WindowMaximized; } static bool isFullWin(QQuickView* win) { return win->windowState() == Qt::WindowFullScreen; } class TaoFrameLessViewPrivate { public: bool m_firstRun = true; bool m_isMax = false; bool m_isFull = false; QQuickItem* m_titleItem = nullptr; HMENU mMenuHandler = NULL; bool borderless = true; // is the window currently borderless bool borderless_resize = true; // should the window allow resizing by dragging the borders while borderless bool borderless_drag = true; // should the window allow moving my dragging the client area bool borderless_shadow = true; // should the window display a native aero shadow while borderless void setBorderLess(HWND handle, bool enabled) { auto newStyle = enabled ? selectBorderLessStyle() : Style::windowed; auto oldStyle = static_cast