aboutsummaryrefslogtreecommitdiff
path: root/DarkMode.h
diff options
context:
space:
mode:
Diffstat (limited to 'DarkMode.h')
-rw-r--r--DarkMode.h184
1 files changed, 184 insertions, 0 deletions
diff --git a/DarkMode.h b/DarkMode.h
new file mode 100644
index 0000000..207ff6a
--- /dev/null
+++ b/DarkMode.h
@@ -0,0 +1,184 @@
+// https://github.com/ysc3839/win32-darkmode/blob/master/win32-darkmode/DarkMode.h
+
+#pragma once
+#include <Windows.h>
+#include <dwmapi.h>
+//#include "IatHook.h"
+
+enum IMMERSIVE_HC_CACHE_MODE
+{
+ IHCM_USE_CACHED_VALUE,
+ IHCM_REFRESH
+};
+
+// Insider 18334
+enum PreferredAppMode
+{
+ Default,
+ AllowDark,
+ ForceDark,
+ ForceLight,
+ Max
+};
+
+using fnRtlGetNtVersionNumbers = void (WINAPI *)(LPDWORD major, LPDWORD minor, LPDWORD build);
+// 1809 17763
+using fnShouldAppsUseDarkMode = bool (WINAPI *)(); // ordinal 132
+using fnAllowDarkModeForWindow = bool (WINAPI *)(HWND hWnd, bool allow); // ordinal 133
+using fnAllowDarkModeForApp = bool (WINAPI *)(bool allow); // ordinal 135, removed since 18334
+using fnFlushMenuThemes = void (WINAPI *)(); // ordinal 136
+using fnRefreshImmersiveColorPolicyState = void (WINAPI *)(); // ordinal 104
+using fnIsDarkModeAllowedForWindow = bool (WINAPI *)(HWND hWnd); // ordinal 137
+using fnGetIsImmersiveColorUsingHighContrast = bool (WINAPI *)(IMMERSIVE_HC_CACHE_MODE mode); // ordinal 106
+using fnOpenNcThemeData = HTHEME(WINAPI *)(HWND hWnd, LPCWSTR pszClassList); // ordinal 49
+ // Insider 18290
+using fnShouldSystemUseDarkMode = bool (WINAPI *)(); // ordinal 138
+ // Insider 18334
+using fnSetPreferredAppMode = PreferredAppMode(WINAPI *)(PreferredAppMode appMode); // ordinal 135, since 18334
+using fnIsDarkModeAllowedForApp = bool (WINAPI *)(); // ordinal 139
+
+fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode = nullptr;
+fnAllowDarkModeForWindow _AllowDarkModeForWindow = nullptr;
+fnAllowDarkModeForApp _AllowDarkModeForApp = nullptr;
+fnFlushMenuThemes _FlushMenuThemes = nullptr;
+fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = nullptr;
+fnIsDarkModeAllowedForWindow _IsDarkModeAllowedForWindow = nullptr;
+fnGetIsImmersiveColorUsingHighContrast _GetIsImmersiveColorUsingHighContrast = nullptr;
+fnOpenNcThemeData _OpenNcThemeData = nullptr;
+// Insider 18290
+fnShouldSystemUseDarkMode _ShouldSystemUseDarkMode = nullptr;
+// Insider 18334
+fnSetPreferredAppMode _SetPreferredAppMode = nullptr;
+
+bool g_darkModeSupported = false;
+bool g_darkModeEnabled = false;
+DWORD g_buildNumber = 0;
+
+bool AllowDarkModeForWindow(HWND hWnd, bool allow)
+{
+ if (g_darkModeSupported)
+ return _AllowDarkModeForWindow(hWnd, allow);
+ return false;
+}
+
+bool IsHighContrast()
+{
+ HIGHCONTRASTW highContrast = { sizeof(highContrast) };
+ if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE))
+ return highContrast.dwFlags & HCF_HIGHCONTRASTON;
+ return false;
+}
+
+void RefreshTitleBarThemeColor(HWND hWnd)
+{
+ BOOL dark = FALSE;
+ if (_IsDarkModeAllowedForWindow(hWnd) &&
+ _ShouldAppsUseDarkMode() &&
+ !IsHighContrast())
+ {
+ dark = TRUE;
+ }
+ DwmSetWindowAttribute(hWnd, 19, &dark, sizeof(dark));
+}
+
+bool IsColorSchemeChangeMessage(LPARAM lParam)
+{
+ bool is = false;
+ if (lParam && CompareStringOrdinal(reinterpret_cast<LPCWCH>(lParam), -1, L"ImmersiveColorSet", -1, TRUE) == CSTR_EQUAL)
+ {
+ _RefreshImmersiveColorPolicyState();
+ is = true;
+ }
+ _GetIsImmersiveColorUsingHighContrast(IHCM_REFRESH);
+ return is;
+}
+
+bool IsColorSchemeChangeMessage(UINT message, LPARAM lParam)
+{
+ if (message == WM_SETTINGCHANGE)
+ return IsColorSchemeChangeMessage(lParam);
+ return false;
+}
+
+void AllowDarkModeForApp(bool allow)
+{
+ if (_AllowDarkModeForApp)
+ _AllowDarkModeForApp(allow);
+ else if (_SetPreferredAppMode)
+ _SetPreferredAppMode(allow ? AllowDark : Default);
+}
+
+void FixDarkScrollBar()
+{
+#if 0
+ auto addr = FindDelayLoadThunkInModule(GetModuleHandleW(L"comctl32.dll"), "uxtheme.dll", 49); // OpenNcThemeData
+ if (addr)
+ {
+ DWORD oldProtect;
+ if (VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), PAGE_READWRITE, &oldProtect))
+ {
+ auto MyOpenThemeData = [](HWND hWnd, LPCWSTR classList) -> HTHEME {
+ if (wcscmp(classList, L"ScrollBar") == 0)
+ {
+ hWnd = nullptr;
+ classList = L"Explorer::ScrollBar";
+ }
+ return _OpenNcThemeData(hWnd, classList);
+ };
+
+ addr->u1.Function = reinterpret_cast<ULONG_PTR>(static_cast<fnOpenNcThemeData>(MyOpenThemeData));
+ VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), oldProtect, &oldProtect);
+ }
+ }
+#endif
+}
+
+void InitDarkMode()
+{
+ fnRtlGetNtVersionNumbers RtlGetNtVersionNumbers = reinterpret_cast<fnRtlGetNtVersionNumbers>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetNtVersionNumbers"));
+ if (RtlGetNtVersionNumbers)
+ {
+ DWORD major, minor;
+ RtlGetNtVersionNumbers(&major, &minor, &g_buildNumber);
+ g_buildNumber &= ~0xF0000000;
+ if (major == 10 && minor == 0 && 17763 <= g_buildNumber && g_buildNumber <= 18362) // Windows 10 1809 10.0.17763 - 1903 10.0.18362
+ {
+ HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (hUxtheme)
+ {
+ _OpenNcThemeData = reinterpret_cast<fnOpenNcThemeData>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(49)));
+ _RefreshImmersiveColorPolicyState = reinterpret_cast<fnRefreshImmersiveColorPolicyState>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));
+ _GetIsImmersiveColorUsingHighContrast = reinterpret_cast<fnGetIsImmersiveColorUsingHighContrast>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(106)));
+ _ShouldAppsUseDarkMode = reinterpret_cast<fnShouldAppsUseDarkMode>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));
+ _AllowDarkModeForWindow = reinterpret_cast<fnAllowDarkModeForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)));
+
+ auto ord135 = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
+ if (g_buildNumber < 18334)
+ _AllowDarkModeForApp = reinterpret_cast<fnAllowDarkModeForApp>(ord135);
+ else
+ _SetPreferredAppMode = reinterpret_cast<fnSetPreferredAppMode>(ord135);
+
+ //_FlushMenuThemes = reinterpret_cast<fnFlushMenuThemes>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)));
+ _IsDarkModeAllowedForWindow = reinterpret_cast<fnIsDarkModeAllowedForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(137)));
+
+ if (_OpenNcThemeData &&
+ _RefreshImmersiveColorPolicyState &&
+ _ShouldAppsUseDarkMode &&
+ _AllowDarkModeForWindow &&
+ (_AllowDarkModeForApp || _SetPreferredAppMode) &&
+ //_FlushMenuThemes &&
+ _IsDarkModeAllowedForWindow)
+ {
+ g_darkModeSupported = true;
+
+ AllowDarkModeForApp(true);
+ _RefreshImmersiveColorPolicyState();
+
+ g_darkModeEnabled = _ShouldAppsUseDarkMode() && !IsHighContrast();
+
+ FixDarkScrollBar();
+ }
+ }
+ }
+ }
+}