CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Windows/W32Util/DarkMode.cpp
Views: 1401
#include "IatHook.h"1#include "DarkMode.h"23fnSetWindowCompositionAttribute _SetWindowCompositionAttribute = nullptr;4fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode = nullptr;5fnAllowDarkModeForWindow _AllowDarkModeForWindow = nullptr;6fnAllowDarkModeForApp _AllowDarkModeForApp = nullptr;7fnFlushMenuThemes _FlushMenuThemes = nullptr;8fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = nullptr;9fnIsDarkModeAllowedForWindow _IsDarkModeAllowedForWindow = nullptr;10fnGetIsImmersiveColorUsingHighContrast _GetIsImmersiveColorUsingHighContrast = nullptr;11fnOpenNcThemeData _OpenNcThemeData = nullptr;12// 1903 1836213fnShouldSystemUseDarkMode _ShouldSystemUseDarkMode = nullptr;14fnSetPreferredAppMode _SetPreferredAppMode = nullptr;15fnSetWindowTheme _SetWindowTheme = nullptr;1617bool g_darkModeSupported = false;18bool g_darkModeEnabled = false;19DWORD g_buildNumber = 0;2021bool AllowDarkModeForWindow(HWND hWnd, bool allow)22{23if (g_darkModeSupported)24return _AllowDarkModeForWindow(hWnd, allow);25return false;26}2728bool IsHighContrast()29{30HIGHCONTRASTW highContrast = { sizeof(highContrast) };31if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE))32return highContrast.dwFlags & HCF_HIGHCONTRASTON;33return false;34}3536void RefreshTitleBarThemeColor(HWND hWnd)37{38BOOL dark = FALSE;39if (_IsDarkModeAllowedForWindow(hWnd) &&40_ShouldAppsUseDarkMode() &&41!IsHighContrast())42{43dark = TRUE;44}45if (g_buildNumber < 18362)46SetPropW(hWnd, L"UseImmersiveDarkModeColors", reinterpret_cast<HANDLE>(static_cast<INT_PTR>(dark)));47else if (_SetWindowCompositionAttribute)48{49WINDOWCOMPOSITIONATTRIBDATA data = { WCA_USEDARKMODECOLORS, &dark, sizeof(dark) };50_SetWindowCompositionAttribute(hWnd, &data);51}52}5354bool IsColorSchemeChangeMessage(LPARAM lParam)55{56bool is = false;57if (lParam && CompareStringOrdinal(reinterpret_cast<LPCWCH>(lParam), -1, L"ImmersiveColorSet", -1, TRUE) == CSTR_EQUAL)58{59_RefreshImmersiveColorPolicyState();60is = true;61}62_GetIsImmersiveColorUsingHighContrast(IHCM_REFRESH);63return is;64}6566bool IsColorSchemeChangeMessage(UINT message, LPARAM lParam)67{68if (message == WM_SETTINGCHANGE)69return IsColorSchemeChangeMessage(lParam);70return false;71}7273void AllowDarkModeForApp(bool allow)74{75if (_AllowDarkModeForApp)76_AllowDarkModeForApp(allow);77else if (_SetPreferredAppMode)78_SetPreferredAppMode(allow ? AllowDark : Default);79}8081void FixDarkScrollBar()82{83// Disable this, doesn't look good.84return;8586HMODULE hComctl = LoadLibraryExW(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);87if (hComctl)88{89auto addr = FindDelayLoadThunkInModule(hComctl, "uxtheme.dll", 49); // OpenNcThemeData90if (addr)91{92DWORD oldProtect;93if (VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), PAGE_READWRITE, &oldProtect))94{95auto MyOpenThemeData = [](HWND hWnd, LPCWSTR classList) -> HTHEME {96if (wcscmp(classList, L"ScrollBar") == 0)97{98hWnd = nullptr;99classList = L"Explorer::ScrollBar";100}101return _OpenNcThemeData(hWnd, classList);102};103104addr->u1.Function = reinterpret_cast<ULONG_PTR>(static_cast<fnOpenNcThemeData>(MyOpenThemeData));105VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), oldProtect, &oldProtect);106}107}108}109}110111void DarkModeInitDialog(HWND hDlg) {112if (g_darkModeSupported) {113_SetWindowTheme(GetDlgItem(hDlg, IDOK), L"Explorer", nullptr);114SendMessageW(hDlg, WM_THEMECHANGED, 0, 0);115}116}117118LRESULT DarkModeDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {119constexpr COLORREF darkBkColor = 0x383838;120constexpr COLORREF darkTextColor = 0xFFFFFF;121static HBRUSH hbrBkgnd = nullptr;122123switch (message) {124case WM_CTLCOLORDLG:125case WM_CTLCOLORSTATIC:126{127if (g_darkModeSupported && g_darkModeEnabled)128{129HDC hdc = reinterpret_cast<HDC>(wParam);130SetTextColor(hdc, darkTextColor);131SetBkColor(hdc, darkBkColor);132if (!hbrBkgnd)133hbrBkgnd = CreateSolidBrush(darkBkColor);134return reinterpret_cast<INT_PTR>(hbrBkgnd);135}136break;137}138case WM_SETTINGCHANGE:139{140if (g_darkModeSupported && IsColorSchemeChangeMessage(lParam))141SendMessageW(hDlg, WM_THEMECHANGED, 0, 0);142break;143}144case WM_THEMECHANGED:145{146if (g_darkModeSupported)147{148_AllowDarkModeForWindow(hDlg, g_darkModeEnabled);149RefreshTitleBarThemeColor(hDlg);150151HWND hButton = GetDlgItem(hDlg, IDOK);152_AllowDarkModeForWindow(hButton, g_darkModeEnabled);153SendMessageW(hButton, WM_THEMECHANGED, 0, 0);154155UpdateWindow(hDlg);156}157break;158}159}160return FALSE;161}162163bool IsDarkModeEnabled() {164return g_darkModeEnabled;165}166167constexpr bool CheckBuildNumber(DWORD buildNumber)168{169// TODO: This is BS.170171return (buildNumber == 17763 || // 1809172buildNumber == 18362 || // 1903173buildNumber == 18363 || // 1909174buildNumber >= 19041); // Windows 11175}176177void InitDarkMode()178{179auto RtlGetNtVersionNumbers = reinterpret_cast<fnRtlGetNtVersionNumbers>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetNtVersionNumbers"));180if (RtlGetNtVersionNumbers)181{182DWORD major, minor;183RtlGetNtVersionNumbers(&major, &minor, &g_buildNumber);184g_buildNumber &= ~0xF0000000;185if (major == 10 && minor == 0 && CheckBuildNumber(g_buildNumber))186{187HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);188if (hUxtheme)189{190_OpenNcThemeData = reinterpret_cast<fnOpenNcThemeData>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(49)));191_RefreshImmersiveColorPolicyState = reinterpret_cast<fnRefreshImmersiveColorPolicyState>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));192_GetIsImmersiveColorUsingHighContrast = reinterpret_cast<fnGetIsImmersiveColorUsingHighContrast>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(106)));193_ShouldAppsUseDarkMode = reinterpret_cast<fnShouldAppsUseDarkMode>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));194_AllowDarkModeForWindow = reinterpret_cast<fnAllowDarkModeForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)));195196auto ord135 = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));197if (g_buildNumber < 18362)198_AllowDarkModeForApp = reinterpret_cast<fnAllowDarkModeForApp>(ord135);199else200_SetPreferredAppMode = reinterpret_cast<fnSetPreferredAppMode>(ord135);201202//_FlushMenuThemes = reinterpret_cast<fnFlushMenuThemes>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)));203_IsDarkModeAllowedForWindow = reinterpret_cast<fnIsDarkModeAllowedForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(137)));204205_SetWindowCompositionAttribute = reinterpret_cast<fnSetWindowCompositionAttribute>(GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetWindowCompositionAttribute"));206_SetWindowTheme = reinterpret_cast<fnSetWindowTheme>(GetProcAddress(hUxtheme, "SetWindowTheme"));207208if (_OpenNcThemeData &&209_RefreshImmersiveColorPolicyState &&210_ShouldAppsUseDarkMode &&211_AllowDarkModeForWindow &&212(_AllowDarkModeForApp || _SetPreferredAppMode) &&213//_FlushMenuThemes &&214_IsDarkModeAllowedForWindow)215{216g_darkModeSupported = true;217218AllowDarkModeForApp(true);219_RefreshImmersiveColorPolicyState();220221g_darkModeEnabled = _ShouldAppsUseDarkMode() && !IsHighContrast();222223FixDarkScrollBar();224}225}226}227}228}229230231