CheckBox¶
Header: winui/ui/input/CheckBox.hpp. Spec: winui/ui/input/CheckBox.hpp.
A box that is checked, unchecked or indeterminate, with an optional label to its right.
The value is a nullable bool: true, false, or std::nullopt for indeterminate. Compare it against a value instead of testing it for truth. if (box.checked()) asks whether the state is determinate and is true for an unchecked box, so write box.checked() == true. A click, Space (not Enter, which belongs to a dialog's default button) or UI Automation's Toggle advances the state; whether that can reach indeterminate is three_state().
Example:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
ui::CheckBoxControl* remember = stack->add(std::make_unique<ui::CheckBoxControl>("Remember me", /*checked=*/false));
ui::ButtonControl* sign_in = stack->add(std::make_unique<ui::ButtonControl>("Sign in"));
sign_in->set_enabled(false);
remember->on_checked_changed([sign_in](std::optional<bool> v) { sign_in->set_enabled(v == true); });
window.set_content(std::move(stack));
// Declaratively, bound both ways to a Property:
ui::Property<bool> remember_me{false};
window.set_content(ui::CheckBox{
.text = "Remember me",
.checked = remember_me,
.on_checked_changed = [&](std::optional<bool> v) { remember_me = v.value_or(false); },
});
ui::CheckBox¶
A checkbox with a trailing label. Builds a ui::CheckBoxControl. checked is nullable: std::nullopt is indeterminate, and a plain true or false converts to it, so .checked = true works. three_state lets a click reach indeterminate.
ui::bind() of a Property<std::optional<bool>> is two-way: a click writes the new state back before .on_checked_changed runs.
Example:
ui::Property<std::optional<bool>> agreed{false};
window.set_content(ui::VerticalStack{
.spacing = 8,
.content = {
ui::CheckBox{.text = "I agree", .checked = agreed},
ui::Button{.text = "Continue",
.enabled = ui::bind(agreed, [](std::optional<bool> on) { return on == true; })},
},
});
Every field, in the order a designated initializer names them:
ui::CheckBox{
.text, .checked, .three_state, .style, .margin, .width, .height, .min_width, .min_height,
.max_width, .max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip,
.enabled, .accessibility, .on_checked_changed, .on_pointer_entered, .on_pointer_exited,
.on_got_focus, .on_lost_focus, .on_key_down, .on_wheel, .control
}
Fields, in declaration order (designators must follow it):
| Field | Type | Default | |
|---|---|---|---|
text |
ui::Binding<std::string> |
The label right of the box. | |
checked |
ui::CheckedField |
{false} |
True, false, or std::nullopt for indeterminate. Seeding it raises nothing. Two-way with a Property<bool> (a click writes true or false; an indeterminate state set on the control writes nothing) or a Property<std::optional<bool>> (every state). See ui::CheckedField. |
three_state |
bool |
false |
A click also reaches indeterminate: unchecked, checked, indeterminate, unchecked. Without it, a click on an indeterminate box checks it. Needs checked bound to a Property<std::optional<bool>> (or one-way), since a Property<bool> cannot hold the third state; a debug build asserts on that. Read once, when the spec is built. |
on_checked_changed |
ui::Callback<void(std::optional<bool>)> |
The new state, after a click, the keyboard or a bound value changed it. | |
on_pointer_entered |
ui::Action |
The pointer moved onto the control. | |
on_pointer_exited |
ui::Action |
The pointer left the control. | |
on_got_focus |
ui::Action |
Keyboard focus arrived on the control, or on anything inside it, from outside it. A control with nothing focusable in it never gets focus, and never raises this. | |
on_lost_focus |
ui::Action |
Keyboard focus left the control and everything inside it. | |
on_key_down |
ui::Callback<ui::Handling(const ui::KeyEvent&)> |
A key pressed while focus is on the control or inside it, before the control's own handling; ui::Handled stops it there (Element::on_key_down()). | |
on_wheel |
ui::Callback<ui::Handling(const ui::PointerEvent&)> |
A wheel turn over the control, before the control scrolls; ui::Handled stops it there (Element::on_wheel()). | |
control |
ui::ControlOut<ui::CheckBox> |
Out: the handle that receives the built control. |
Plus the common fields style, margin, width, height, min_width, min_height, max_width, max_height, horizontal_alignment, vertical_alignment, visible, tool_tip, enabled, accessibility every spec carries (conventions).
build¶
Consumes the spec and returns the built ui::CheckBoxControl; the caller owns it.
ui::CheckBoxControl¶
Derives from ui::Element, ui::ToggleProvider.
A box that is checked, unchecked or indeterminate, with an optional label to its right.
The value is a nullable bool: true, false, or std::nullopt for indeterminate. Compare it against a value instead of testing it for truth. if (box.checked()) asks whether the state is determinate and is true for an unchecked box, so write box.checked() == true. A click, Space (not Enter, which belongs to a dialog's default button) or UI Automation's Toggle advances the state; whether that can reach indeterminate is three_state().
Example:
auto stack = std::make_unique<ui::StackControl>(ui::Orientation::Vertical);
ui::CheckBoxControl* remember = stack->add(std::make_unique<ui::CheckBoxControl>("Remember me", /*checked=*/false));
ui::ButtonControl* sign_in = stack->add(std::make_unique<ui::ButtonControl>("Sign in"));
sign_in->set_enabled(false);
remember->on_checked_changed([sign_in](std::optional<bool> v) { sign_in->set_enabled(v == true); });
window.set_content(std::move(stack));
// Declaratively, bound both ways to a Property:
ui::Property<bool> remember_me{false};
window.set_content(ui::CheckBox{
.text = "Remember me",
.checked = remember_me,
.on_checked_changed = [&](std::optional<bool> v) { remember_me = v.value_or(false); },
});
CheckBoxControl¶
An unlabeled, unchecked box.
CheckBoxControl¶
A box labeled text (UTF-8) in state checked (nullopt: indeterminate). Seeding the state raises nothing: no handler is attached yet.
text¶
The label right of the box (UTF-8); empty draws the box alone. Also the automation name fallback.
set_text¶
Sets the label (UTF-8). The box is measured again and redrawn.
checked¶
True, false, or nullopt for indeterminate; false by default. Compare against a value (== true) instead of testing the optional for truth.
set_checked¶
Sets the state, allowed to be indeterminate even when not three_state(). Fires on_checked_changed() when the value changes, and redraws.
three_state¶
Whether clicking (or Space, or UI Automation's Toggle) cycles through indeterminate: unchecked -> checked -> indeterminate -> unchecked. Off, the cycle is unchecked <-> checked, and an indeterminate box set in code clicks to unchecked. Off by default.
set_three_state¶
Affects only the next click; the current state is left as it is.
on_checked_changed¶
Invoked whenever checked changes (click, Space, or set_checked()), including into and out of indeterminate. Receives the new state. Replaces any previous handler.
parallel_measure_safe¶
True: measuring reads only the box's own state, the measurer and the theme.
focused¶
Whether the box holds keyboard focus.
focusable¶
A disabled box is skipped in the tab order.
is_pressed¶
True while pressed by the pointer or a held Space.
automation_role¶
Always AutomationRole::CheckBox.
automation_name_fallback¶
text(), used when Accessibility::name is not set.
visual_state¶
Disabled, Pressed, Hover or Normal, from the enabled flag and the pointer/key input.
measure_override¶
The box plus, when there is a label, the gap and the label's measured text.
pointer_override¶
A press and release inside the control (box or label) toggles it.
render_override¶
Draws the box (with its check or indeterminate dash), the label and the focus ring.
tick_override¶
In themes that animate the mark (the Fluent eras), draws the tick in (about 317 ms) when checked and erases it (67 ms) when cleared. The box's colors change at once and an indeterminate dash appears without animation. Until the box gets its first animation frame, and with animations off, the mark appears at once.
enabled_changed¶
is_enabled() flipped, through set_enabled() here or on an ancestor, or a move to another parent. Drop any press or hover state. The element is redrawn either way. No-op by default.
focus_changed¶
Called by Window. Losing focus cancels a Space press in progress. Redraws.
key_override¶
Space down presses, Space up toggles. Enter is not handled.
focus_ring_rect¶
Around box and label in the Fluent eras, the label (or the box without one) in the classic ones, the box in Metro's.
focus_ring_corner_radius¶
The ring's corner radius: the theme's control radius by default.
Tests¶
tests/test_check_box.cpp