#include "WindowsWindowEffect.h" #include "utils/Win32Utils.h" #include #include #include WindowsWindowEffect::WindowsWindowEffect(QWidget *parent) : QWidget(parent) { winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY; winCompAttrData.SizeOfData = sizeof(accentPolicy); winCompAttrData.Data = &accentPolicy; } bool WindowsWindowEffect::setAcrylicEffect(HWND hWnd, std::string gradientColor, bool enableShadow, uint32_t animationId) { if (!Win32Utils::isGreaterEqualWin10()) { QMessageBox::warning(nullptr, "warning", "The acrylic effect is only available on Win10+"); return false; } std::string gradientColorBigEndian; for (int index = gradientColor.size(); index > 0; index -= 2) { gradientColorBigEndian += gradientColor.substr(index - 2, 2); } DWORD gradientColorValue = strtol(gradientColorBigEndian.c_str(), NULL, 16); DWORD accentFlags = 0; if (enableShadow) { accentFlags = 0x20 | 0x40 | 0x80 | 0x100; } this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_ENABLE_BLURBEHIND; this->accentPolicy.GradientColor = gradientColorValue; this->accentPolicy.AccentFlags = accentFlags; this->accentPolicy.AnimationId = animationId; this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY; HMODULE huser = GetModuleHandle(L"user32.dll"); if (huser) { SetWindowCompositionAttribute setWindowCompositionAttribute = (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute"); if (setWindowCompositionAttribute) { setWindowCompositionAttribute(hWnd, &this->winCompAttrData); return true; } } return false; } /** * @brief WindowsWindowEffect::setMicaEffect * @param hWnd: Window handle * @param isDarkMode: whether to use dark mode mica effect * @return */ bool WindowsWindowEffect::setMicaEffect(HWND hWnd, bool isDarkMode) { if (!Win32Utils::isGreaterEqualWin11()) { QMessageBox::warning(nullptr, "warning", "The Mica effect is only available on Win11"); return false; } MARGINS margins = { -1, -1, -1, -1 }; if (S_OK != DwmExtendFrameIntoClientArea(hWnd, &margins)) { return false; } this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY; this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_ENABLE_HOSTBACKDROP; HMODULE huser = GetModuleHandle(L"user32.dll"); if (!huser) { return false; } SetWindowCompositionAttribute setWindowCompositionAttribute = (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute"); if (!setWindowCompositionAttribute) { return false; } setWindowCompositionAttribute(hWnd, &this->winCompAttrData); if (isDarkMode) { this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_USEDARKMODECOLORS; setWindowCompositionAttribute(hWnd, &this->winCompAttrData); } if (QOperatingSystemVersion::current().microVersion() < 22523) { DWORD V = 1; if (S_OK != DwmSetWindowAttribute(hWnd, 1029, &V, 4)) { return false; } } else { DWORD V = 2; if (S_OK != DwmSetWindowAttribute(hWnd, 38, &V, 4)) { return false; } } return true; } bool WindowsWindowEffect::setAeroEffect(HWND hWnd) { this->winCompAttrData.Attribute = WINDOWCOMPOSITIONATTRIB::WCA_ACCENT_POLICY; this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_ENABLE_BLURBEHIND; HMODULE huser = GetModuleHandle(L"user32.dll"); if (huser) { SetWindowCompositionAttribute setWindowCompositionAttribute = (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute"); if (setWindowCompositionAttribute) { setWindowCompositionAttribute(hWnd, &this->winCompAttrData); return true; } } return false; } bool WindowsWindowEffect::removeBackgroundEffect(HWND hWnd) { this->accentPolicy.AccentState = ACCENT_STATE::ACCENT_DISABLED; HMODULE huser = GetModuleHandle(L"user32.dll"); if (huser) { SetWindowCompositionAttribute setWindowCompositionAttribute = (SetWindowCompositionAttribute)GetProcAddress(huser, "SetWindowCompositionAttribute"); if (setWindowCompositionAttribute) { setWindowCompositionAttribute(hWnd, &this->winCompAttrData); return true; } } return false; } void WindowsWindowEffect::moveWindow(HWND hWnd) { ReleaseCapture(); SendMessage(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); } /** * @brief Add DWM shadow to window * @param hWnd * @return */ bool WindowsWindowEffect::addShadowEffect(HWND hWnd) { if (!QtWin::isCompositionEnabled()) { return false; } MARGINS margins = { -1, -1, -1, -1 }; if (S_OK != DwmExtendFrameIntoClientArea(hWnd, &margins)) { return false; } return true; } /** * @brief Add DWM shadow to menu * @param hWnd * @return */ bool WindowsWindowEffect::addMenuShadowEffect(HWND hWnd) { if (!QtWin::isCompositionEnabled()) { return false; } DWORD attribute = DWMNCRENDERINGPOLICY::DWMNCRP_ENABLED; if (S_OK != DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE::DWMWA_NCRENDERING_POLICY, &attribute, 4)) { return false; } MARGINS margins = { -1, -1, -1, -1 }; if (S_OK != DwmExtendFrameIntoClientArea(hWnd, &margins)) { return false; } return true; } /** * @brief Remove DWM shadow from the window * @param hWnd * @return */ bool WindowsWindowEffect::removeShadowEffect(HWND hWnd) { DWORD attribute = DWMNCRENDERINGPOLICY::DWMNCRP_DISABLED; if (S_OK != DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE::DWMWA_NCRENDERING_POLICY, &attribute, 4)) { return false; } return true; } /** * @brief Remove shadow from pop-up menu * @param hWnd * @return */ void WindowsWindowEffect::removeMenuShadowEffect(HWND hWnd) { DWORD style = GetClassLong(hWnd, GCL_STYLE); style &= ~CS_DROPSHADOW; SetClassLong(hWnd, GCL_STYLE, style); } /** * @brief Enables the maximize and minimize animation of the window * @param hWnd */ void WindowsWindowEffect::addWindowAnimation(HWND hWnd) { DWORD style = GetClassLong(hWnd, GCL_STYLE); SetWindowLong(hWnd, GWL_STYLE, style | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | CS_DBLCLKS | WS_THICKFRAME); }