Skip to content

PasswordBox

Header: winui/ui/text/PasswordBox.hpp. Spec: winui/ui/text/PasswordBox.hpp.

A single-line field that masks what is typed into it.

It owns a TextBox as its edit part, masked with password_char(). Caret, selection, clipboard and context menu work on the hidden text. A password offers no Cut or Copy, is never spell checked, and screen readers get only mask characters. In the default PasswordBoxRevealMode::Peek, a reveal button shows the password while it is held. The button shows only for a password typed since the field was last empty, so whoever sits down next can't peek at a password filled in earlier. In a spec tree it is built by ui::PasswordBox.

Example:

ui::Control<ui::PasswordBox> box;
window.set_content(ui::PasswordBox{
    .header           = "Password",
    .placeholder_text = "Enter your password",
    .max_length       = 64,
    .width            = 300.0f,
    .on_password_changed = [&box](const std::string& password) {
        if (password == "Password")
            box->set_password(""); // rejecting a value from inside the handler is fine
    },
    .control = box,
});

// Imperatively:
auto pin = std::make_unique<ui::PasswordBoxControl>();
pin->set_password_char(U'*');
pin->set_reveal_mode(ui::PasswordBoxRevealMode::Hidden);
pin->on_password_changed([](const std::string& p) { /* validate p */ });

ui::PasswordBox

A field for a password: the text is masked, and can be peeked at with the reveal button. Builds a ui::PasswordBoxControl.

Example:

void sign_in(const std::string& password); // the app's own
std::string secret;

window.set_content(ui::PasswordBox{
    .header              = "Password",
    .placeholder_text    = "Enter your password",
    .max_length          = 64,
    .width               = 240,
    .on_password_changed = [&](const std::string& p) { secret = p; },
    .on_submit           = [&] { sign_in(secret); },
});

Every field, in the order a designated initializer names them:

