#include "ElaWinShadowHelper.h" #ifdef Q_OS_WIN #include #include ElaWinShadowHelper::ElaWinShadowHelper(QObject* parent) : QObject(parent) { _pIsWinVersionGreater10 = true; _pIsWinVersionGreater11 = true; HMODULE module = LoadLibraryW(L"ntdll.dll"); if (module) { auto pRtlGetVersion = reinterpret_cast(::GetProcAddress(module, "RtlGetVersion")); Q_ASSERT(pRtlGetVersion); _windowsVersion.dwOSVersionInfoSize = sizeof(_windowsVersion); pRtlGetVersion(&_windowsVersion); _pIsWinVersionGreater10 = compareWindowsVersion(Win10_Origin); _pIsWinVersionGreater11 = compareWindowsVersion(Win11_Origin); } } ElaWinShadowHelper::~ElaWinShadowHelper() { } bool ElaWinShadowHelper::initWinAPI() { HMODULE dwmModule = LoadLibraryW(L"dwmapi.dll"); if (dwmModule) { if (!_dwmExtendFrameIntoClientArea) { _dwmExtendFrameIntoClientArea = reinterpret_cast(GetProcAddress(dwmModule, "DwmExtendFrameIntoClientArea")); } if (!_dwmSetWindowAttribute) { _dwmSetWindowAttribute = reinterpret_cast(GetProcAddress(dwmModule, "DwmSetWindowAttribute")); } if (!_dwmIsCompositionEnabled) { _dwmIsCompositionEnabled = reinterpret_cast(GetProcAddress(dwmModule, "DwmIsCompositionEnabled")); } if (!_dwmEnableBlurBehindWindow) { _dwmEnableBlurBehindWindow = reinterpret_cast(GetProcAddress(dwmModule, "DwmEnableBlurBehindWindow")); } if (!(_dwmExtendFrameIntoClientArea && _dwmSetWindowAttribute && _dwmIsCompositionEnabled && _dwmEnableBlurBehindWindow)) { qCritical() << "Dwm Func Init Incomplete!"; return false; } } else { qCritical() << "dwmapi.dll Load Fail!"; return false; } HMODULE user32Module = LoadLibraryW(L"user32.dll"); if (user32Module) { if (!_setWindowCompositionAttribute) { _setWindowCompositionAttribute = reinterpret_cast(GetProcAddress(user32Module, "SetWindowCompositionAttribute")); } if (!_getDpiForWindow) { _getDpiForWindow = reinterpret_cast(GetProcAddress(user32Module, "GetDpiForWindow")); } if (!_getSystemMetricsForDpi) { _getSystemMetricsForDpi = reinterpret_cast(GetProcAddress(user32Module, "GetSystemMetricsForDpi")); } if (!(_setWindowCompositionAttribute && _getDpiForWindow && _getSystemMetricsForDpi)) { qCritical() << "User32 Func Init Incomplete!"; return false; } } else { qCritical() << "user32.dll Load Fail!"; return false; } HMODULE shCoreModule = LoadLibraryW(L"SHCore.dll"); if (shCoreModule) { if (!_getDpiForMonitor) { _getDpiForMonitor = reinterpret_cast(GetProcAddress(shCoreModule, "GetDpiForMonitor")); } if (!(_getDpiForMonitor)) { qCritical() << "SHCore Func Init Incomplete!"; return false; } } else { qCritical() << "SHCore.dll Load Fail!"; return false; } return true; } void ElaWinShadowHelper::setWindowShadow(quint64 hwnd) { static const MARGINS shadow = {1, 0, 0, 0}; _dwmExtendFrameIntoClientArea((HWND)hwnd, &shadow); } void ElaWinShadowHelper::setWindowThemeMode(quint64 hwnd, bool isLightMode) { if (!compareWindowsVersion(Win10_1809)) { return; } BOOL bIsLightMode = !isLightMode; _DWMWINDOWATTRIBUTE dwAttritube = compareWindowsVersion(Win10_20H1) ? _DWMWA_USE_IMMERSIVE_DARK_MODE : _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1; _dwmSetWindowAttribute((HWND)hwnd, dwAttritube, &bIsLightMode, sizeof(bIsLightMode)); } void ElaWinShadowHelper::setWindowDisplayMode(QWidget* widget, ElaApplicationType::WindowDisplayMode displayMode, ElaApplicationType::WindowDisplayMode lastDisplayMode) { HWND winHwnd = (HWND)widget->winId(); switch (lastDisplayMode) { case ElaApplicationType::Mica: { if (!compareWindowsVersion(Win11_Origin)) { break; } if (compareWindowsVersion(Win11_22H2)) { const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_AUTO; _dwmSetWindowAttribute(winHwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(backdropType)); } else { const BOOL isEnable = FALSE; _dwmSetWindowAttribute(winHwnd, _DWMWA_MICA_EFFECT, &isEnable, sizeof(isEnable)); } break; } case ElaApplicationType::MicaAlt: { if (!compareWindowsVersion(Win11_22H2)) { break; } const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_AUTO; _dwmSetWindowAttribute(winHwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(backdropType)); break; } case ElaApplicationType::Acrylic: { if (!compareWindowsVersion(Win11_Origin)) { break; } const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_AUTO; _dwmSetWindowAttribute(winHwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(backdropType)); break; } case ElaApplicationType::DWMBlur: { if (compareWindowsVersion(Win7_Origin)) { _ACCENT_POLICY policy{}; policy.dwAccentState = _ACCENT_DISABLED; policy.dwAccentFlags = _ACCENT_NONE; _WINDOWCOMPOSITIONATTRIBDATA wcad{}; wcad.Attrib = _WCA_ACCENT_POLICY; wcad.pvData = &policy; wcad.cbData = sizeof(policy); _setWindowCompositionAttribute(winHwnd, &wcad); } else { DWM_BLURBEHIND bb{}; bb.fEnable = FALSE; bb.dwFlags = DWM_BB_ENABLE; _dwmEnableBlurBehindWindow(winHwnd, &bb); } break; } default: { break; } } switch (displayMode) { case ElaApplicationType::Mica: { if (!compareWindowsVersion(Win11_Origin)) { break; } _externWindowMargins(winHwnd); if (compareWindowsVersion(Win11_22H2)) { const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_MAINWINDOW; _dwmSetWindowAttribute(winHwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(backdropType)); } else { const BOOL enable = TRUE; _dwmSetWindowAttribute(winHwnd, _DWMWA_MICA_EFFECT, &enable, sizeof(enable)); } break; } case ElaApplicationType::MicaAlt: { if (!compareWindowsVersion(Win11_22H2)) { break; } _externWindowMargins(winHwnd); const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_TABBEDWINDOW; _dwmSetWindowAttribute(winHwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(backdropType)); break; } case ElaApplicationType::Acrylic: { if (!compareWindowsVersion(Win11_Origin)) { break; } _externWindowMargins(winHwnd); const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_TRANSIENTWINDOW; _dwmSetWindowAttribute(winHwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(backdropType)); break; } case ElaApplicationType::DWMBlur: { MARGINS windowMargins = {0, 1, 0, 0}; _dwmExtendFrameIntoClientArea(winHwnd, &windowMargins); if (compareWindowsVersion(Win7_Origin)) { _ACCENT_POLICY policy{}; policy.dwAccentState = _ACCENT_ENABLE_BLURBEHIND; policy.dwAccentFlags = _ACCENT_NONE; _WINDOWCOMPOSITIONATTRIBDATA wcad{}; wcad.Attrib = _WCA_ACCENT_POLICY; wcad.pvData = &policy; wcad.cbData = sizeof(policy); _setWindowCompositionAttribute(winHwnd, &wcad); } else { DWM_BLURBEHIND bb{}; bb.fEnable = TRUE; bb.dwFlags = DWM_BB_ENABLE; _dwmEnableBlurBehindWindow(winHwnd, &bb); } break; } default: { break; } } } bool ElaWinShadowHelper::getIsCompositionEnabled() const { BOOL isCompositionEnabled = false; _dwmIsCompositionEnabled(&isCompositionEnabled); return isCompositionEnabled; } bool ElaWinShadowHelper::getIsFullScreen(const HWND hwnd) { RECT windowRect{}; ::GetWindowRect(hwnd, &windowRect); RECT rcMonitor = getMonitorForWindow(hwnd).rcMonitor; return windowRect.top == rcMonitor.top && windowRect.left == rcMonitor.left && windowRect.right == rcMonitor.right && windowRect.bottom == rcMonitor.bottom; } MONITORINFOEXW ElaWinShadowHelper::getMonitorForWindow(const HWND hwnd) { HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); MONITORINFOEXW monitorInfo{}; monitorInfo.cbSize = sizeof(monitorInfo); ::GetMonitorInfoW(monitor, &monitorInfo); return monitorInfo; } quint32 ElaWinShadowHelper::getResizeBorderThickness(const HWND hwnd) { return getSystemMetricsForDpi(hwnd, SM_CXSIZEFRAME) + getSystemMetricsForDpi(hwnd, SM_CXPADDEDBORDER); } quint32 ElaWinShadowHelper::getDpiForWindow(const HWND hwnd) { if (_getDpiForWindow) { return _getDpiForWindow(hwnd); } else if (_getDpiForMonitor) { HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); UINT dpiX{0}; UINT dpiY{0}; _getDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); return dpiX; } else { HDC hdc = ::GetDC(nullptr); const int dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX); ::ReleaseDC(nullptr, hdc); return quint32(dpiX); } } int ElaWinShadowHelper::getSystemMetricsForDpi(const HWND hwnd, const int index) { const quint32 dpi = getDpiForWindow(hwnd); if (_getSystemMetricsForDpi) { return _getSystemMetricsForDpi(index, dpi); } const int result = ::GetSystemMetrics(index); if (dpi != USER_DEFAULT_SCREEN_DPI) { return result; } const qreal dpr = qreal(dpi) / qreal(USER_DEFAULT_SCREEN_DPI); return qRound(qreal(result) / dpr); } bool ElaWinShadowHelper::compareWindowsVersion(const QString& windowsVersion) const { QStringList versionList = windowsVersion.split("."); if (versionList.count() != 3) { return false; } return (_windowsVersion.dwMajorVersion > versionList[0].toUInt()) || (_windowsVersion.dwMajorVersion == versionList[0].toUInt() && (_windowsVersion.dwMinorVersion > versionList[1].toUInt() || _windowsVersion.dwBuildNumber >= versionList[2].toUInt())); } void ElaWinShadowHelper::_externWindowMargins(HWND hwnd) { static const MARGINS margins = {65536, 0, 0, 0}; _dwmExtendFrameIntoClientArea(hwnd, &margins); } #endif