# SftDarkMode — API Reference > Complete A-Z reference for SftDarkMode. The guide and feature documentation is in https://softelvdm.com/Vault/Softelvdm.com/llms/SftDarkMode.txt Online documentation: https://softelvdm.com/Documentation/SftDarkMode ## SftDarkMode_ApplyToChildren *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytochildren* Apply [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) theming to every direct child of a window or dialog. Iterates the children and calls [SftDarkMode_ApplyToControl](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytocontrol) on each. C ``` void SftDarkMode_ApplyToChildren(HWND hwndParent); ``` ### Parameters hwndParent The dialog or window whose direct children should be themed. ### Comments ApplyToChildren walks *GetWindow(hwndParent, GW_CHILD)* and the *GW_HWNDNEXT* chain, calling SftDarkMode_ApplyToControl on each. It **does not recurse** into grandchildren - controls that own internal children (combo boxes, custom composite controls) need their own dedicated handling. For combo boxes specifically, [SftDarkMode_ApplyToComboBox](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytocombobox) themes the combo box and its internal children in one call. ApplyToChildren is called automatically by [SftDarkMode_ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog) and by the *WM_SETTINGCHANGE* handler inside [SftDarkMode_HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) when the user toggles the Windows mode at runtime. Most applications never need to call it directly. See Also ApplyToControl | ApplyToDialog | ApplyToComboBox ## SftDarkMode_ApplyToComboBox *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytocombobox* Apply [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) to a combo box and its internal child controls. Use after creating a combo box dynamically (or any time the combo box was not themed by an enclosing [SftDarkMode_ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog) call). C ``` void SftDarkMode_ApplyToComboBox(HWND hwndCombo); ``` ### Parameters hwndCombo The combo box window handle. ### Comments A standard Win32 combo box is a parent window with internal child controls (the edit field for editable combos, the dropdown button, the listbox). Theming only the combo's HWND leaves the children unstyled. ApplyToComboBox sets the *DarkMode_CFD* theme class on the combo itself, then calls [SftDarkMode_ApplyToChildren](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytochildren) so the internal children pick up dark theming as well. The function is a no-op when the helper is not in dark mode - the combo retains its default light styling. For combo boxes placed via dialog template, SftDarkMode_ApplyToDialog routes through [SftDarkMode_ApplyToControl](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytocontrol), which already applies *DarkMode_CFD* to top-level combo controls. ApplyToComboBox is needed only when the combo is created dynamically or when its internal layout has been re-built and the children need re-theming. See Also ApplyToControl | ApplyToChildren | ApplyToDialog ## SftDarkMode_ApplyToControl *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytocontrol* Apply [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) theming to a single control. Picks the correct theme class for the control's window class and arms the per-window opt-in needed for dark NC scrollbars on edit / list controls. C ``` void SftDarkMode_ApplyToControl(HWND hwnd); ``` ### Parameters hwnd The control to apply dark mode to. ### Comments ApplyToControl reads the control's window class and selects an appropriate theme class: | Window class | Theme applied | | --- | --- | | ComboBox | DarkMode_CFD | | Edit | DarkMode_CFD | | SysListView32 | DarkMode_ItemsView | | Button (group box) | Theme stripped (so *WM_CTLCOLORSTATIC* can recolor the label) | | Anything else | DarkMode_Explorer | For each, the helper calls *AllowDarkModeForWindow*, *SetWindowTheme*, and sends *WM_THEMECHANGED* so comctl32 reopens its theme handle. *Group boxes* are a special case: they ignore *SetTextColor* when themed. ApplyToControl strips the theme on group boxes (so the label can be repainted dark by *WM_CTLCOLORSTATIC*). The *WM_CTLCOLORSTATIC* hook in [SftDarkMode_HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) provides the dark text color and brush. *Edit and list NC scrollbars* require both AllowDarkModeForWindow and an IAT hook in comctl32 - the hook is installed by [SftDarkMode_Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init), and ApplyToControl arms its per-window opt-in via *SetWindowTheme*. Bare *SetWindowTheme* alone does not produce dark scrollbars on standard controls. ApplyToControl is normally called automatically by [SftDarkMode_ApplyToChildren](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytochildren) or [SftDarkMode_ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog). Call it directly only for controls created or shown after the parent dialog has already been themed. See Also ApplyToChildren | ApplyToDialog | [ApplyToComboBox](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytocombobox) ## SftDarkMode_ApplyToDialog *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog* Apply [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) to a dialog and all of its children in one call. The recommended one-shot helper to invoke from *WM_INITDIALOG* (plain Win32) or *OnInitDialog* (MFC). C ``` void SftDarkMode_ApplyToDialog(HWND hwndDlg); ``` ### Parameters hwndDlg The dialog window handle. ### Comments ApplyToDialog performs four steps: 1. Sets (or clears) the *SftDarkModeScrollBar* window property on the dialog. The IAT hook installed by [SftDarkMode_Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init) checks this property to decide whether to redirect a scrollbar theme lookup to *Explorer::ScrollBar* (dark) or leave it at the default (light). Setting the property on the dialog opts every direct child in. 1. Calls [SftDarkMode_ApplyToWindow](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytowindow) on the dialog so the title bar and frame switch to the dark color. 1. Applies the *DarkMode_Explorer* theme class to the dialog itself (or strips the theme in light mode), then sends *WM_THEMECHANGED* so comctl32 reopens its scrollbar theme handle. This is needed for dialog hosts (CFormView, etc.) that own NC scrollbars - without it, the cached scrollbar theme handle persists until the window is destroyed. 1. Calls [SftDarkMode_ApplyToChildren](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytochildren) to theme every direct child, then redraws the entire NC tree with *RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN* so scrollbar bitmaps repaint at the new theme colors. Call ApplyToDialog from *WM_INITDIALOG* once. Re-call it after toggling the dark state through [SftDarkMode_SetActive](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_setactive) so the dialog and children re-theme to match. The *WM_SETTINGCHANGE* branch of [SftDarkMode_HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) re-applies dark mode automatically when the user flips the Windows setting - applications that route every dialog through HandleDialogMessage do not need to handle WM_SETTINGCHANGE themselves. ApplyToDialog is also the right call for an MFC *CFormView* or other non-modal form host: theming requires the same dialog property + theme + child sweep regardless of whether the parent is a *DIALOGEX* template or a CFormView with a dialog template. See Also ApplyToWindow | ApplyToChildren | HandleDialogMessage | Init ## SftDarkMode_ApplyToWindow *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytowindow* Apply [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) to a top-level window's non-client area. Sets the dark title bar through DWM and forces the system to recompute the NC area so the title bar repaints in the new color. C ``` void SftDarkMode_ApplyToWindow(HWND hwnd); ``` ### Parameters hwnd The top-level window to apply dark mode to. ### Comments ApplyToWindow handles the *window* aspect of dark mode - title bar color, frame, and the dark-mode opt-in. It does **not** touch the window's children. Use [SftDarkMode_ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog) for the typical dialog scenario where the dialog and every child should be themed in one call. The helper sets the *DWMWA_USE_IMMERSIVE_DARK_MODE* attribute through *DwmSetWindowAttribute* (using both attribute index 19 and 20 to cover Windows 10 1809-1903 builds), calls *AllowDarkModeForWindow* on the window, and forces an NC redraw via *SetWindowPos(... | SWP_FRAMECHANGED)*. On Windows builds that do not support the immersive dark mode attribute, DwmSetWindowAttribute returns an error which is ignored - ApplyToWindow has no visible effect on those platforms. See Also ApplyToDialog | [ApplyToControl](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytocontrol) | [ApplyToChildren](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytochildren) ## SftDarkMode_GetNaturalChildSize *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_getnaturalchildsize* Compute the natural content size of a form-style window by unioning the bounding rects of its direct children. Useful for computing scroll ranges in *CScrollView* or any host that needs to size itself to its template content. C ``` SIZE SftDarkMode_GetNaturalChildSize(HWND hwnd, int padRight, int padBottom); ``` ### Parameters hwnd The parent window whose direct children should be measured. padRight Right-edge padding to add to the union, in pixels. Pass 0 for no padding. The padding ensures the rightmost control is not flush against the parent's edge. padBottom Bottom-edge padding to add to the union, in pixels. Pass 0 for no padding. ### Return Value A SIZE whose *cx* / *cy* are the width and height of the union of every direct child's bounding rect, in *hwnd*'s client coordinates, plus the padding. Returns *{0, 0}* if *hwnd* is NULL or has no children. ### Comments Despite living in the [SftDarkMode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) header, this is a general-purpose layout helper - it is unrelated to dark mode and has no dependency on the rest of the helper. It is included here because the same dialog hosts that need the dark-mode helpers (*CFormView*, dialog templates rendered as scrolling forms) typically also need a natural-size computation after a PerMonitorV2 DPI change. Under PerMonitorV2 DPI awareness, Windows repositions the dialog-template children automatically when the host moves to a different-DPI monitor. After the repositioning, the union of the children's bounding rects is the new natural size at the new DPI, with no manual *MulDiv* required. Pass the result to *CScrollView::SetScrollSizes* (or equivalent) to update the scrollbar range. ``` // In OnSize / OnDpiChangedAfterParent: SIZE szContent = SftDarkMode_GetNaturalChildSize(m_hWnd, 16, 16); SetScrollSizes(MM_TEXT, szContent); ``` The function does not recurse - only direct children are considered. Composite controls that own internal children contribute their outer bounding rect, not their inner layout. See Also [ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog) ## SftDarkMode_HandleDialogMessage *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_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](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) 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 five categories of message: | Message | Behavior | | --- | --- | | WM_CTLCOLORDLG | Returns the dark background brush so the dialog client area paints dark. | | WM_CTLCOLORSTATIC, WM_CTLCOLOREDIT, WM_CTLCOLORBTN, WM_CTLCOLORLISTBOX | Sets 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](https://softelvdm.com/Documentation/SftDarkMode/Topic/def_sftdarkmode_colors) (or *COLOR_GRAYTEXT* for disabled), then returns *CDRF_SKIPDEFAULT*. The radio glyph itself is still drawn by the system. | | WM_SETTINGCHANGE / ImmersiveColorSet | Re-detects the current "Choose your mode" preference. If it changed, calls [SftDarkMode_ApplyToWindow](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytowindow) on the dialog and *RefreshImmersiveColorPolicyState*. Always re-applies themes to children via [SftDarkMode_ApplyToChildren](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_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. For a window procedure (returns *LRESULT*), use [SftDarkMode_HandleWindowMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_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. 1. Add a DarkMode.cpp source file that defines [SFTDARKMODE_IMPLEMENTATION](https://softelvdm.com/Documentation/SftDarkMode/Topic/def_sftdarkmode_implementation) before its *#include "SftDarkMode.h"*. 1. Call [SftDarkMode_Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init) in *InitInstance*. 1. Call [SftDarkMode_ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_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](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_isactive) | HandleWindowMessage | [HandleMenuMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handlemenumessage) ## SftDarkMode_HandleMenuMessage *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handlemenumessage* **Experimental.** Render a window's menu bar and menu items in dark colors using undocumented Windows messages. Call from the window procedure of any window that has a menu bar. C ``` BOOL SftDarkMode_HandleMenuMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* pResult); ``` ### Parameters hwnd The window receiving the message. msg, wParam, lParam The message and its parameters as received by the window procedure. pResult Pointer to an *LRESULT* that receives the 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 window procedure. FALSE if the message was not handled. The caller continues with its own message routing. ### Comments **This function uses undocumented Windows messages and may break with future Windows updates.** Use at your own risk - it is provided as an opt-in for applications that want a dark menu bar today and accept that the implementation is not part of the documented Win32 contract. The function is a no-op when the helper is not in [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) - the menu paints with the system default. HandleMenuMessage handles three message families: | Message | Behavior | | --- | --- | | WM_UAHDRAWMENU (0x0091) | Fills the menu bar background with the dark brush. | | WM_UAHDRAWMENUITEM (0x0092) | Draws each menu item with the dark palette - dark background, light text, hover / selected states use a slightly lighter background, disabled items use *COLOR_GRAYTEXT*. Honors *ODS_NOACCEL* for hidden underlines. | | WM_NCPAINT, WM_NCACTIVATE | Lets the default proc paint the NC area first, then overpaints the one-pixel border below the menu bar with the dark brush so it blends with the dark menu instead of showing a default-color seam. | ### Usage ``` LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT dmResult; /* Optional: dark menu bar (experimental) */ if (SftDarkMode_HandleMenuMessage(hwnd, msg, wParam, lParam, &dmResult)) return dmResult; /* Standard dark mode handling */ if (SftDarkMode_HandleWindowMessage(hwnd, msg, wParam, lParam, &dmResult)) return dmResult; return DefWindowProc(hwnd, msg, wParam, lParam); } ``` Most applications do not need a dark menu bar - dialog-only applications have no menu, and many MFC applications use a docked toolbar / ribbon rather than a top-level menu. HandleMenuMessage is intended for the small number of legacy SDI / MDI applications where a dark menu bar matters. The function relies on the undocumented *WM_UAHDRAWMENU* / *WM_UAHDRAWMENUITEM* messages that Windows sends to the window proc when *AllowDarkModeForWindow* has been called - which [SftDarkMode_ApplyToWindow](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytowindow) (and therefore [SftDarkMode_ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog)) does. If those messages stop being sent in a future Windows build, HandleMenuMessage stops doing anything but remains safely callable. See Also [HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) | ApplyToWindow ## SftDarkMode_HandleWindowMessage *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handlewindowmessage* Handle dark-mode-related window messages. Identical behavior to [SftDarkMode_HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage); the result is written through an *LRESULT** (the return type of a window procedure) instead of *INT_PTR** (the dialog procedure return type). C ``` BOOL SftDarkMode_HandleWindowMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* pResult); ``` ### Parameters hwnd The window receiving the message. msg, wParam, lParam The message and its parameters as received by the window procedure. pResult Pointer to an *LRESULT* that receives the 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 window procedure. FALSE if the message was not handled. The caller continues with its own message routing. ### Comments See SftDarkMode_HandleDialogMessage for the full list of messages handled and their behavior. HandleWindowMessage is the window-proc form of the same helper. ### Usage in window procedures ``` LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT dmResult; if (SftDarkMode_HandleWindowMessage(hwnd, msg, wParam, lParam, &dmResult)) return dmResult; /* Application-specific handling ... */ return DefWindowProc(hwnd, msg, wParam, lParam); } ``` ### MFC frame and view windows For MFC classes that override *WindowProc* (*CFrameWnd*, *CMDIFrameWnd*, *CView* subclasses), call HandleWindowMessage from the override. If you also call [SftDarkMode_HandleMenuMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handlemenumessage) from the same WindowProc, both helpers can share an *LRESULT* local because both take *LRESULT**. ``` LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { LRESULT dmResult; if (SftDarkMode_HandleMenuMessage(m_hWnd, message, wParam, lParam, &dmResult)) return dmResult; if (SftDarkMode_HandleWindowMessage(m_hWnd, message, wParam, lParam, &dmResult)) return dmResult; return CFrameWnd::WindowProc(message, wParam, lParam); } ``` See Also [Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init) | [ApplyToWindow](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytowindow) | [IsActive](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_isactive) | HandleDialogMessage | HandleMenuMessage ## SftDarkMode_Init *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init* Initialize the dark-mode helper. Detects the current "Choose your mode" preference, resolves the undocumented uxtheme.dll dark-mode entry points, hooks comctl32's delay-load import of *OpenNcThemeData* so dark NC scrollbars work on standard controls, and creates the shared dark background brush. C ``` void SftDarkMode_Init(void); ``` ### Parameters None. ### Comments Call **exactly once** at application startup, before any window is created. Typical call sites: - Plain Win32: from *WinMain*, before the first *DialogBox* / *CreateWindow* / *DialogBoxIndirect* call. - MFC: from *CWinApp::InitInstance*, before the first dialog is constructed. Calling Init multiple times is harmless but wasteful - the second and later calls reload uxtheme.dll, re-resolve the same ordinal exports, and recreate the dark brush. Pair with no explicit shutdown - the helper does not allocate per-process resources that need releasing on exit. Init is what makes the rest of the [SftDarkMode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) API actually do anything. Without it, [SftDarkMode_IsActive](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_isactive) returns FALSE, the [ApplyTo*](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog) functions silently no-op, and [SftDarkMode_HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) returns FALSE for every message. Note: the implementation must be compiled into the application by defining [SFTDARKMODE_IMPLEMENTATION](https://softelvdm.com/Documentation/SftDarkMode/Topic/def_sftdarkmode_implementation) in exactly one source file before including *SftDarkMode.h*. Without that define the linker will fail with an unresolved symbol on *SftDarkMode_Init*. See Also IsActive | [SetActive](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_setactive) | ApplyToDialog | HandleDialogMessage ## SftDarkMode_IsActive *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_isactive* Return TRUE if [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) is currently active. C ``` BOOL SftDarkMode_IsActive(void); ``` ### Parameters None. ### Return Value TRUE if dark mode is currently in effect, FALSE otherwise. ### Comments The returned value reflects the **cached** dark-mode state established at [SftDarkMode_Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init) time and updated automatically by [SftDarkMode_HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) when *WM_SETTINGCHANGE / ImmersiveColorSet* is delivered to a dialog or window that routes through the helper. Use IsActive to drive application-side rendering decisions - choosing icon variants, picking GDI brush handles, deciding which color overrides to push into Softel vdm controls' SFT*_CONTROL structures, and so on. The state can also be overridden programmatically through [SftDarkMode_SetActive](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_setactive). After SetActive, IsActive returns the override value rather than the system setting. See Also Init | SetActive ## SftDarkMode_SetActive *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/function_setactive* Override the dark / light state programmatically. Use to add a Light / Dark toggle to an application that does not want to follow the Windows "Choose your mode" setting. C ``` void SftDarkMode_SetActive(BOOL fDark); ``` ### Parameters fDark TRUE to set [dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) active, FALSE to set light mode. ### Comments SetActive only updates the cached state read by [SftDarkMode_IsActive](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_isactive) and used by the [ApplyTo*](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog) and [HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) functions. It does **not** re-theme already-shown dialogs or controls - the application must call SftDarkMode_ApplyToDialog on every visible dialog after toggling the state. If the application also forwards Windows *WM_SETTINGCHANGE / ImmersiveColorSet* through SftDarkMode_HandleDialogMessage, the cached state is overwritten by whatever the user selects in Windows Settings. Applications that expose their own toggle should typically choose one model: either follow Windows, or override. Per-Softel-vdm-control note: SetActive sets the global helper state. To make a Softel vdm control mirror the global state, set its own *nDarkMode* to AUTO (so it follows Windows) or call its *SetDarkMode* method explicitly with ON / OFF when the toggle changes. See Also [Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init) | IsActive | ApplyToDialog ## SFTDARKMODE Color Constants *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/def_sftdarkmode_colors* *Also listed as: SFTDARKMODE_BG_COLOR, SFTDARKMODE_BTNFACE_COLOR, SFTDARKMODE_HOT_COLOR, SFTDARKMODE_PRESSED_COLOR, SFTDARKMODE_TEXT_COLOR* Five RGB color constants that define the [SftDarkMode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) palette. The helper uses them when painting the dark dialog background, *WM_CTLCOLOR** surfaces, the experimental dark menu bar, and the dark text color used for radio-button labels. Applications can read the same constants when painting their own surfaces against a dark dialog so the colors match the helper's palette exactly. ``` #define SFTDARKMODE_BG_COLOR RGB(32, 32, 32) #define SFTDARKMODE_TEXT_COLOR RGB(230, 230, 230) #define SFTDARKMODE_BTNFACE_COLOR RGB(45, 45, 45) #define SFTDARKMODE_HOT_COLOR RGB(55, 55, 55) #define SFTDARKMODE_PRESSED_COLOR RGB(32, 32, 32) ``` | Constant | Value | Purpose | | --- | --- | --- | | SFTDARKMODE_BG_COLOR | RGB(32, 32, 32) | Dark background fill. Used for the dialog client area, the brush returned from *WM_CTLCOLOR** handlers, and the menu-bar background in the experimental [HandleMenuMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handlemenumessage). | | SFTDARKMODE_TEXT_COLOR | RGB(230, 230, 230) | Dark-mode text color - applied to *WM_CTLCOLOR** HDCs, repainted radio-button labels, and dark-menu items. | | SFTDARKMODE_BTNFACE_COLOR | RGB(45, 45, 45) | Dark button-face / panel color, slightly lighter than the dialog background. Provided for application use; the helper does not paint with it directly. Suitable for distinguishing a panel inset from the dialog background. | | SFTDARKMODE_HOT_COLOR | RGB(55, 55, 55) | Dark "hot" / hover background. Provided for application use; the helper does not paint with it directly. | | SFTDARKMODE_PRESSED_COLOR | RGB(32, 32, 32) | Dark pressed-state background. Equal to *SFTDARKMODE_BG_COLOR* so a pressed button visually merges with the dialog. Provided for application use; the helper does not paint with it directly. | The constants are plain *#define* macros that expand to *RGB(...)*. They are visible to both C and C++ code, and to resource scripts after including SftDarkMode.h. Note: BG and PRESSED are intentionally identical. The pressed-state value exists as a separate constant so application code that wants to special-case pressed rendering can rebind it without changing the dialog background. See Also SftDarkMode | [HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) | HandleMenuMessage ## SFTDARKMODE_IMPLEMENTATION *Source: https://softelvdm.com/Documentation/SftDarkMode/Topic/def_sftdarkmode_implementation* [SftDarkMode.h](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) is a single-header library in the *stb-style*: the header always exposes the function declarations, but the implementation is compiled only when **SFTDARKMODE_IMPLEMENTATION** is defined before the include. ``` // In one .c / .cpp file (e.g. DarkMode.cpp): #define SFTDARKMODE_IMPLEMENTATION #include "SftDarkMode.h" // Everywhere else that needs the declarations: #include "SftDarkMode.h" ``` Define *SFTDARKMODE_IMPLEMENTATION* in **exactly one** source file per executable - typically a small dedicated translation unit such as *DarkMode.cpp*. The implementation defines the *SftDarkMode_** functions; without the define, the linker fails with unresolved external symbols when the application calls [SftDarkMode_Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init) or any other helper. Defining the macro in more than one source file produces multiple-definition linker errors for the same set of functions. Defining it in zero source files leaves the helper undefined. The pattern lets SftDarkMode.h ship as a single header that drops into any project without requiring a separate .c / .cpp source addition - the application creates its own implementation file when (and only when) it wants the dark-mode helper compiled in. MFC note: the dedicated implementation file is the natural place to put any application-level dark-mode setup. The MFC sample applications include a minimal *DarkMode.cpp* that contains nothing but the *#define + #include* pair. See Also SftDarkMode | Init