ui¶
Namespace-scope declarations of ui from the themes headers.
Enumerations¶
ButtonState¶
Header: winui/ui/themes/Theme.hpp.
The interaction state a control derives from its input flags. Focus is not one of them. The focus visual is a separate ring a control draws on top of whichever of these four states it is in, so a focused and hovered control keeps its hover look.
| Value | |
|---|---|
Normal |
At rest. |
Hover |
The pointer is over the control. |
Pressed |
Held down by the pointer or the keyboard. |
Disabled |
The control is disabled; wins over the other three. |
CornerPreference¶
Header: winui/ui/themes/Theme.hpp.
How the corners of the system-drawn window frame are rounded. An era theme sets this so the frame matches the content, so a Windows 95 theme asks for square corners. Windows 11 only.
| Value | |
|---|---|
Default |
The system decides: round on Windows 11. |
DoNotRound |
Square corners. |
Round |
The standard window radius. |
RoundSmall |
The smaller menu and flyout radius. |
FrameColorKind¶
Header: winui/ui/themes/Theme.hpp.
Which of the four answers a FrameColor holds.
| Value | |
|---|---|
Follow |
No opinion; the next layer decides (see follow()). |
SystemDefault |
The system's own color. |
None |
Draw nothing. For the border only. |
Custom |
The color in operator*(). |
ThemeDividerVisual¶
Header: winui/ui/themes/Theme.hpp.
How dividers and separators are drawn, Toolbar's separators included: the classic two-line etched groove from surfaces.separator_light and separator_dark, the default, or Fluent's flat single line in colors.divider. Only Theme::fluent() picks the flat line. Every other theme keeps the groove.
| Value | |
|---|---|
EtchedGroove |
Two 1px lines, surfaces.separator_light / separator_dark. |
FlatStroke |
One 1px line in colors.divider. |
ThemeDisclosureVisual¶
Header: winui/ui/themes/Theme.hpp.
How a control marks that something opens, drops down or expands: Expander, TreeView, NavigationShell, Breadcrumb, DropdownButton, SplitButton, NumberBox's spin buttons and a menu's submenu arrow. Fluent and every theme after Windows 2000 draw the icon font's chevrons. The classic themes draw solid arrows and plus/minus boxes.
| Value | |
|---|---|
IconChevron |
The icon font's line chevrons (glyphs::ChevronDown and the rest). |
ClassicArrow |
The classic solid arrows, 7 x 4 at 96 DPI (draw_classic_arrow()), as on scroll bars and submenus, and a tree view's 9 x 9 plus/minus box (draw_classic_tree_button()). |
ThemePopupShadow¶
Header: winui/ui/themes/Theme.hpp.
Which drop shadow an open popup casts (render/OverlayShadow.hpp). Fluent's two-light shadow follows from an elevation scale, where every kind of surface has a height. Aero casts no shadow under a button, card or panel. Its only shadow is an offset block with a 5 px fall-off under a menu, tooltip or drop-down. Defaults to the Fluent shadow.
| Value | |
|---|---|
FluentTwoLight |
Fluent's soft two-light elevation shadow. |
AeroDropShadow |
An offset block with a 5 px fall-off, as Luna and Aero draw it. |
None |
No shadow at all. Menus, drop-downs and dialogs are plain rectangles on the surface below them. |
ThemePopupAnimation¶
Header: winui/ui/themes/Theme.hpp.
How a menu (MenuFlyout, the menu bar's menus, a context menu) and a drop-down list (ComboBox) come into view. Every era animates these differently: - Fluent 2, Fluent, MDL2 and Metro (the defaults): a menu slides out from its own edge over 250 ms and fades out over 83 ms. A drop-down list appears at once. - Aero and Luna follow the system's animation settings. A menu fades in when menu fading is on, slides in when it is off, and does neither when menu animation is off. A drop-down list slides open when list box animation is on. Both run 200 ms, and a menu closes at once. resolve_theme() reads the settings from OsThemeSnapshot. - Windows 9x, 3.x and 1.x/2.x: no animation.
| Value | |
|---|---|
Slide |
Slides out from its own edge. |
Fade |
Fades in. |
None |
Appears at once. |
ThemeVariant¶
Header: winui/ui/themes/Theme.hpp.
The design language (era) the whole UI is drawn in, chosen independently of the Windows version the app runs on. ThemeVariant::System, the default, draws the look of the running Windows: Fluent 2 on Windows 11 and Fluent before it. Fluent2 is the primary target.
System, Fluent2 and Fluent are always available. The era themes (Mdl2 to Windows1x) are linked into an app only once it calls enable_era_themes(). Before that, asking for one draws the System look.
Dark and light are not variants. They are set by ThemeMode, which by default follows the system. Fluent2, Fluent, Metro and Mdl2 have a dark and a light palette and honor ThemeMode and ThemeRequest::accent_override. Every other variant has one fixed, light palette and ignores both (theme_variant_supports_dark_mode()).
Under high contrast every variant draws its own era's high-contrast look. Windows 9x, 3.x and 1.x take the contrast colors as one more color scheme, Luna and Aero fall back to the Classic look as XP and 7 did, and Metro, MDL2 and Fluent keep their shapes in contrast colors. The colors are the system's contrast theme while one is on, and the era's own contrast scheme when an app forces ThemeMode::HighContrast without one.
Example:
int run_retro()
{
ui::Window retro{{
.title = "Retro",
.theme = ui::ThemeRequest{.variant = ui::ThemeVariant::Windows9x}, // light-only, ignores ThemeMode
}};
return ui::run(retro);
}
| Value | |
|---|---|
System |
The look of the running Windows: Fluent2 on Windows 11 and Fluent on Windows 10 and earlier (OsThemeSnapshot::system_variant). The default. A resolved Theme never reports it. Its Theme::variant is the variant System stood for. |
Fluent2 |
Fluent 2, Windows 11's design, whatever Windows the app runs on. The primary target, with resolve_high_contrast() under high contrast. |
Fluent |
Fluent 1: the original Fluent Design System as it shipped on Windows 10, from 1709 (2017) through early 2021. Follows dark and light mode and the accent, like Fluent2. Windows 11 is Fluent2. See resolve_fluent1() for what this variant changes. |
Mdl2 |
MDL2 ("Microsoft Design Language 2"): Windows 10's original flat, square look with the accent as its only color, as it shipped from 1507 (2015-07-29) through 1703 (2017-04-11), before Fluent. No material, no elevation, and no rounded corners except the Slider thumb and the ToggleSwitch track. Follows dark and light mode and the accent, like Fluent2, Fluent and Metro. Its colors come from the 24 base colors of an Mdl2Palette, in a light and a dark set. The name is a press convention. No Microsoft document of the era uses it. |
Metro |
MDL ("Metro Design Language"): Windows 8 and 8.1 merged into one entry. It follows Windows 8.1, with its dark mode and user accent. |
Aero |
Aero: Windows Vista and 7 merged into one entry, defaulting to Windows 7's column. The two releases barely differ. The only change a control shows is disabled text, which went from #808080 to #6D6D6D. Aero has no control accent, since the user's glass color tinted the frame, taskbar and Start menu but never a control. This variant ignores both ThemeMode's light and dark and ThemeRequest::accent_override. |
Luna |
Luna: Windows XP's default visual style. |
Windows9x |
Windows 9x: Windows 95, 98, and 2000 merged into one entry. Defaults to the Windows 95 and 98 "Windows Standard" scheme (ClassicPalette::windows_standard()). ThemeRequest::classic_scheme swaps in any other ClassicPalette, such as ClassicPalette::windows_standard_2000(). |
Windows3x |
Windows 3.x: before hot tracking, Active Desktop and the four-color bevel of Windows 95. |
Windows1x |
Early Windows: Windows 1.01 (1985-11) through 2.11 (1989-03), the design language Windows 3.0 replaced in May 1990. It has no sense of depth at all: no bevel, no gray #C0C0C0 face, no light source, no highlight and shadow pair and no drop shadow. All of its chrome is black and white, and the only depth cue is a one-pixel frame line. It has ten colors, thirteen from 2.0, with no button face, selection or disabled-text color among them. That is why its colors are an EarlyPalette instead of a ClassicPalette, and its theme comes from Theme::early() instead of Theme::classic(). What sets "Windows 1" apart from "Windows 2" happens at 2.03 in December 1987, when windows stopped being tiled. This one variant covers both and defaults to the Windows 2.03 color palette. EarlyPalette::windows_1x_mono() and the other two palettes are one ThemeRequest::early_scheme away. The four palettes are separate looks, so pick a version first, then a display type, and do not mix them. |
ThemeMode¶
Header: winui/ui/themes/ThemeSource.hpp.
Which light, dark or contrast appearance a ThemeRequest asks for.
Only the variants for which theme_variant_supports_dark_mode() is true tell Light and Dark apart. HighContrast applies to every variant.
| Value | |
|---|---|
System |
Follow the system's light or dark setting as it changes (the default). |
Light |
Always light, whatever the system setting. |
Dark |
Always dark, whatever the system setting. |
HighContrast |
The system's contrast theme while one is on, otherwise the variant's own contrast colors (see resolve_theme()). |
AnimationPreference¶
Header: winui/ui/themes/ThemeSource.hpp.
Whether controls animate: follow the system's "Animation effects" setting, or force it either way.
With animations off, every transition the framework plays itself lands on its end state at once: control state tweens, transitions, implicit and brush transitions, popup motion, animated icons, animated scrolling and connected animations. Timers that are not animations (tooltip delay, caret blink, key repeat) keep running, and an indeterminate ProgressBar or ProgressRing keeps moving, since that motion is what tells the user work is going on.
Example:
// A "Reduce motion" switch in an app's settings page:
void set_reduce_motion(bool reduce_motion)
{
ui::ThemeRequest request = window.theme_request();
request.animations = reduce_motion ? ui::AnimationPreference::Off : ui::AnimationPreference::System;
window.set_theme(request);
}
| Value | |
|---|---|
System |
Follow OsThemeSnapshot::animations_enabled as it changes (the default). |
On |
Always animate, whatever the system setting. |
Off |
Never animate, whatever the system setting. |
Functions¶
classic_lighter¶
Header: winui/ui/themes/ClassicPalette.hpp.
Lightens c the way the classic 3-D ramp is derived from a face color. The color's luminosity moves toward white by up to half the remaining distance, and percent, clamped to [0,1], scales that move. Hue, saturation and alpha are kept.
Example:
const ui::Color face = ui::Color::from_rgba(128, 64, 128); // a custom face
const ui::Color light = ui::classic_lighter(face, 0.5f); // the bevel's outer light ring
const ui::Color dark = ui::classic_darker(face, 1.0f); // the bevel's outer dark ring
classic_darker¶
Header: winui/ui/themes/ClassicPalette.hpp.
Darkens c the same way classic_lighter() lightens it. The luminosity moves toward black by up to a third, scaled by percent, which is clamped to [0,1]. Hue, saturation and alpha are kept.
classic_bevel_ramp_from_face¶
Header: winui/ui/themes/ClassicPalette.hpp.
Derives the whole classic 3-D ramp from one face color. light is classic_lighter(face, 0.5), highlight is classic_lighter(face, 1.0), shadow is classic_darker(face, 0.5) and dark_shadow is classic_darker(face, 1.0).
When face is exactly one of the two standard grays, the ramp that era ships is returned as is, because neither can be derived:
- 0xC0C0C0 (Windows 95 and 98 SE): 0xDFDFDF, white, 0x808080 and black. Its light ring sits between the face and the highlight.
- 0xD4D0C8 (Windows 2000, and XP's Classic scheme): the face itself, white, 0x808080 and 0x404040. The light ring equals the face, and the dark ring is softer than black.
Any other face color, as in a custom scheme, gets the computed ramp.
Example:
// In a custom control's render_override(): a raised teal panel. Teal is no canonical gray, so its
// ramp is computed, with `highlight` equal to classic_lighter(face, 1.0f).
class TealPanelControl : public ui::Element
{
protected:
void render_override(ui::Renderer& renderer, const ui::RenderContext&) const override
{
const ui::Color face = ui::Color::from_rgba(0, 128, 128);
const ui::ClassicBevelRamp ramp = ui::classic_bevel_ramp_from_face(face);
renderer.fill_rounded_rect(bounds(), 0.0f, face);
ui::draw_bevel_border(renderer, bounds(), ui::BorderStyle::Raised, ramp.light, ramp.highlight,
ramp.shadow, ramp.dark_shadow, 1.0f);
}
};
// Windows 2000's gray gets its published ramp instead: `#D4D0C8` (the face itself), white,
// `#808080` and `#404040`.
const ui::ClassicBevelRamp win2000 = ui::classic_bevel_ramp_from_face(ui::Color::from_argb(0xFFD4D0C8));
early_reverse_video¶
Header: winui/ui/themes/EarlyPalette.hpp.
Reverse video, the era's only way to show a selected state, which is why the palettes above have no selection color. A selected run swaps its foreground and background. Returns the swapped pair as {background, foreground}.
The swap keeps the palette's own colors. Inverting each pixel instead would turn the 2.03 color palette's cyan menu red. On monochrome palettes both give the same result.
Example:
const ui::EarlyPalette p = ui::EarlyPalette::windows_2x_color();
const ui::Rect item_rect = {0, 0, 80, 20};
const auto [fill, text] = ui::early_reverse_video(p.menu, p.menu_text); // a selected menu item
renderer.fill_rounded_rect(item_rect, 0.0f, fill);
renderer.draw_text("Open...", item_rect, text, theme.text_style);
early_dither_gray¶
Header: winui/ui/themes/EarlyPalette.hpp.
The era's gray as one flat color. The era has no disabled-text color and grays disabled items with a 50 % checkerboard of ink and paper. Renderer has no pattern fill, so this returns the checkerboard's average, the midpoint of the two colors. Black on white gives #808080, the gray the Windows 1.01 monochrome palette uses for the desktop and inactive captions.
Only the text grays out. A disabled push button keeps its frame, corners and border and grays its label.
Example:
const ui::EarlyPalette p = ui::EarlyPalette::windows_1x_mono();
const ui::Color gray = ui::early_dither_gray(p.window_text, p.window); // ~`#808080`
const ui::Rect label_rect = {0, 0, 80, 20};
const bool enabled = false;
renderer.draw_text("Cancel", label_rect, enabled ? p.window_text : gray, theme.text_style);
merge_chrome¶
Header: winui/ui/themes/Theme.hpp.
The frame settings a window applies: overrides layered over theme.
resolve_theme¶
Header: winui/ui/themes/ThemeSource.hpp.
Resolves an app's request against the system's settings into a Theme. High contrast, when it is on because the system reports it or the app asked for ThemeMode::HighContrast, wins over every other color input (mode, accent_override, classic_scheme, early_scheme), since apps don't keep their brand colors under high contrast. variant still picks the era the contrast colors are drawn in. The system's contrast theme (os.hc) is the user's choice and always supplies the colors. A forced high contrast with no contrast theme on takes the variant's own contrast colors: Aquatic for Fluent 2, Windows 10's High Contrast Black for Fluent, MDL2 and Metro, the XP and Windows 98 High Contrast Black schemes for Luna, Aero and Windows 9x, Windows 3.1's Monochrome scheme, and the matching monochrome palette for Early Windows.
Example:
ui::OsThemeSnapshot os;
os.dark = true;
// The app asks for light, so the system being dark doesn't change the result.
const ui::Theme theme = ui::resolve_theme(ui::ThemeRequest{.mode = ui::ThemeMode::Light}, os);
window.pin_theme(theme);
enable_era_themes¶
Header: winui/ui/themes/ThemeSource.hpp.
Links the era themes into the app, ThemeVariant::Mdl2 to ThemeVariant::Windows1x, with their window frames. Until it is called they are left out of the executable, and a ThemeRequest asking for one draws ThemeVariant::System instead. Call it once, before the first window. Calling it again does nothing.
Example:
int main()
{
ui::enable_era_themes();
ui::Window window{{.title = "Retro", .theme = ui::ThemeRequest{.variant = ui::ThemeVariant::Luna}}};
return ui::run(window);
}
era_themes_enabled¶
Header: winui/ui/themes/ThemeSource.hpp.
Whether enable_era_themes() was called, so the era variants draw as themselves.
theme_variant_supports_dark_mode¶
Header: winui/ui/themes/ThemeSource.hpp.
Whether variant tells ThemeRequest::mode's Dark and Light apart: true for System, Fluent2, Fluent, Metro and Mdl2. Every other variant has one fixed, light palette and looks the same whatever mode says, except ThemeMode::HighContrast, which still replaces its colors. A UI with a variant picker and a dark/light switch uses it to disable the switch when it would have no effect.
os_theme¶
Header: winui/ui/themes/ThemeSource.hpp.
What the operating system's theme is right now: light or dark, the accent color, high contrast. A window that follows the system already tracks this by itself; ask for it to pre-select a theme picker to match, or to resolve a theme before a window exists. A platform with no backend returns the defaults.
Example: