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.
Whether apps should use dark mode or not.
typedef bool (WINAPI* ShouldAppsUseDarkMode_t)(); // ordinal 132Dark 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 135New 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
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
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.
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));
}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));
}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.
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.
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/

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.