HeaderPane
Main
Share Link
Print

SftDarkMode_HandleDialogMessage

Handle dark-mode-related dialog 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);

Parameters

hwndDlg

The dialog receiving the message.

msg, wParam, lParam

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

pResult

Pointer to an INT_PTR that receives the dialog-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 procedure.

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

Comments

HandleDialogMessage handles four 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.

The WM_CTLCOLOR* and WM_NOTIFY handlers act only while the helper is in dark mode. The WM_SETTINGCHANGE / ImmersiveColorSet handler runs in both modes, so the dialog follows the Windows setting in both directions; it returns FALSE so the dialog's own routing still sees the message. In light mode HandleDialogMessage returns FALSE for every message.

For a window procedure (returns LRESULT), use SftDarkMode_HandleWindowMessage instead.

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.

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 | HandleWindowMessage | HandleMenuMessage


Last Updated 10/11/2026 - (email)
© 2026 Softel vdm, Inc.