Skip to content

Instantly share code, notes, and snippets.

@rounk-ctrl
Last active November 5, 2024 23:03
Show Gist options
  • Save rounk-ctrl/b04e5622e30e0d62956870d5c22b7017 to your computer and use it in GitHub Desktop.
Save rounk-ctrl/b04e5622e30e0d62956870d5c22b7017 to your computer and use it in GitHub Desktop.
Win32 Dark Mode

Dark Mode APIs.

API Signatures.

ShouldAppsUseDarkMode()

Checks whether system is using dark mode or not.
Signature:

using fnShouldAppsUseDarkMode = bool (WINAPI*)(); // ordinal 132

AllowDarkModeForWindow(In HWND hWnd, In bool allow)

Switches the control's theme to the dark variant if available.
Signature:

using fnAllowDarkModeForWindow = bool (WINAPI*)(HWND hWnd, bool allow); // ordinal 133

SetPreferredAppMode(In PreferredAppMode appMode)

Dark Context menu for the app. I don't know what else this does.
Signature(1903+):

using fnSetPreferredAppMode = PreferredAppMode(WINAPI*)(PreferredAppMode appMode); // ordinal 135, in 1903

PreferredAppMode enum

enum class PreferredAppMode
{
   Default,
   AllowDark,
   ForceDark,
   ForceLight,
   Max
};

Actually using them.

First we need to load uxtheme dll as a HMODULE.

HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);

Then we need to get the Process Address of the functions. We already know their ordinal numbers.
First initialize a instance of the signature.

fnSetPreferredAppMode SetPreferredAppMode;

then set the process address by using GetProcAddress

SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));

You can do like this for any API. Dont forget to free it

FreeLibrary(hUxtheme);

Usage.

Enables dark context menus which change automatically depending on the theme.

SetPreferredAppMode(PreferredAppMode::AllowDark);

Dark Controls:

First we need to know which all controls support Dark Mode.
If you open aero.msstyles in msstylesEditor, you would be able to see a lot of DarkMode elements.

image
And no you cant just do SetWindowTheme([handle to the control], L"DarkMode_Explorer", NULL);

Button:
SetWindowTheme([handle to the control], L"Explorer", NULL);
AllowDarkModeForWindow([handle to the control], true);
SendMessageW([handle to the control], WM_THEMECHANGED, 0, 0);
Edit:
SetWindowTheme([handle to the control], L"CFD", NULL);
AllowDarkModeForWindow([handle to the control], true);
SendMessageW([handle to the control], WM_THEMECHANGED, 0, 0);
ComboBox:
SetWindowTheme([handle to the control], L"CFD", NULL);
AllowDarkModeForWindow([handle to the control], true);
SendMessageW([handle to the control], WM_THEMECHANGED, 0, 0);
TreeView (maybe):
SetWindowTheme([handle to the control], L"Explorer", NULL);
AllowDarkModeForWindow([handle to the control], true);
SendMessageW([handle to the control], WM_THEMECHANGED, 0, 0);
Dark Scrollbars:

For dark scrollbars you need to iat hook and change the scrollbar theme before its created.
First download this header file and add it to your project. IatHook.h
Then use this function before the creation of HWND.

void FixDarkScrollBar()
{
	HMODULE hComctl = LoadLibraryExW(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
	if (hComctl)
	{
		auto addr = FindDelayLoadThunkInModule(hComctl, "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);
			}
		}
	}
}
@jjYBdx4IL
Copy link

I can't. It's not my app. I'm just plugging in a plugin dll.

https://github.com/jjYBdx4IL/ReaperThemeHackDll

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment