diff --git a/include/FramelessHelper/Core/framelesshelper_windows.h b/include/FramelessHelper/Core/framelesshelper_windows.h index 0553135..2e336d6 100644 --- a/include/FramelessHelper/Core/framelesshelper_windows.h +++ b/include/FramelessHelper/Core/framelesshelper_windows.h @@ -52,7 +52,9 @@ # define NOMINMAX #endif -#include +#if __has_include() +# include +#endif #ifndef _WIN32_WINNT_WIN10 # define _WIN32_WINNT_WIN10 0x0A00 @@ -79,6 +81,8 @@ #include #include +#include + #ifndef WM_NCUAHDRAWCAPTION # define WM_NCUAHDRAWCAPTION (0x00AE) #endif @@ -437,6 +441,265 @@ using ShouldSystemUseDarkModePtr = BOOL(WINAPI *)(VOID); // Ordinal 138 using SetPreferredAppModePtr = PREFERRED_APP_MODE(WINAPI *)(PREFERRED_APP_MODE); // Ordinal 135 using IsDarkModeAllowedForAppPtr = BOOL(WINAPI *)(VOID); // Ordinal 139 +EXTERN_C_START + +/////////////////////////////////////////////// +// Function prototypes + +_MMRESULT WINAPI +_timeGetDevCaps( + _PTIMECAPS ptc, + UINT cbtc +); + +_MMRESULT WINAPI +_timeBeginPeriod( + UINT uPeriod +); + +_MMRESULT WINAPI +_timeEndPeriod( + UINT uPeriod +); + +HRESULT WINAPI +_SetProcessDpiAwareness( + _PROCESS_DPI_AWARENESS value +); + +HRESULT WINAPI +_GetProcessDpiAwareness( + HANDLE hProcess, + _PROCESS_DPI_AWARENESS *value +); + +HRESULT WINAPI +_GetDpiForMonitor( + HMONITOR hMonitor, + _MONITOR_DPI_TYPE dpiType, + UINT *dpiX, + UINT *dpiY +); + +int WINAPI +_GetSystemMetricsForDpi( + int nIndex, + UINT dpi +); + +UINT WINAPI +_GetWindowDPI( + HWND hWnd +); + +UINT WINAPI +_GetDpiForWindow( + HWND hWnd +); + +UINT WINAPI +_GetDpiForSystem( + VOID +); + +UINT WINAPI +_GetSystemDpiForProcess( + HANDLE hProcess +); + +BOOL WINAPI +_SetProcessDpiAwarenessContext( + _DPI_AWARENESS_CONTEXT value +); + +BOOL WINAPI +_SetProcessDPIAware( + VOID +); + +HRESULT WINAPI +_GetScaleFactorForMonitor( + HMONITOR hMon, + _DEVICE_SCALE_FACTOR *pScale +); + +BOOL WINAPI +_EnableNonClientDpiScaling( + HWND hWnd +); + +_DPI_AWARENESS_CONTEXT WINAPI +_GetThreadDpiAwarenessContext( + VOID +); + +_DPI_AWARENESS_CONTEXT WINAPI +_GetWindowDpiAwarenessContext( + HWND hWnd +); + +_DPI_AWARENESS WINAPI +_GetAwarenessFromDpiAwarenessContext( + _DPI_AWARENESS_CONTEXT value +); + +_DPI_AWARENESS_CONTEXT WINAPI +_GetDpiAwarenessContextForProcess( + HANDLE hProcess +); + +BOOL WINAPI +_AreDpiAwarenessContextsEqual( + _DPI_AWARENESS_CONTEXT dpiContextA, + _DPI_AWARENESS_CONTEXT dpiContextB +); + +BOOL WINAPI +_EnableChildWindowDpiMessage( + HWND hWnd, + BOOL fEnable +); + +BOOL WINAPI +_EnablePerMonitorDialogScaling( + VOID +); + +int WINAPI +_GetDpiMetrics( + int nIndex, + UINT dpi +); + +BOOL WINAPI +_AdjustWindowRectExForDpi( + LPRECT lpRect, + DWORD dwStyle, + BOOL bMenu, + DWORD dwExStyle, + UINT dpi +); + +/////////////////////////////////////////////// +// API thunks + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_GetWindowCompositionAttribute( + const HWND hWnd, + PWINDOWCOMPOSITIONATTRIBDATA pvData +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_SetWindowCompositionAttribute( + const HWND hWnd, + PWINDOWCOMPOSITIONATTRIBDATA pvData +); + +FRAMELESSHELPER_CORE_API HRESULT WINAPI +_SetWindowThemeAttribute( + const HWND hWnd, + const _WINDOWTHEMEATTRIBUTETYPE attrib, + PVOID pvData, + const DWORD cbData +); + +FRAMELESSHELPER_CORE_API HRESULT WINAPI +_SetWindowThemeNonClientAttributes( + const HWND hWnd, + const DWORD dwMask, + const DWORD dwAttributes +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_ShouldAppsUseDarkMode( + VOID +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_AllowDarkModeForWindow( + const HWND hWnd, + const BOOL bAllow +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_AllowDarkModeForApp( + const BOOL bAllow +); + +FRAMELESSHELPER_CORE_API VOID WINAPI +_FlushMenuThemes( + VOID +); + +FRAMELESSHELPER_CORE_API VOID WINAPI +_RefreshImmersiveColorPolicyState( + VOID +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_IsDarkModeAllowedForWindow( + const HWND hWnd +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_GetIsImmersiveColorUsingHighContrast( + const IMMERSIVE_HC_CACHE_MODE mode +); + +FRAMELESSHELPER_CORE_API HTHEME WINAPI +_OpenNcThemeData( + const HWND hWnd, + LPCWSTR pszClassList +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_ShouldSystemUseDarkMode( + VOID +); + +FRAMELESSHELPER_CORE_API PREFERRED_APP_MODE WINAPI +_SetPreferredAppMode( + const PREFERRED_APP_MODE mode +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_IsDarkModeAllowedForApp( + VOID +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_EnableChildWindowDpiMessage2( + const HWND hWnd, + const BOOL fEnable +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_EnablePerMonitorDialogScaling2( + VOID +); + +FRAMELESSHELPER_CORE_API UINT WINAPI +_GetDpiForWindow2( + const HWND hWnd +); + +FRAMELESSHELPER_CORE_API int WINAPI +_GetSystemMetricsForDpi2( + const int nIndex, + const UINT dpi +); + +FRAMELESSHELPER_CORE_API BOOL WINAPI +_AdjustWindowRectExForDpi2( + LPRECT lpRect, + const DWORD dwStyle, + const BOOL bMenu, + const DWORD dwExStyle, + const UINT dpi +); + +EXTERN_C_END + [[maybe_unused]] inline constexpr const int kAutoHideTaskBarThickness = 2; // The thickness of an auto-hide taskbar in pixels. [[maybe_unused]] inline constexpr const wchar_t kDwmRegistryKey[] = LR"(Software\Microsoft\Windows\DWM)"; [[maybe_unused]] inline constexpr const wchar_t kPersonalizeRegistryKey[] = LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)"; diff --git a/qmake/core.pri b/qmake/core.pri index 5dd5402..91b3b53 100644 --- a/qmake/core.pri +++ b/qmake/core.pri @@ -58,7 +58,8 @@ win32 { $$CORE_SRC_DIR/framelesshelper_win.cpp \ $$CORE_SRC_DIR/utils_win.cpp \ $$CORE_SRC_DIR/registrykey.cpp \ - $$CORE_SRC_DIR/winverhelper.cpp + $$CORE_SRC_DIR/winverhelper.cpp \ + $$CORE_SRC_DIR/platformsupport_win.cpp LIBS += -luser32 -lgdi32 -lshell32 } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e86716d..675209e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -97,6 +97,7 @@ if(WIN32) utils_win.cpp framelesshelper_win.cpp winverhelper.cpp + platformsupport_win.cpp ) elseif(APPLE) list(APPEND SOURCES utils_mac.mm) diff --git a/src/core/platformsupport_win.cpp b/src/core/platformsupport_win.cpp new file mode 100644 index 0000000..97d0e52 --- /dev/null +++ b/src/core/platformsupport_win.cpp @@ -0,0 +1,501 @@ +/* + * MIT License + * + * Copyright (C) 2021-2023 by wangwenx190 (Yuhang Zhao) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "sysapiloader_p.h" +#include "winverhelper_p.h" +#include "framelesshelper_windows.h" + +FRAMELESSHELPER_STRING_CONSTANT(user32) +FRAMELESSHELPER_STRING_CONSTANT(uxtheme) +FRAMELESSHELPER_STRING_CONSTANT(win32u) + +FRAMELESSHELPER_STRING_CONSTANT(GetWindowCompositionAttribute) +FRAMELESSHELPER_STRING_CONSTANT(SetWindowCompositionAttribute) +FRAMELESSHELPER_STRING_CONSTANT(SetWindowThemeAttribute) +FRAMELESSHELPER_STRING_CONSTANT(NtUserEnableChildWindowDpiMessage) +FRAMELESSHELPER_STRING_CONSTANT(EnableChildWindowDpiMessage) +FRAMELESSHELPER_STRING_CONSTANT(EnablePerMonitorDialogScaling) +FRAMELESSHELPER_STRING_CONSTANT(GetDpiForWindow) +FRAMELESSHELPER_STRING_CONSTANT(GetWindowDPI) +FRAMELESSHELPER_STRING_CONSTANT(GetSystemMetricsForDpi) +FRAMELESSHELPER_STRING_CONSTANT(GetDpiMetrics) +FRAMELESSHELPER_STRING_CONSTANT(AdjustWindowRectExForDpi) + +EXTERN_C BOOL WINAPI +_GetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvData) +{ + Q_ASSERT(hWnd); + Q_ASSERT(pvData); + if (!hWnd || !pvData) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (!API_USER_AVAILABLE(GetWindowCompositionAttribute)) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return API_CALL_FUNCTION4(GetWindowCompositionAttribute, hWnd, pvData); +} + +EXTERN_C BOOL WINAPI +_SetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvData) +{ + Q_ASSERT(hWnd); + Q_ASSERT(pvData); + if (!hWnd || !pvData) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (!API_USER_AVAILABLE(SetWindowCompositionAttribute)) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return API_CALL_FUNCTION4(SetWindowCompositionAttribute, hWnd, pvData); +} + +EXTERN_C HRESULT WINAPI +_SetWindowThemeAttribute(const HWND hWnd, const _WINDOWTHEMEATTRIBUTETYPE attrib, + PVOID pvData, const DWORD cbData +) +{ + Q_ASSERT(hWnd); + Q_ASSERT(pvData); + Q_ASSERT(cbData != 0); + if (!hWnd || !pvData || (cbData == 0)) { + return E_INVALIDARG; + } + if (!API_THEME_AVAILABLE(SetWindowThemeAttribute)) { + return E_NOTIMPL; + } + return API_CALL_FUNCTION4(SetWindowThemeAttribute, hWnd, attrib, pvData, cbData); +} + +EXTERN_C HRESULT WINAPI +_SetWindowThemeNonClientAttributes(const HWND hWnd, const DWORD dwMask, const DWORD dwAttributes) +{ + Q_ASSERT(hWnd); + if (!hWnd) { + return E_INVALIDARG; + } + WTA_OPTIONS2 options = {}; + options.dwFlags = dwAttributes; + options.dwMask = dwMask; + return _SetWindowThemeAttribute(hWnd, _WTA_NONCLIENT, &options, sizeof(options)); +} + +EXTERN_C BOOL WINAPI +_ShouldAppsUseDarkMode(VOID) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + static const auto pShouldAppsUseDarkMode + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(132))); + if (!pShouldAppsUseDarkMode) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pShouldAppsUseDarkMode(); +} + +EXTERN_C BOOL WINAPI +_AllowDarkModeForWindow(const HWND hWnd, const BOOL bAllow) +{ + Q_ASSERT(hWnd); + if (!hWnd) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + static const auto pAllowDarkModeForWindow + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(133))); + if (!pAllowDarkModeForWindow) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pAllowDarkModeForWindow(hWnd, bAllow); +} + +EXTERN_C BOOL WINAPI +_AllowDarkModeForApp(const BOOL bAllow) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + static const auto pAllowDarkModeForApp + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135))); + if (!pAllowDarkModeForApp) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pAllowDarkModeForApp(bAllow); +} + +EXTERN_C VOID WINAPI +_FlushMenuThemes(VOID) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return; + } + static const auto pFlushMenuThemes + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(136))); + if (!pFlushMenuThemes) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return; + } + pFlushMenuThemes(); +} + +EXTERN_C VOID WINAPI +_RefreshImmersiveColorPolicyState(VOID) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return; + } + static const auto pRefreshImmersiveColorPolicyState + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(104))); + if (!pRefreshImmersiveColorPolicyState) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return; + } + pRefreshImmersiveColorPolicyState(); +} + +EXTERN_C BOOL WINAPI +_IsDarkModeAllowedForWindow(const HWND hWnd) +{ + Q_ASSERT(hWnd); + if (!hWnd) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + static const auto pIsDarkModeAllowedForWindow + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(137))); + if (!pIsDarkModeAllowedForWindow) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pIsDarkModeAllowedForWindow(hWnd); +} + +EXTERN_C BOOL WINAPI +_GetIsImmersiveColorUsingHighContrast(const IMMERSIVE_HC_CACHE_MODE mode) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + static const auto pGetIsImmersiveColorUsingHighContrast + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(106))); + if (!pGetIsImmersiveColorUsingHighContrast) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pGetIsImmersiveColorUsingHighContrast(mode); +} + +EXTERN_C HTHEME WINAPI +_OpenNcThemeData(const HWND hWnd, LPCWSTR pszClassList) +{ + Q_ASSERT(hWnd); + Q_ASSERT(pszClassList); + if (!hWnd || !pszClassList) { + SetLastError(ERROR_INVALID_PARAMETER); + return nullptr; + } + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return nullptr; + } + static const auto pOpenNcThemeData + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(49))); + if (!pOpenNcThemeData) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return nullptr; + } + return pOpenNcThemeData(hWnd, pszClassList); +} + +EXTERN_C BOOL WINAPI +_ShouldSystemUseDarkMode(VOID) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + static const auto pShouldSystemUseDarkMode + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(138))); + if (!pShouldSystemUseDarkMode) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pShouldSystemUseDarkMode(); +} + +EXTERN_C PREFERRED_APP_MODE WINAPI +_SetPreferredAppMode(const PREFERRED_APP_MODE mode) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return PAM_MAX; + } + static const auto pSetPreferredAppMode + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135))); + if (!pSetPreferredAppMode) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return PAM_MAX; + } + return pSetPreferredAppMode(mode); +} + +EXTERN_C BOOL WINAPI +_IsDarkModeAllowedForApp(VOID) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + static const auto pIsDarkModeAllowedForApp + = reinterpret_cast( + SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(139))); + if (!pIsDarkModeAllowedForApp) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pIsDarkModeAllowedForApp(); +} + +EXTERN_C BOOL WINAPI +_EnableChildWindowDpiMessage2(const HWND hWnd, const BOOL fEnable) +{ + Q_ASSERT(hWnd); + if (!hWnd) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + using EnableChildWindowDpiMessagePtr = decltype(&::_EnableChildWindowDpiMessage); + static const auto pEnableChildWindowDpiMessage = []() -> EnableChildWindowDpiMessagePtr { + // EnableChildWindowDpiMessage() was moved to "win32u.dll" and renamed to + // "NtUserEnableChildWindowDpiMessage" since Win10 1607. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kwin32u, kNtUserEnableChildWindowDpiMessage))) { + return pFunc; + } + // EnableChildWindowDpiMessage() was once a public API, so we can load it by name, + // but it got removed in Win10 1607, so we can't link to it directly. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, kEnableChildWindowDpiMessage))) { + return pFunc; + } + // EnableChildWindowDpiMessage() was made private since Win10 1607. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2704)))) { + return pFunc; + } + return nullptr; + }(); + if (!pEnableChildWindowDpiMessage) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pEnableChildWindowDpiMessage(hWnd, fEnable); +} + +EXTERN_C BOOL WINAPI +_EnablePerMonitorDialogScaling2(VOID) +{ + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + using EnablePerMonitorDialogScalingPtr = decltype(&::_EnablePerMonitorDialogScaling); + static const auto pEnablePerMonitorDialogScaling = []() -> EnablePerMonitorDialogScalingPtr { + // EnablePerMonitorDialogScaling() was once a public API, so we can load it by name, + // but it got removed in Win10 1607, so we can't link to it directly. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, kEnablePerMonitorDialogScaling))) { + return pFunc; + } + // EnablePerMonitorDialogScaling() was made private since Win10 1607. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2577)))) { + return pFunc; + } + return nullptr; + }(); + if (!pEnablePerMonitorDialogScaling) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pEnablePerMonitorDialogScaling(); +} + +EXTERN_C UINT WINAPI +_GetDpiForWindow2(const HWND hWnd) +{ + Q_ASSERT(hWnd); + if (!hWnd) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + using GetDpiForWindowPtr = decltype(&::_GetDpiForWindow); + static const auto pGetDpiForWindow = []() -> GetDpiForWindowPtr { + // GetDpiForWindow() was made public since Win10 1607. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, kGetDpiForWindow))) { + return pFunc; + } + // GetDpiForWindow() was named "GetWindowDPI" before made public. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, kGetWindowDPI))) { + return pFunc; + } + // GetWindowDPI() was made private since Win10 1607. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2707)))) { + return pFunc; + } + return nullptr; + }(); + if (!pGetDpiForWindow) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + return pGetDpiForWindow(hWnd); +} + +EXTERN_C int WINAPI +_GetSystemMetricsForDpi2(const int nIndex, const UINT dpi) +{ + Q_ASSERT(nIndex >= 0); + Q_ASSERT(dpi != 0); + if ((nIndex < 0) || (dpi == 0)) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + using GetSystemMetricsForDpiPtr = decltype(&::_GetSystemMetricsForDpi); + static const auto pGetSystemMetricsForDpi = []() -> GetSystemMetricsForDpiPtr { + // GetSystemMetricsForDpi() was made public since Win10 1607. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, kGetSystemMetricsForDpi))) { + return pFunc; + } + // GetSystemMetricsForDpi() was named "GetDpiMetrics" before made public, + // that is, when in Win10 1507 & 1511. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, kGetDpiMetrics))) { + return pFunc; + } + return nullptr; + }(); + if (!pGetSystemMetricsForDpi) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; + } + return pGetSystemMetricsForDpi(nIndex, dpi); +} + +EXTERN_C BOOL WINAPI +_AdjustWindowRectExForDpi2(LPRECT lpRect, const DWORD dwStyle, + const BOOL bMenu, const DWORD dwExStyle, const UINT dpi) +{ + Q_ASSERT(lpRect); + Q_ASSERT(dpi != 0); + if (!lpRect || (dpi == 0)) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + FRAMELESSHELPER_USE_NAMESPACE + if (!WindowsVersionHelper::isWin10OrGreater()) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + using AdjustWindowRectExForDpiPtr = decltype(&::_AdjustWindowRectExForDpi); + static const auto pAdjustWindowRectExForDpi = []() -> AdjustWindowRectExForDpiPtr { + // AdjustWindowRectExForDpi() was made public since Win10 1607. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, kAdjustWindowRectExForDpi))) { + return pFunc; + } + // AdjustWindowRectExForDpi() was made private in Win10 1507 & 1511. + if (const auto pFunc = reinterpret_cast( + SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2580)))) { + return pFunc; + } + return nullptr; + }(); + if (!pAdjustWindowRectExForDpi) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + return pAdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); +} diff --git a/src/core/utils_win.cpp b/src/core/utils_win.cpp index 3dd6c12..219b5a2 100644 --- a/src/core/utils_win.cpp +++ b/src/core/utils_win.cpp @@ -23,6 +23,12 @@ */ #include "utils.h" +#include "framelesshelper_windows.h" +#include "framelessmanager.h" +#include "framelessconfig_p.h" +#include "sysapiloader_p.h" +#include "registrykey_p.h" +#include "winverhelper_p.h" #include #include #include @@ -39,641 +45,8 @@ # include # endif // (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #endif // FRAMELESSHELPER_CORE_NO_PRIVATE -#include "framelessmanager.h" -#include "framelesshelper_windows.h" -#include "framelessconfig_p.h" -#include "sysapiloader_p.h" -#include "registrykey_p.h" -#include "winverhelper_p.h" #include -EXTERN_C_START - -_MMRESULT WINAPI -_timeGetDevCaps( - _Out_writes_bytes_(cbtc) _PTIMECAPS ptc, - _In_ UINT cbtc -); - -_MMRESULT WINAPI -_timeBeginPeriod( - _In_ UINT uPeriod -); - -_MMRESULT WINAPI -_timeEndPeriod( - _In_ UINT uPeriod -); - -HRESULT WINAPI -_SetProcessDpiAwareness( - _In_ _PROCESS_DPI_AWARENESS value -); - -HRESULT WINAPI -_GetProcessDpiAwareness( - _In_opt_ HANDLE hProcess, - _Out_ _PROCESS_DPI_AWARENESS *value -); - -HRESULT WINAPI -_GetDpiForMonitor( - _In_ HMONITOR hMonitor, - _In_ _MONITOR_DPI_TYPE dpiType, - _Out_ UINT *dpiX, - _Out_ UINT *dpiY -); - -int WINAPI -_GetSystemMetricsForDpi( - _In_ int nIndex, - _In_ UINT dpi -); - -UINT WINAPI -_GetWindowDPI( - _In_ HWND hWnd -); - -UINT WINAPI -_GetDpiForWindow( - _In_ HWND hWnd -); - -UINT WINAPI -_GetDpiForSystem( - VOID -); - -UINT WINAPI -_GetSystemDpiForProcess( - _In_ HANDLE hProcess -); - -BOOL WINAPI -_SetProcessDpiAwarenessContext( - _In_ _DPI_AWARENESS_CONTEXT value -); - -BOOL WINAPI -_SetProcessDPIAware( - VOID -); - -HRESULT WINAPI -_GetScaleFactorForMonitor( - _In_ HMONITOR hMon, - _Out_ _DEVICE_SCALE_FACTOR *pScale -); - -BOOL WINAPI -_EnableNonClientDpiScaling( - _In_ HWND hWnd -); - -_DPI_AWARENESS_CONTEXT WINAPI -_GetThreadDpiAwarenessContext( - VOID -); - -_DPI_AWARENESS_CONTEXT WINAPI -_GetWindowDpiAwarenessContext( - _In_ HWND hWnd -); - -_DPI_AWARENESS WINAPI -_GetAwarenessFromDpiAwarenessContext( - _In_ _DPI_AWARENESS_CONTEXT value -); - -_DPI_AWARENESS_CONTEXT WINAPI -_GetDpiAwarenessContextForProcess( - _In_ HANDLE hProcess -); - -BOOL WINAPI -_AreDpiAwarenessContextsEqual( - _In_ _DPI_AWARENESS_CONTEXT dpiContextA, - _In_ _DPI_AWARENESS_CONTEXT dpiContextB -); - -BOOL WINAPI -_EnableChildWindowDpiMessage( - _In_ HWND hWnd, - _In_ BOOL fEnable -); - -BOOL WINAPI -_EnablePerMonitorDialogScaling( - VOID -); - -int WINAPI -_GetDpiMetrics( - _In_ int nIndex, - _In_ UINT dpi -); - -BOOL WINAPI -_AdjustWindowRectExForDpi( - _Inout_ LPRECT lpRect, - _In_ DWORD dwStyle, - _In_ BOOL bMenu, - _In_ DWORD dwExStyle, - _In_ UINT dpi -); - -EXTERN_C_END - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_GetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvData) -{ - Q_ASSERT(hWnd); - Q_ASSERT(pvData); - if (!hWnd || !pvData) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(user32) - FRAMELESSHELPER_STRING_CONSTANT(GetWindowCompositionAttribute) - if (!API_USER_AVAILABLE(GetWindowCompositionAttribute)) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return API_CALL_FUNCTION4(GetWindowCompositionAttribute, hWnd, pvData); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_SetWindowCompositionAttribute(const HWND hWnd, PWINDOWCOMPOSITIONATTRIBDATA pvData) -{ - Q_ASSERT(hWnd); - Q_ASSERT(pvData); - if (!hWnd || !pvData) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(user32) - FRAMELESSHELPER_STRING_CONSTANT(SetWindowCompositionAttribute) - if (!API_USER_AVAILABLE(SetWindowCompositionAttribute)) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return API_CALL_FUNCTION4(SetWindowCompositionAttribute, hWnd, pvData); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API HRESULT WINAPI -_SetWindowThemeAttribute(const HWND hWnd, const _WINDOWTHEMEATTRIBUTETYPE attrib, - PVOID pvData, const DWORD cbData -) -{ - Q_ASSERT(hWnd); - Q_ASSERT(pvData); - Q_ASSERT(cbData != 0); - if (!hWnd || !pvData || (cbData == 0)) { - return E_INVALIDARG; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - FRAMELESSHELPER_STRING_CONSTANT(SetWindowThemeAttribute) - if (!API_THEME_AVAILABLE(SetWindowThemeAttribute)) { - return E_NOTIMPL; - } - return API_CALL_FUNCTION4(SetWindowThemeAttribute, hWnd, attrib, pvData, cbData); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API HRESULT WINAPI -_SetWindowThemeNonClientAttributes(const HWND hWnd, const DWORD dwMask, const DWORD dwAttributes) -{ - Q_ASSERT(hWnd); - if (!hWnd) { - return E_INVALIDARG; - } - WTA_OPTIONS2 options = {}; - options.dwFlags = dwAttributes; - options.dwMask = dwMask; - return _SetWindowThemeAttribute(hWnd, _WTA_NONCLIENT, &options, sizeof(options)); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_ShouldAppsUseDarkMode(VOID) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pShouldAppsUseDarkMode - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(132))); - if (!pShouldAppsUseDarkMode) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pShouldAppsUseDarkMode(); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_AllowDarkModeForWindow(const HWND hWnd, const BOOL bAllow) -{ - Q_ASSERT(hWnd); - if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pAllowDarkModeForWindow - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(133))); - if (!pAllowDarkModeForWindow) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pAllowDarkModeForWindow(hWnd, bAllow); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_AllowDarkModeForApp(const BOOL bAllow) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pAllowDarkModeForApp - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135))); - if (!pAllowDarkModeForApp) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pAllowDarkModeForApp(bAllow); -} - -EXTERN_C FRAMELESSHELPER_CORE_API VOID WINAPI -_FlushMenuThemes(VOID) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pFlushMenuThemes - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(136))); - if (!pFlushMenuThemes) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return; - } - pFlushMenuThemes(); -} - -EXTERN_C FRAMELESSHELPER_CORE_API VOID WINAPI -_RefreshImmersiveColorPolicyState(VOID) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pRefreshImmersiveColorPolicyState - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(104))); - if (!pRefreshImmersiveColorPolicyState) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return; - } - pRefreshImmersiveColorPolicyState(); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_IsDarkModeAllowedForWindow(const HWND hWnd) -{ - Q_ASSERT(hWnd); - if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pIsDarkModeAllowedForWindow - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(137))); - if (!pIsDarkModeAllowedForWindow) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pIsDarkModeAllowedForWindow(hWnd); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_GetIsImmersiveColorUsingHighContrast(const IMMERSIVE_HC_CACHE_MODE mode) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pGetIsImmersiveColorUsingHighContrast - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(106))); - if (!pGetIsImmersiveColorUsingHighContrast) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pGetIsImmersiveColorUsingHighContrast(mode); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API HTHEME WINAPI -_OpenNcThemeData(const HWND hWnd, LPCWSTR pszClassList) -{ - Q_ASSERT(hWnd); - Q_ASSERT(pszClassList); - if (!hWnd || !pszClassList) { - SetLastError(ERROR_INVALID_PARAMETER); - return nullptr; - } - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return nullptr; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pOpenNcThemeData - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(49))); - if (!pOpenNcThemeData) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return nullptr; - } - return pOpenNcThemeData(hWnd, pszClassList); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_ShouldSystemUseDarkMode(VOID) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pShouldSystemUseDarkMode - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(138))); - if (!pShouldSystemUseDarkMode) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pShouldSystemUseDarkMode(); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API PREFERRED_APP_MODE WINAPI -_SetPreferredAppMode(const PREFERRED_APP_MODE mode) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return PAM_MAX; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pSetPreferredAppMode - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(135))); - if (!pSetPreferredAppMode) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return PAM_MAX; - } - return pSetPreferredAppMode(mode); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_IsDarkModeAllowedForApp(VOID) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - FRAMELESSHELPER_STRING_CONSTANT(uxtheme) - static const auto pIsDarkModeAllowedForApp - = reinterpret_cast( - SysApiLoader::resolve(kuxtheme, MAKEINTRESOURCEA(139))); - if (!pIsDarkModeAllowedForApp) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pIsDarkModeAllowedForApp(); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_EnableChildWindowDpiMessage2(const HWND hWnd, const BOOL fEnable) -{ - Q_ASSERT(hWnd); - if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - using EnableChildWindowDpiMessagePtr = decltype(&::_EnableChildWindowDpiMessage); - static const auto pEnableChildWindowDpiMessage = []() -> EnableChildWindowDpiMessagePtr { - FRAMELESSHELPER_STRING_CONSTANT(win32u) - FRAMELESSHELPER_STRING_CONSTANT(NtUserEnableChildWindowDpiMessage) - // EnableChildWindowDpiMessage() was moved to "win32u.dll" and renamed to - // "NtUserEnableChildWindowDpiMessage" since Win10 1607. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kwin32u, kNtUserEnableChildWindowDpiMessage))) { - return pFunc; - } - FRAMELESSHELPER_STRING_CONSTANT(user32) - FRAMELESSHELPER_STRING_CONSTANT(EnableChildWindowDpiMessage) - // EnableChildWindowDpiMessage() was once a public API, so we can load it by name, - // but it got removed in Win10 1607, so we can't link to it directly. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, kEnableChildWindowDpiMessage))) { - return pFunc; - } - // EnableChildWindowDpiMessage() was made private since Win10 1607. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2704)))) { - return pFunc; - } - return nullptr; - }(); - if (!pEnableChildWindowDpiMessage) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pEnableChildWindowDpiMessage(hWnd, fEnable); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_EnablePerMonitorDialogScaling2(VOID) -{ - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - using EnablePerMonitorDialogScalingPtr = decltype(&::_EnablePerMonitorDialogScaling); - static const auto pEnablePerMonitorDialogScaling = []() -> EnablePerMonitorDialogScalingPtr { - FRAMELESSHELPER_STRING_CONSTANT(user32) - FRAMELESSHELPER_STRING_CONSTANT(EnablePerMonitorDialogScaling) - // EnablePerMonitorDialogScaling() was once a public API, so we can load it by name, - // but it got removed in Win10 1607, so we can't link to it directly. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, kEnablePerMonitorDialogScaling))) { - return pFunc; - } - // EnablePerMonitorDialogScaling() was made private since Win10 1607. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2577)))) { - return pFunc; - } - return nullptr; - }(); - if (!pEnablePerMonitorDialogScaling) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pEnablePerMonitorDialogScaling(); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API UINT WINAPI -_GetDpiForWindow2(const HWND hWnd) -{ - Q_ASSERT(hWnd); - if (!hWnd) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - using GetDpiForWindowPtr = decltype(&::_GetDpiForWindow); - static const auto pGetDpiForWindow = []() -> GetDpiForWindowPtr { - FRAMELESSHELPER_STRING_CONSTANT(user32) - FRAMELESSHELPER_STRING_CONSTANT(GetDpiForWindow) - // GetDpiForWindow() was made public since Win10 1607. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, kGetDpiForWindow))) { - return pFunc; - } - // GetDpiForWindow() was named "GetWindowDPI" before made public. - FRAMELESSHELPER_STRING_CONSTANT(GetWindowDPI) - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, kGetWindowDPI))) { - return pFunc; - } - // GetWindowDPI() was made private since Win10 1607. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2707)))) { - return pFunc; - } - return nullptr; - }(); - if (!pGetDpiForWindow) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - return pGetDpiForWindow(hWnd); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API int WINAPI -_GetSystemMetricsForDpi2(const int nIndex, const UINT dpi) -{ - Q_ASSERT(nIndex >= 0); - Q_ASSERT(dpi != 0); - if ((nIndex < 0) || (dpi == 0)) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - using GetSystemMetricsForDpiPtr = decltype(&::_GetSystemMetricsForDpi); - static const auto pGetSystemMetricsForDpi = []() -> GetSystemMetricsForDpiPtr { - FRAMELESSHELPER_STRING_CONSTANT(user32) - FRAMELESSHELPER_STRING_CONSTANT(GetSystemMetricsForDpi) - // GetSystemMetricsForDpi() was made public since Win10 1607. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, kGetSystemMetricsForDpi))) { - return pFunc; - } - // GetSystemMetricsForDpi() was named "GetDpiMetrics" before made public, - // that is, when in Win10 1507 & 1511. - FRAMELESSHELPER_STRING_CONSTANT(GetDpiMetrics) - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, kGetDpiMetrics))) { - return pFunc; - } - return nullptr; - }(); - if (!pGetSystemMetricsForDpi) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - } - return pGetSystemMetricsForDpi(nIndex, dpi); -} - -EXTERN_C [[nodiscard]] FRAMELESSHELPER_CORE_API BOOL WINAPI -_AdjustWindowRectExForDpi2(LPRECT lpRect, const DWORD dwStyle, - const BOOL bMenu, const DWORD dwExStyle, const UINT dpi) -{ - Q_ASSERT(lpRect); - Q_ASSERT(dpi != 0); - if (!lpRect || (dpi == 0)) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - FRAMELESSHELPER_USE_NAMESPACE - if (!WindowsVersionHelper::isWin10OrGreater()) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - using AdjustWindowRectExForDpiPtr = decltype(&::_AdjustWindowRectExForDpi); - static const auto pAdjustWindowRectExForDpi = []() -> AdjustWindowRectExForDpiPtr { - FRAMELESSHELPER_STRING_CONSTANT(user32) - FRAMELESSHELPER_STRING_CONSTANT(AdjustWindowRectExForDpi) - // AdjustWindowRectExForDpi() was made public since Win10 1607. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, kAdjustWindowRectExForDpi))) { - return pFunc; - } - // AdjustWindowRectExForDpi() was made private in Win10 1507 & 1511. - if (const auto pFunc = reinterpret_cast( - SysApiLoader::resolve(kuser32, MAKEINTRESOURCEA(2580)))) { - return pFunc; - } - return nullptr; - }(); - if (!pAdjustWindowRectExForDpi) { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; - } - return pAdjustWindowRectExForDpi(lpRect, dwStyle, bMenu, dwExStyle, dpi); -} - Q_DECLARE_METATYPE(QMargins) FRAMELESSHELPER_BEGIN_NAMESPACE @@ -1630,6 +1003,8 @@ quint32 Utils::getPrimaryScreenDpi(const bool horizontal) HRESULT hr = pD2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), nullptr, reinterpret_cast(&d2dFactory)); if (SUCCEEDED(hr)) { + // We want to get the newest system DPI, so refresh the system metrics + // manually to ensure that. hr = d2dFactory->ReloadSystemMetrics(); if (SUCCEEDED(hr)) { FLOAT dpiX = 0.0f, dpiY = 0.0f;