feat: 添加ElaWidgetTool库
This commit is contained in:
353
ElaWidgetTools/DeveloperComponents/ElaWinShadowHelper.cpp
Normal file
353
ElaWidgetTools/DeveloperComponents/ElaWinShadowHelper.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
#include "ElaWinShadowHelper.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QDebug>
|
||||
#include <QWidget>
|
||||
|
||||
ElaWinShadowHelper::ElaWinShadowHelper(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
_pIsWinVersionGreater10 = true;
|
||||
_pIsWinVersionGreater11 = true;
|
||||
HMODULE module = LoadLibraryW(L"ntdll.dll");
|
||||
if (module)
|
||||
{
|
||||
auto pRtlGetVersion = reinterpret_cast<RtlGetVersionFunc>(::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<DwmExtendFrameIntoClientAreaFunc>(GetProcAddress(dwmModule, "DwmExtendFrameIntoClientArea"));
|
||||
}
|
||||
if (!_dwmSetWindowAttribute)
|
||||
{
|
||||
_dwmSetWindowAttribute = reinterpret_cast<DwmSetWindowAttributeFunc>(GetProcAddress(dwmModule, "DwmSetWindowAttribute"));
|
||||
}
|
||||
if (!_dwmIsCompositionEnabled)
|
||||
{
|
||||
_dwmIsCompositionEnabled = reinterpret_cast<DwmIsCompositionEnabledFunc>(GetProcAddress(dwmModule, "DwmIsCompositionEnabled"));
|
||||
}
|
||||
if (!_dwmEnableBlurBehindWindow)
|
||||
{
|
||||
_dwmEnableBlurBehindWindow = reinterpret_cast<DwmEnableBlurBehindWindowFunc>(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<SetWindowCompositionAttributeFunc>(GetProcAddress(user32Module, "SetWindowCompositionAttribute"));
|
||||
}
|
||||
if (!_getDpiForWindow)
|
||||
{
|
||||
_getDpiForWindow = reinterpret_cast<GetDpiForWindowFunc>(GetProcAddress(user32Module, "GetDpiForWindow"));
|
||||
}
|
||||
if (!_getSystemMetricsForDpi)
|
||||
{
|
||||
_getSystemMetricsForDpi = reinterpret_cast<GetSystemMetricsForDpiFunc>(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<GetDpiForMonitorFunc>(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
|
||||
Reference in New Issue
Block a user