HeaderPane
Main

Dark Mode Support

Share Link
Print

SftDarkMode_HandleDialogMessage

Handle dark-mode-related dialog or window messages. Paints WM_CTLCOLOR* responses with the dark palette, repaints radio-button labels in dark text, and re-applies dark mode to the dialog and children when the user flips the Windows setting at runtime.

C

BOOL SftDarkMode_HandleDialogMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam, INT_PTR* pResult);

#define SftDarkMode_HandleWindowMessage SftDarkMode_HandleDialogMessage

Parameters

hwndDlg

The dialog or window receiving the message.

msg, wParam, lParam

The message and its parameters as received by the dialog procedure or window procedure.

pResult

Pointer to an INT_PTR that receives the dialog-proc / window-proc return value when the function returns TRUE. Must not be NULL.

Return Value

TRUE if the message was handled by the helper. The caller must return *pResult from its dialog or window procedure (cast to LRESULT when called from a window proc).

FALSE if the message was not handled. The caller continues with its own message routing.

Comments

HandleDialogMessage handles five categories of message:

MessageBehavior
WM_CTLCOLORDLGReturns the dark background brush so the dialog client area paints dark.
WM_CTLCOLORSTATIC, WM_CTLCOLOREDIT, WM_CTLCOLORBTN, WM_CTLCOLORLISTBOXSets dark text and background colors on the HDC and returns the dark brush so static labels, edits, buttons (group boxes) and listboxes paint with the dark palette.
WM_NOTIFY (NM_CUSTOMDRAW on a radio button)Repaints the radio button label in dark text. Standard radio buttons ignore SetTextColor when themed; the helper steals the CDDS_PREPAINT stage and draws the label itself with DrawText in SFTDARKMODE_TEXT_COLOR (or COLOR_GRAYTEXT for disabled), then returns CDRF_SKIPDEFAULT. The radio glyph itself is still drawn by the system.
WM_SETTINGCHANGE / ImmersiveColorSetRe-detects the current "Choose your mode" preference. If it changed, calls SftDarkMode_ApplyToWindow on the dialog and RefreshImmersiveColorPolicyState. Always re-applies themes to children via SftDarkMode_ApplyToChildren, invalidates the dialog, and forwards WM_SETTINGCHANGE to each direct child so they can re-render too. Accepts both LPCWSTR (Unicode procs) and LPCSTR (ANSI procs) forms of lParam.

All handlers are gated on the helper being in dark mode. In light mode HandleDialogMessage returns FALSE for every message and the dialog's default message routing applies.

Usage in plain Win32 dialogs

INT_PTR CALLBACK MyDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    INT_PTR dmResult;

    /* Application-specific handling first ... */

    if (SftDarkMode_HandleDialogMessage(hwndDlg, msg, wParam, lParam, &dmResult))
        return dmResult;

    return FALSE;
}

When sharing a dialog proc with other Softel vdm helpers (SftTabs page-host helpers, for example), HandleDialogMessage typically goes last - after SftTabs_HandleDialogMessage and SftTabs_TransparentControls but before the application's default-return path.

Usage in window procedures

The same helper works in non-dialog window procedures. The SftDarkMode_HandleWindowMessage alias makes the intent clearer in window-proc code:

LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    INT_PTR dmResult;
    if (SftDarkMode_HandleWindowMessage(hwnd, msg, wParam, lParam, &dmResult))
        return (LRESULT)dmResult;

    /* Application-specific handling ... */

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

MFC usage

For MFC applications using the SftTabs dialog / page classes, HandleDialogMessage is called automatically - CSftTabsDialog and CSftTabsPage (in SftTbM.h) route through it from their OnWndMsg when SftDarkMode.h is included before SftTb.h. Application code only has to:

  1. Include SftDarkMode.h in StdAfx.h, before SftTb.h.
  2. Add a DarkMode.cpp source file that defines SFTDARKMODE_IMPLEMENTATION before its #include "SftDarkMode.h".
  3. Call SftDarkMode_Init in InitInstance.
  4. Call SftDarkMode_ApplyToDialog in each OnInitDialog.

For MFC dialogs that do not derive from a SftTabs class, route HandleDialogMessage from the dialog's WindowProc or OnWndMsg override the same way the plain Win32 example does.

See Also Init | ApplyToDialog | IsActive | HandleMenuMessage


Last Updated 05/09/2026 - (email)
© 2026 Softel vdm, Inc.