恍兮惚兮 bcf500fdf9 pch
2024-05-03 01:54:36 +08:00

188 lines
5.4 KiB
C++

#include "define.h"
// https://github.com/Blinue/Xaml-Islands-Cpp/blob/main/src/XamlIslandsCpp/XamlWindow.h
enum WindowBackdrop : int32_t
{
SolidColor = 0,
Acrylic = 1,
Mica = 2,
MicaAlt = 3,
};
static uint32_t GetOSBuild() noexcept
{
HMODULE hNtDll = GetModuleHandle(L"ntdll.dll");
if (!hNtDll)
{
return 0;
}
auto rtlGetVersion = (LONG(WINAPI *)(PRTL_OSVERSIONINFOW))GetProcAddress(hNtDll, "RtlGetVersion");
if (rtlGetVersion == nullptr)
{
// assert(false);
return 0;
}
RTL_OSVERSIONINFOW version{};
version.dwOSVersionInfoSize = sizeof(version);
rtlGetVersion(&version);
return version.dwBuildNumber;
}
struct Win32Helper
{
struct OSVersion
{
constexpr OSVersion(uint32_t build) : _build(build) {}
bool Is20H1OrNewer() const noexcept
{
return _build >= 19041;
}
// 下面为 Win11
// 不考虑代号相同的 Win10
bool IsWin11() const noexcept
{
return Is21H2OrNewer();
}
bool Is21H2OrNewer() const noexcept
{
return _build >= 22000;
}
bool Is22H2OrNewer() const noexcept
{
return _build >= 22621;
}
private:
uint32_t _build = 0;
};
static OSVersion GetOSVersion() noexcept;
};
Win32Helper::OSVersion Win32Helper::GetOSVersion() noexcept
{
static OSVersion version = GetOSBuild();
return version;
}
enum class PreferredAppMode
{
Default,
AllowDark,
ForceDark,
ForceLight,
Max
};
using fnSetPreferredAppMode = PreferredAppMode(WINAPI *)(PreferredAppMode appMode);
using fnAllowDarkModeForWindow = bool(WINAPI *)(HWND hWnd, bool allow);
using fnRefreshImmersiveColorPolicyState = void(WINAPI *)();
using fnFlushMenuThemes = void(WINAPI *)();
// using fnDwmSetWindowAttribute=HRESULT (WINAPI*)(HWND,DWORD,LPCVOID,DWORD);
static fnSetPreferredAppMode SetPreferredAppMode = nullptr;
static fnAllowDarkModeForWindow AllowDarkModeForWindow = nullptr;
static fnRefreshImmersiveColorPolicyState RefreshImmersiveColorPolicyState = nullptr;
static fnFlushMenuThemes FlushMenuThemes = nullptr;
// static fnDwmSetWindowAttribute DwmSetWindowAttribute=nullptr;
static bool initok()
{
return SetPreferredAppMode && AllowDarkModeForWindow && RefreshImmersiveColorPolicyState && FlushMenuThemes; //&&DwmSetWindowAttribute;
}
static bool InitApis() noexcept
{
if (initok())
return true;
HMODULE hUxtheme = LoadLibrary(L"uxtheme.dll");
// assert(hUxtheme);
SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
AllowDarkModeForWindow = (fnAllowDarkModeForWindow)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133));
RefreshImmersiveColorPolicyState = (fnRefreshImmersiveColorPolicyState)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104));
FlushMenuThemes = (fnFlushMenuThemes)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136));
// HMODULE hdwmapi = LoadLibrary(L"dwmapi.dll");
// DwmSetWindowAttribute = (fnDwmSetWindowAttribute)GetProcAddress(hdwmapi, "DwmSetWindowAttribute");
return initok();
}
static void SetWindowTheme(HWND hWnd, bool darkBorder, bool darkMenu) noexcept
{
if (!InitApis())
return;
SetPreferredAppMode(darkMenu ? PreferredAppMode::ForceDark : PreferredAppMode::ForceLight);
AllowDarkModeForWindow(hWnd, darkMenu);
// 使标题栏适应黑暗模式
// build 18985 之前 DWMWA_USE_IMMERSIVE_DARK_MODE 的值不同
// https://github.com/MicrosoftDocs/sdk-api/pull/966/files
constexpr const DWORD DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19;
BOOL value = darkBorder;
DwmSetWindowAttribute(
hWnd,
Win32Helper::GetOSVersion().Is20H1OrNewer() ? DWMWA_USE_IMMERSIVE_DARK_MODE : DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1,
&value,
sizeof(value));
RefreshImmersiveColorPolicyState();
FlushMenuThemes();
}
bool _SetTheme(
HWND _hWnd,
bool dark,
int backdrop)
{
auto _isBackgroundSolidColor = backdrop == WindowBackdrop::SolidColor;
if (Win32Helper::GetOSVersion().Is22H2OrNewer() &&
_isBackgroundSolidColor != (backdrop == WindowBackdrop::SolidColor))
{
return true;
}
// Win10 中即使在亮色主题下我们也使用暗色边框,这也是 UWP 窗口的行为
SetWindowTheme(
_hWnd,
Win32Helper::GetOSVersion().IsWin11() ? dark : true,
dark);
if (!Win32Helper::GetOSVersion().Is22H2OrNewer())
{
return false;
}
// 设置背景
static const DWM_SYSTEMBACKDROP_TYPE BACKDROP_MAP[] = {
DWMSBT_AUTO, DWMSBT_TRANSIENTWINDOW, DWMSBT_MAINWINDOW, DWMSBT_TABBEDWINDOW};
DWM_SYSTEMBACKDROP_TYPE value = BACKDROP_MAP[(int)backdrop];
DwmSetWindowAttribute(_hWnd, DWMWA_SYSTEMBACKDROP_TYPE, &value, sizeof(value));
return false;
}
DECLARE bool isDark()
{
HKEY hKey;
const char *subKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
if (RegOpenKeyExA(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
DWORD value;
DWORD dataSize = sizeof(DWORD);
if (RegQueryValueExA(hKey, "AppsUseLightTheme", 0, NULL, (LPBYTE)&value, &dataSize) == ERROR_SUCCESS)
{
RegCloseKey(hKey);
return 1 - value;
}
RegCloseKey(hKey);
}
return false;
}