Skip to content

Instantly share code, notes, and snippets.

@rounk-ctrl
Last active March 7, 2026 17:32
Show Gist options
  • Select an option

  • Save rounk-ctrl/b04e5622e30e0d62956870d5c22b7017 to your computer and use it in GitHub Desktop.

Select an option

Save rounk-ctrl/b04e5622e30e0d62956870d5c22b7017 to your computer and use it in GitHub Desktop.
Win32 Dark Mode

Dark Mode

How to use the newly added dark mode system added in recent Windows 11 builds. They added a dark mode variant of almost every control.

API Signatures.

ShouldAppsUseDarkMode

Whether apps should use dark mode or not.

typedef bool (WINAPI* ShouldAppsUseDarkMode_t)(); // ordinal 132

SetPreferredAppMode

Dark Context menu for the app. I don't know what else this does.

enum class PreferredAppMode
{
	Default,
	AllowDark,
	ForceDark,
	ForceLight,
	Max
};
typedef PreferredAppMode (WINAPI* SetPreferredAppMode_t)(PreferredAppMode); // ordinal 135

AllowDarkModeForWindowWithParentFallback

New function in recent Windows 11 builds.
bAutoThemeChange- it will automatically switch the controls whenever theme change happens between light and dark mode.

typedef bool (WINAPI* AllowDarkModeForWindowWithParentFallback_t)(HWND, bool bAutoThemeChange); // ordinal 145

Importing the functions

This is how we load functions exported as ordinals by any dll:

HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
SetPreferredAppMode_t SetPreferredAppMode;
SetPreferredAppMode = (SetPreferredAppMode_t)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));

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

Using them

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

SetPreferredAppMode(PreferredAppMode::AllowDark);

To apply to all controls, just call AllowDarkModeForWindowWithParentFallback on the main HWND

AllowDarkModeForWindowWithParentFallback(hWnd, TRUE);

All supported controls will automatically get dark mode. But some stubborn controls still don't work (atleast for me), for that you need to handle it in the wndproc.

Static control

The background of the static control doesnt change
clr- the background color of the static

case WM_CTLCOLORSTATIC: 
{
	if (ShouldAppsUseDarkMode())
	{
		HDC hdc = reinterpret_cast<HDC>(wParam);
		SetBkMode(hdc, TRANSPARENT);
	}
	return reinterpret_cast<INT_PTR>(CreateSolidBrush(clr));
}

Button

There will be a while border around the button if you dont do this

case WM_CTLCOLORBTN:
{
	if (ShouldAppsUseDarkMode())
	{
		HDC hdc = reinterpret_cast<HDC>(wParam);
		SetBkMode(hdc, TRANSPARENT);
	}
	return reinterpret_cast<INT_PTR>(CreateSolidBrush(clr));
}

Combobox/Edit

Their text field will behave weirdly

case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
{
	if (ShouldAppsUseDarkMode())
	{
		HDC hdc = reinterpret_cast<HDC>(wParam);
		SetBkColor(hdc, editBg);
		SetTextColor(hdc, clrTxt);
	}
	return reinterpret_cast<INT_PTR>(CreateSolidBrush(editBg));
}

Update the stored color values accordingly whenever theme changes by refreshing it in WM_THEMECHANGED.
For window background, handle WM_ERASEBKGND.

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);
			}
		}
	}
}

For a sample project, check https://github.com/rounk-ctrl/win32-darkmode/

@0xF5T9
Copy link

0xF5T9 commented Sep 19, 2022

Hi, thank you for sharing the info.
May I ask how to set the menu bar to dark mode? I've tried to send TB_SETWINDOWTHEME message (DarkMode_Explorer) but nothing changed.

It happen in the original example code as well and not just my project
The menu bar is white by default and dropdown menu always in dark mode

I'm sorry if this isn't the right place to ask.

EDIT: I'm using latest Windows Version
EDIT: End up custom draw the menu bar, Thank you @rounk-ctrl.

@rounk-ctrl
Copy link
Author

Oh, for that you need to custom paint it. i think notepad++ has an implementation.

btw its menu bar not toolbar

@jjYBdx4IL
Copy link

I'm calling SetPreferredAppMode(PreferredAppMode::AllowDark) when the windows are already visible. I have to toggle fullscreen on and off to make the change affect menu popups. Is there any way to push the change through programmatically?

@rounk-ctrl
Copy link
Author

you can call that function at the beginning of your app, before any window is created. it will auto change the popup menu theme and stuff if you switch between dark and light

@jjYBdx4IL
Copy link

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

https://github.com/jjYBdx4IL/ReaperThemeHackDll

@ajtruckle
Copy link

@rounk-ctrl Are you able to show me the code to ownerdrawcthe menu bar? 🙏

@ajtruckle
Copy link

@0xF5T9 I think it was you who made ownerdraw menu bar? Any pointers appreciated. 🙏

@ajtruckle
Copy link

I got menu bar working.

@abrudz
Copy link

abrudz commented Jun 5, 2025

@ajtruckle Congrats! Can you post the code for that?

@ajtruckle
Copy link

@abrudz

I include the #include "UAHMenuBar.h" header. You can get that header from this repository:

https://github.com/adzm/win32-custom-menubar-aero-theme/tree/main

Then, in my dialog I override WindowProc using classwizard and do:

LRESULT DarkModeTools::CDarkModeDialogEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if (IsUsingDarkMode())
	{
		LRESULT lr = 0;
		if (UAHWndProc(GetSafeHwnd(), message, wParam, lParam, &lr)) {
			return lr;
		}
	}

	return __super::WindowProc(message, wParam, lParam);
}

You code IsUsingDarkMode() yourself as required for your app.

image

@Abdullah-Ajeebi
Copy link

I tried getting the TreeView to become dark, but no matter what, it stayed light. Anyone has a fix?

@rounk-ctrl
Copy link
Author

@Abdullah-Ajeebi try this new method for windows 11, it supports treeview

@ajtruckle
Copy link

@rounk-ctrl what new method?

@rounk-ctrl
Copy link
Author

check the gist, i updated it

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