mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-29 16:44:13 +08:00
192 lines
5.4 KiB
C++
192 lines
5.4 KiB
C++
#include <Windows.h>
|
|
#include <stdint.h>
|
|
#include <dwmapi.h>
|
|
#include <string>
|
|
#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;
|
|
} |