ui::PasswordBox{
    .header, .description, .error, .placeholder_text, .password, .max_length, .password_char,
    .reveal_mode, .style, .margin, .width, .height, .min_width, .min_height, .max_width,
    .max_height, .horizontal_alignment, .vertical_alignment, .visible, .tool_tip, .enabled,
    .accessibility, .on_password_changed, .on_submit, .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
header ui::Binding<std::string> The label above the control. Empty draws none.
description ui::Binding<std::string> Secondary text under the field, such as what to enter or why; empty draws none. Screen readers offer it as help text.
error ui::Binding<std::string> What is wrong with the value: non-empty shows it in the description's place in the critical color and draws the border in that color, and screen readers report the field invalid. The field shows exactly what it is given, so bind it to a check of the value and decide there when it shows (after the first submit, say).
placeholder_text ui::Binding<std::string> The hint shown while the password is empty.
password ui::TwoWayField<std::string> The password (UTF-8); drawn masked unless revealed.
max_length ui::Binding<std::size_t> {0} The most characters the user can type or paste; 0 is no limit.
password_char ui::Binding<char32_t> {U'\x25CF'} The code point drawn once per hidden character; U+25CF by default.
reveal_mode ui::Binding<ui::PasswordBoxRevealMode> {ui::PasswordBoxRevealMode::Peek} When the password can be revealed; Peek by default.
on_password_changed ui::Callback<void(const std::string&)> Fires after every change the user makes, with the new password.
on_submit ui::Action Fired on Enter. Without it Enter reaches the window's default button.
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::PasswordBox> 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

std::unique_ptr<Element> build()&&

Consumes the spec and returns the built ui::PasswordBoxControl; the caller owns it.

ui::PasswordBoxControl

Derives from ui::Element, ui::ValueProvider.

A single-line field that masks what is typed into it.

It owns a TextBox as its edit part, masked with password_char(). Caret, selection, clipboard and context menu work on the hidden text. A password offers no Cut or Copy, is never spell checked, and screen readers get only mask characters. In the default PasswordBoxRevealMode::Peek, a reveal button shows the password while it is held. The button shows only for a password typed since the field was last empty, so whoever sits down next can't peek at a password filled in earlier. In a spec tree it is built by ui::PasswordBox.

Example:

ui::Control<ui::PasswordBox> box;
window.set_content(ui::PasswordBox{
    .header           = "Password",
    .placeholder_text = "Enter your password",
    .max_length       = 64,
    .width            = 300.0f,
    .on_password_changed = [&box](const std::string& password) {
        if (password == "Password")
            box->set_password(""); // rejecting a value from inside the handler is fine
    },
    .control = box,
});

// Imperatively:
auto pin = std::make_unique<ui::PasswordBoxControl>();
pin->set_password_char(U'*');
pin->set_reveal_mode(ui::PasswordBoxRevealMode::Hidden);
pin->on_password_changed([](const std::string& p) { /* validate p */ });

PasswordBoxControl

PasswordBoxControl()

An empty, enabled box in Peek mode, masking with U+25CF.

~PasswordBoxControl

~PasswordBoxControl() override

password

const std::string& password() const

The password in clear text (UTF-8), whatever the reveal mode.

set_password

void set_password(std::string password)

Replaces the password. Does not fire on_password_changed(). An empty password hides the reveal button until something is typed again.

password_char

char32_t password_char() const

The code point drawn once per hidden character; U+25CF (a black circle) by default.

set_password_char

void set_password_char(char32_t mask)

Sets the mask character. The drawn mask and what screen readers get change at once.

reveal_mode

PasswordBoxRevealMode reveal_mode() const

When the password can be revealed; Peek by default.

set_reveal_mode

void set_reveal_mode(PasswordBoxRevealMode mode)

Sets when the password can be revealed. Switching to Visible shows the text at once, and switching away masks it again.

password_revealed

bool password_revealed() const

Whether the password shows right now: in Visible mode, or while the reveal button is held.

reveal_button_visible

bool reveal_button_visible() const

Whether the reveal button is shown.

reveal_button_rect

Rect reveal_button_rect() const

The reveal button's rectangle, a 30 DIP column at the field's right edge, in the same coordinates as bounds(). Meaningful only while reveal_button_visible().

const std::string& header() const

The label drawn above the field; empty (the default) draws none. Screen readers also use it as the name when none is set.

set_header

void set_header(std::string header)

Sets the header.

description

const std::string& description() const

The secondary text under the field; empty (the default) draws none. Screen readers also offer it as help text when no description is set.

set_description

void set_description(std::string description)

Sets the description. Empty draws none and takes no room.

error

const std::string& error() const

What is wrong with the value, shown in the description's place in the critical color, with the border in the same color; empty (the default) shows the description.

set_error

void set_error(std::string error)

Sets the error. Empty shows the description again.

automation_help_text_fallback

std::string automation_help_text_fallback() const override

The description, or the error while one is set, when accessibility().description is empty.

automation_invalid

bool automation_invalid() const override

Invalid while an error is set.

placeholder_text

const std::string& placeholder_text() const

The hint shown while the password is empty.

set_placeholder_text

void set_placeholder_text(std::string text)

Sets the hint shown while the password is empty.

max_length

std::size_t max_length() const

The character limit set by set_max_length(); 0 is no limit.

set_max_length

void set_max_length(std::size_t length)

The most characters the user can type or paste; 0 (the default) is no limit.

enabled

bool enabled() const

Whether the box accepts input and focus; true by default.

on_password_changed

void on_password_changed(Callback<void(const std::string&)> handler)

Fired after the user changes the password, with the new one.

on_submit

void on_submit(Callback<void()> handler)

Fired when the user presses Enter in the box. Without a handler Enter is left to the window, which clicks its default button.

focusable

bool focusable() const override

Focusable while enabled.

focused

bool focused() const

Whether the box currently has keyboard focus.

handle_context_menu

bool handle_context_menu(std::optional<Point> position, ContextMenuHost& host) override

Window::handle_context_menu() calls this on the focused element when the user right-clicks or presses Shift+F10/the Menu key, after focusing whatever focusable element sits under the pointer, as a pointer Down would. position is the right-click point (window-client DIPs), or nullopt for a keyboard request, where the element picks its own anchor (TextBox: its caret). host is only valid for this call, so show a menu through it here or not at all. Returns whether a menu was shown; default: none.

cursor_at

std::optional<CursorShape> cursor_at(Point p) const override

The text field's cursor over the text field: an I-beam, or an arrow over its buttons.

automation_role

AutomationRole automation_role() const override

Always AutomationRole::Edit.

automation_name_fallback

std::string automation_name_fallback() const override

The header, when no Accessibility::name is set.

caret_bounds

std::optional<Rect> caret_bounds() const override

The inner text box's caret.

build_visual_tree_override

void build_visual_tree_override(VisualTree& tree) const override

Adds the inner text box, which for_each_child() leaves out.

measure_override

Size measure_override(Size available, const MeasureContext& context) const override

Implement these instead of measure() and arrange(). The base class has already applied margin, size limits and alignment by the time these run. measure_override() is pure (every concrete Element must size itself); arrange_override() defaults to a no-op since most leaves need nothing beyond having bounds() set, which the base already did.

arrange_override

void arrange_override(const Rect& final_rect, const ArrangeContext& context) override

Position children within the rect arrange() settled on (also in bounds(), window DIPs). Default: nothing, for a leaf.

render_override

void render_override(Renderer& renderer, const RenderContext& context) const override

What the control draws, in layout coordinates; render() has already applied the visual layer. A container draws its children through their render(), never their render_override().

pointer_override

bool pointer_override(const PointerEvent& e) override

A pointer event for this element: the element under the pointer, one inside it that did not handle the event, or the element holding the capture. The position is in layout coordinates (handle_pointer()). Return true when the event did something here, and it goes no further up; a handled press also captures the pointer until its release. A control that acts on a press (a click, a toggle, a caret placed, a drag started) returns true for the press and its release, so a list row or a card around it does not act on the same click. Default: false.

hit_test_children

void hit_test_children(Point p, std::vector<Element*>& out) const override

The children p (in this element's layout coordinates) is tested against, topmost first. Default: what for_each_child() lists, last first. A container that draws in another order (Panel's z-index), a control with parts for_each_child() does not list, or one whose parts cover others in places (a pane drawn over the content) lists them here.

covers_children_at

bool covers_children_at(Point p) const override

Whether a part of this element drawn over its children is at p (a scroll bar over the content), so the element is hit there instead of a child. Default: false.

clear_dirty_override

void clear_dirty_override(DirtyFlags flags) override

This element's own part of clear_dirty(): clear any part it owns but leaves out of for_each_child() (a parked page, a hidden button), through that part's clear_dirty(). Default: nothing.

tick_override

void tick_override(Duration delta) override

This element's own part of tick(): a clock of its own (ToolTip's hover delay, an animation's phase, a caret blink). Runs after the visual layer has advanced and before the children are ticked, which tick() does by itself. Tick only parts that for_each_child() does not list here. Default: nothing.

enabled_changed

void enabled_changed() override

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

void focus_changed(bool focused) override

Gaining focus hides the reveal button until the field is cleared and typed into again.

key_override

bool key_override(const KeyEvent& e) override

Forwarded to the inner TextBox while focused. Enter is left to the window unless there is a submit handler.

text_override

bool text_override(const TextInputEvent& text_event) override

Forwarded to the inner TextBox while focused. Each edit fires on_password_changed().

draws_focus_ring

bool draws_focus_ring() const override

None: the field shows focus with its accent border.

Enumerations

PasswordBoxRevealMode

enum class PasswordBoxRevealMode

How a ui::PasswordBox shows its password.

Value
Peek Masked, with a reveal button that shows the password while held down (the default). The button appears only while the box is focused, for a password typed since the box was last empty.
Hidden Always masked; no reveal button.
Visible Always shown in clear text; no reveal button.

Tests

  • tests/test_password_box.cpp