C language > User contributions

Enable Dark Mode for Title bar

(1/8) > >>

WiiLF23:
This will turn on Dark Mode for the window title bar.


--- Code: ---#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")

#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#endif

static INT_PTR CALLBACK MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg)
    {
        case WM_INITDIALOG:
        {
                // Enable dark mode title bar
                BOOL value = TRUE;
                DwmSetWindowAttribute(hwndDlg, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));

                ...

--- End code ---

https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/apply-windows-themes#enable-a-dark-mode-title-bar-for-win32-applications

Toggle DarkMode/LightMode


--- Code: ---BOOL isDarkModeEnabled = FALSE;

void ToggleDarkMode(HWND hWnd) {
    isDarkModeEnabled = !isDarkModeEnabled;

    // Enable or disable dark mode title bar
    BOOL value = isDarkModeEnabled;
    DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));

    RECT rc;
    GetWindowRect(hWnd, &rc);

    if (isDarkModeEnabled) {
        // Increase window size by 1 pixel
        MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left + 1, rc.bottom - rc.top + 1, TRUE);
    } else {
        // Decrease window size by 1 pixel
        MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left - 1, rc.bottom - rc.top - 1, TRUE);
    }
}

--- End code ---

Turning Some Elements Dark
Undocumented - https://stackoverflow.com/a/53545935/2694720


--- Code: ---#include <uxtheme.h>
#pragma comment(lib, "uxtheme.lib")

void ApplyDarkModeToControls(HWND hwnd, BOOL darkMode)
{
    HWND hChild = GetWindow(hwnd, GW_CHILD);

    while (hChild)
    {
        if (darkMode)
        {
            SetWindowTheme(hChild, L"DarkMode_Explorer", NULL);
        }
        else
        {
            SetWindowTheme(hChild, NULL, NULL);
        }

        ApplyDarkModeToControls(hChild, darkMode);
        hChild = GetWindow(hChild, GW_HWNDNEXT);
    }
}

void ToggleDarkMode(HWND hWnd)
{
    isDarkModeEnabled = !isDarkModeEnabled;

    // Enable or disable dark mode title bar
    BOOL value = isDarkModeEnabled;
    DwmSetWindowAttribute(hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));

    // Apply the theme to all child controls recursively
    ApplyDarkModeToControls(hWnd, isDarkModeEnabled);

    RECT rc;
    GetWindowRect(hWnd, &rc);

    if (isDarkModeEnabled)
    {
        MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left + 1, rc.bottom - rc.top + 1, TRUE);
    }
    else
    {
        MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left - 1, rc.bottom - rc.top - 1, TRUE);
    }
}

--- End code ---

I hope to actually implement a full window + full control solution

https://gist.github.com/rounk-ctrl/b04e5622e30e0d62956870d5c22b7017

Enjoy!

John Z:
Hi WiiLF23,

Thanks for the example and links.  I've not used uxtheme.lib so nice to see an example. 

In a program I gave the user the ability to create and save 5 themes themselves not dependent on the system theme but with some limitations. like the toolbar and menu.  Maybe I'll try uxtheme for them.

John Z

WiiLF23:

--- Quote from: John Z on January 07, 2024, 09:22:39 PM ---Hi WiiLF23,

Thanks for the example and links.  I've not used uxtheme.lib so nice to see an example. 

In a program I gave the user the ability to create and save 5 themes themselves not dependent on the system theme but with some limitations. like the toolbar and menu.  Maybe I'll try uxtheme for them.

John Z

--- End quote ---

Most welcome! I am currently implementing the full experience and I have dark mode for Menu now. The only issue im having, is applying the menu theme by calling when desired. Menu only darkens when I call in WM_INITDIALOG message.

Current progress, working successfully for full menu dark mode:


--- Code: ---typedef BOOL(WINAPI* fnShouldAppsUseDarkMode)();
typedef BOOL(WINAPI* fnAllowDarkModeForWindow)(HWND hWnd, BOOL allow);
typedef DWORD(WINAPI* fnSetPreferredAppMode)(DWORD appMode);

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

HMODULE hUxtheme;

fnShouldAppsUseDarkMode ShouldAppsUseDarkMode;
fnAllowDarkModeForWindow AllowDarkModeForWindow;
fnSetPreferredAppMode SetPreferredAppMode;

void InitDarkMode()
{
    hUxtheme = LoadLibraryExW(L"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
    if (hUxtheme)
    {
        ShouldAppsUseDarkMode = (fnShouldAppsUseDarkMode)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132));
        AllowDarkModeForWindow = (fnAllowDarkModeForWindow)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133));
        SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
    }
}

--- End code ---

WM_INITDIALOG:

--- Code: ---InitDarkMode();
SetPreferredAppMode(ForceDark); // options in enum

--- End code ---

WM_DESTROY:

--- Code: ---FreeLibrary(hUxtheme);

--- End code ---





John Z:
Hi WiiLF23,


--- Quote from: WiiLF23 on January 08, 2024, 02:17:28 AM ---The only issue im having, is applying the menu theme by calling when desired. Menu only darkens when I call in WM_INITDIALOG message.

--- End quote ---

Most Menu changes need to be followed up by  DrawMenuBar(gHWND);  might be worth a try.

John Z

WiiLF23:
Redraw, Invalidate, DrawMenu all fail on the parent window. Its a strange issue. I read that Microsoft decided not to expose a lot of the API for dark mode for winapi so a lot of people have discussed it over time, not very happy with their findings etc but its intended for UWP apps, so its short of a miracle to get it this far at the moment.


At this point, I will keep the current dark controls possible, and paint the window and the rest of the controls accordingly. Starting to learn about this as we speak, I think this is the best option.


--- Code: ---case WM_PAINT: {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwndDlg, &ps);

    // Set the background color to dark (black)
    SetBkColor(hdc, RGB(0, 0, 0));
    ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &ps.rcPaint, NULL, 0, NULL);

    EndPaint(hwndDlg, &ps);
    return 0;
}

--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version