Skip to content

ui

Namespace-scope declarations of ui from the core headers.

Enumerations

Handling

enum class Handling : std::uint8_t

Header: winui/core/Callback.hpp.

What a handler asked to act returns: whether it dealt with the event, so it goes no further. Written as the constants ui::Handled and ui::NotHandled. A handler that returns nothing gets its event's default: handled where the handler is the target asked to act (a shortcut, a context-menu request), not handled where it watches events pass by (Window::on_key_preview).

Value
Handled Dealt with; the event goes no further.
NotHandled Not this handler's; the event goes on.

Decision

enum class Decision : std::uint8_t

Header: winui/core/Callback.hpp.

What a handler asked before something happens returns: let it go ahead, or stop it (a window closing, an edit starting or being committed, a sort). Written as the constants ui::Proceed and ui::Cancel. A handler that returns nothing lets it proceed.

Value
Proceed Go ahead.
Cancel Stop it; nothing changes.

DirtyFlags

enum class DirtyFlags : std::uint8_t

Header: winui/core/DirtyFlags.hpp.

Bitmask of what about an Element is out of date and must be redone at the next layout pass.

Setters mark flags on their element and the bits bubble to every ancestor, so a host can ask the root whether anything below it changed. On the element itself Measure and Arrange also say its own last measure or arrange is out of date. On an ancestor they only say something below needs it. Combine with |, test with & or any(), clear with &= ~flags. Read back through Element::is_dirty() / Element::dirty_flags(); Window::layout() clears them.

Example:

// In a custom control, each setter marks what its change invalidates.
class TagControl : public ui::Element
{
public:
    void set_label(std::string label)
    {
        if (label_ != label)
        {
            label_ = std::move(label);
            mark_dirty(ui::DirtyFlags::Layout | ui::DirtyFlags::Visual); // new size and new look
        }
    }

    void set_highlighted(bool highlighted)
    {
        if (highlighted_ != highlighted)
        {
            highlighted_ = highlighted;
            mark_dirty(ui::DirtyFlags::Visual); // same size and place, only a redraw
        }
    }

private:
    std::string label_;
    bool        highlighted_ = false;
};

// Outside the element: has anything below the panel changed size since the last layout pass?
bool needs_measure(const ui::Element& panel)
{
    return panel.is_dirty(ui::DirtyFlags::Measure); // measured again at the next layout
}

Value
None Up to date.
Measure The desired size must be recomputed, and so the arrangement too.
Visual Appearance changed (color, focus ring, scroll offset, ...); size and place unaffected.
Arrange The place of the element or its children changed, its desired size did not.
Layout Measure and arrange: what a size-affecting setter marks.
All Every flag; the default mask of the queries.

Orientation

enum class Orientation

Header: winui/core/Geometry.hpp.

The axis a control runs along: a stack's direction, a slider's track, a pager's row of pips.

Value
Horizontal left to right
Vertical top to bottom

CursorShape

enum class CursorShape

Header: winui/core/Input.hpp.

The system pointer shapes an element can ask for with Element::set_cursor(). Each shows the system cursor of the same name.

Example:

void set_cursors(ui::Element& splitter, ui::Element& link)
{
    splitter.set_cursor(ui::CursorShape::SizeWestEast);
    link.set_cursor(ui::CursorShape::Hand);
}

Value
Arrow The standard arrow; the default.
Cross Crosshair, for precise picking.
Hand Pointing hand, over hyperlinks.
Help Arrow with a question mark.
IBeam Text caret, over editable or selectable text.
SizeAll Four-way arrow, for moving.
SizeNortheastSouthwest Diagonal resize, / direction.
SizeNorthSouth Vertical resize.
SizeNorthwestSoutheast Diagonal resize, \ direction.
SizeWestEast Horizontal resize, e.g. a column splitter.
UniversalNo Slashed circle. The action is not allowed here.
UpArrow Vertical arrow.
Wait Busy. Input is blocked.
Pin Location pin.
Person Person.
AppStarting Arrow with a busy indicator. Input still works.

PointerButton

enum class PointerButton

Header: winui/core/Input.hpp.

Which mouse button a PointerEvent is about.

Value
None No button: moves, leaves and wheel turns.
Left The primary button (also a touch or pen contact).
Right The secondary button; context menus open on its Up.
Middle The wheel button.

PointerAction

enum class PointerAction

Header: winui/core/Input.hpp.

What happened in a PointerEvent.

Value
Move The pointer moved over the element (hover), with or without a button held.
Down button was pressed; see PointerEvent::click_count for double/triple clicks.
Up button was released.
Leave The pointer left the element (or the window); clears hover state.
Wheel A wheel turn; see PointerEvent::wheel_delta and horizontal_wheel.

PointerDeviceType

enum class PointerDeviceType : std::uint8_t

Header: winui/core/Input.hpp.

What kind of device a PointerEvent came from.

Value
Mouse A mouse or touchpad: the default, and what an event of unknown origin counts as.
Pen A pen or stylus, its tip or its eraser end.
Touch A finger on a touch screen.

PointerDeviceTypes

enum class PointerDeviceTypes : std::uint8_t

Header: winui/core/Input.hpp.

A set of pointer devices, for a control that takes input from some kinds of device only, such as ui::InkCanvasControl::set_input_device_types(). Flags.

Value
None No device.
Mouse The mouse and the touchpad.
Touch Touch screens.
Pen Pens, tip and eraser end alike.
All Every device.

Key

enum class Key

Header: winui/core/Input.hpp.

The keys a control or a shortcut reads: navigation and editing keys, letters, digits, function keys and the keypad operators. Any other key arrives as Unknown.

Example:

const ui::KeyCombo save = ui::Ctrl + ui::Key::S; // save.text() is "Ctrl+S"

// In an element of your own:
class FileListControl : public ui::Element
{
protected:
    bool key_override(const ui::KeyEvent& e) override
    {
        if (e.action == ui::KeyAction::Down && e.key == ui::Key::Delete)
        {
            remove_selected();
            return true;
        }
        return false;
    }

private:
    void remove_selected();
};

Value
Unknown A key outside this set; controls ignore it.
A Letter A; TextBox's Ctrl+A select-all.
B Letter B.
C Letter C; TextBox's Ctrl+C copy.
D Letter D.
E Letter E.
F Letter F.
G Letter G.
H Letter H.
I Letter I.
J Letter J.
K Letter K.
L Letter L.
M Letter M.
N Letter N.
O Letter O.
P Letter P.
Q Letter Q.
R Letter R.
S Letter S.
T Letter T.
U Letter U.
V Letter V; TextBox's Ctrl+V paste.
W Letter W.
X Letter X; TextBox's Ctrl+X cut.
Y Letter Y; StandardCommand::Redo's Ctrl+Y.
Z Letter Z; TextBox's Ctrl+Z, which also reverts an autocorrection.
Number0 Digit 0 on the main row.
Number1 Digit 1 on the main row.
Number2 Digit 2 on the main row.
Number3 Digit 3 on the main row.
Number4 Digit 4 on the main row.
Number5 Digit 5 on the main row.
Number6 Digit 6 on the main row.
Number7 Digit 7 on the main row.
Number8 Digit 8 on the main row.
Number9 Digit 9 on the main row.
F1 Function key F1.
F2 Function key F2.
F3 Function key F3.
F4 F4; opens and closes a ComboBox.
F5 Function key F5.
F6 Function key F6.
F7 Function key F7.
F8 Function key F8.
F9 Function key F9.
F10 Function key F10.
F11 F11; the usual full-screen toggle. No control reads it, an app does.
F12 Function key F12.
Enter Activates the focused button (on release); commits a NumberBox edit.
Space Activates the focused button or toggle (on release).
Tab Moves focus; Shift+Tab moves backwards.
Escape Closes the topmost popup, flyout or dialog; leaves a focus scope.
Backspace Deletes before the caret in TextBox and RichEditBox.
Delete Deletes after the caret; StandardCommand::Delete's shortcut.
Insert Insert.
Home Start of line / first item.
End End of line / last item.
PageUp A page up in a scroller; Carousel's previous item.
PageDown A page down in a scroller; Carousel's next item.
ArrowLeft Left arrow: moves the caret, a slider, or between tabs and items.
ArrowUp Up arrow: moves within lists, sliders, menus and text.
ArrowRight Right arrow.
ArrowDown Down arrow; Alt+Down opens a SplitButton's or ComboBox's drop-down.
Add The keypad's +.
Subtract The keypad's -.
Multiply The keypad's *.
Divide The keypad's /.
Plus The main keyboard's + key (with = on a US layout).
Minus The main keyboard's - key.
Comma The main keyboard's , key.
Period The main keyboard's . key.
Slash The key with / and ? on a US layout; other layouts put other characters there.

KeyAction

enum class KeyAction

Header: winui/core/Input.hpp.

Whether a KeyEvent is a press or a release.

Value
Down Pressed, or auto-repeated while held. Shortcuts and navigation fire on Down.
Up Released. Button activation by Enter/Space completes on Up.

RoundingAlgorithm

enum class RoundingAlgorithm

Header: winui/core/NumberFormat.hpp.

How IncrementNumberRounder picks between the two neighboring multiples of its increment.

Value
RoundDown toward negative infinity
RoundUp toward positive infinity
RoundTowardsZero truncate: -2.7 becomes -2
RoundAwayFromZero away from zero: -2.2 becomes -3
RoundHalfDown nearest; a tie toward negative infinity
RoundHalfUp nearest; a tie toward positive infinity
RoundHalfTowardsZero nearest; a tie toward zero
RoundHalfAwayFromZero nearest; a tie away from zero (school rounding)
RoundHalfToEven nearest; a tie to the even multiple (banker's rounding): 2.5 becomes 2
RoundHalfToOdd nearest; a tie to the odd multiple: 2.5 becomes 3

CollectionChangeKind

enum class CollectionChangeKind

Header: winui/core/ObservableVector.hpp.

What happened to a collection, as reported by ui::ObservableVector.

Value
Inserted count items were inserted at index.
Removed count items were removed, starting at index.
Replaced count items starting at index were replaced by new ones.
Moved The item at index moved to to; both are positions in the collection.
Reset Everything changed at once: the collection was cleared or assigned.

Aliases

Action

using ui::Action = Callback<void()>

Header: winui/core/Callback.hpp.

The most common shape, Callback<void()>, named because it reads better in a spec field: .on_click = [&] { save(); }.

Duration

using ui::Duration = std::chrono::duration<double, std::milli>

Header: winui/core/Duration.hpp.

A length of time: every delay, duration, interval and elapsed time in the API. Milliseconds with a fractional part, so std::chrono_literals write it (800ms, 0.3s, 2s) and a frame step of 16.7 ms keeps its fraction. A bare number does not convert, so a value always says its unit.

Example:

using namespace std::chrono_literals;

ui::Property<std::string> hint{"Saved"};
window.set_content(ui::ToolTip{
    .delay   = 400ms,
    .anchor  = ui::Button{ .text = "Refresh" },
    .content = ui::Text{ .text = "Reload the list" },
});
ui::Subscription hide_hint = window.after(2s, [&] { hint = ""; });

NativeHandle

using ui::NativeHandle = HWND__*

Header: winui/core/NativeHandle.hpp.

The operating system's own handle of a window or a hosted control, for the calls libwinui does not wrap. On Windows it is the same type as HWND, declared here without <windows.h>, so a real HWND passes in and out unchanged; elsewhere it is an opaque pointer. Null while the window does not exist.

Example:

if (const ui::NativeHandle hwnd = window.native_handle())
{
    FlashWindow(hwnd, TRUE); // any Win32 call libwinui doesn't wrap
}

ThreadCheckHandler

using ui::ThreadCheckHandler = void (*)(const ThreadCheckFailure&)

Header: winui/core/ThreadCheck.hpp.

What set_thread_check_handler() installs: called on the offending thread, before the call it reports goes ahead.

VisualId

using ui::VisualId = std::uint32_t

Header: winui/core/VisualId.hpp.

A stable identity for an Element, unique in the process, assigned at construction and never reused (Element::visual_id()). Use it as a key for data kept about an element elsewhere.

Functions

lerp

Color lerp(const Color& a, const Color& b, float t)

Header: winui/core/Color.hpp.

Channel-wise linear interpolation from a (t = 0) to b (t = 1), alpha included. t is clamped to [0, 1]. Interpolates the stored sRGB values directly, not in linear light.

command_line

std::vector<std::string> command_line()

Header: winui/core/CommandLine.hpp.

Every argument, UTF-8 encoded, the program itself first (argv[0]'s place), so an app that wants only what the user passed starts at index 1. A path argument goes through path_from_utf8() (core/Utf8Path.hpp), not std::filesystem::path's own std::string constructor. Re-reads the process command line on every call; empty only where no source exists.

Example:

int main()
{
    const std::vector<std::string> args = ui::command_line();
    const std::filesystem::path folder =
        args.size() > 1 ? ui::path_from_utf8(args[1]) : std::filesystem::current_path();
    // ... open `folder` ...
    return 0;
}

regional_date_format

const DateFormatSymbols& regional_date_format()

Header: winui/core/DateFormat.hpp.

The regional date format: what the date and time controls use. Invariant until a host sets it. Process-wide; UI thread only.

set_regional_date_format

void set_regional_date_format(DateFormatSymbols symbols)

Header: winui/core/DateFormat.hpp.

Sets the regional date format. The window host sets it from the user's locale and the Region settings. Raises regional_date_format_changed() when it differs from the current one.

regional_date_format_changed

const Signal& regional_date_format_changed()

Header: winui/core/DateFormat.hpp.

Raised when the regional date format changes: the date and time controls write their text again. An app that caches formatted dates subscribes here and keeps the Subscription.

format_date

std::string format_date(std::chrono::year_month_day date, std::string_view pattern, const DateFormatSymbols& symbols = regional_date_format())

Header: winui/core/DateFormat.hpp.

date written with pattern (see DateFormatSymbols). An invalid date writes nothing.

format_time

std::string format_time(std::chrono::minutes time, std::string_view pattern, const DateFormatSymbols& symbols = regional_date_format())

Header: winui/core/DateFormat.hpp.

time (a time of day, from midnight) written with pattern (see DateFormatSymbols). Whole days in time are dropped.

today

std::chrono::year_month_day today()

Header: winui/core/DateFormat.hpp.

The date today on the local clock. Read from the system clock on every call.

operator|

DirtyFlags operator|(DirtyFlags a, DirtyFlags b)

Header: winui/core/DirtyFlags.hpp.

Union of two flag sets.

operator&

DirtyFlags operator&(DirtyFlags a, DirtyFlags b)

Header: winui/core/DirtyFlags.hpp.

Intersection of two flag sets; pass the result to any() to test a bit.

operator~

DirtyFlags operator~(DirtyFlags a)

Header: winui/core/DirtyFlags.hpp.

Complement within DirtyFlags::All, so ~Layout never carries undefined high bits.

operator|=

DirtyFlags& operator|=(DirtyFlags& a, DirtyFlags b)

Header: winui/core/DirtyFlags.hpp.

Adds the flags in b to a.

operator&=

DirtyFlags& operator&=(DirtyFlags& a, DirtyFlags b)

Header: winui/core/DirtyFlags.hpp.

Keeps only the flags of a that are also in b; a &= ~f clears f.

any

bool any(DirtyFlags flags)

Header: winui/core/DirtyFlags.hpp.

True if at least one flag is set.

intersection

Rect intersection(const Rect& a, const Rect& b)

Header: winui/core/Geometry.hpp.

Intersection of two rectangles (empty rect if they do not overlap).

operator|

PointerDeviceTypes operator|(PointerDeviceTypes a, PointerDeviceTypes b)

Header: winui/core/Input.hpp.

Combines two device sets (ui::PointerDeviceTypes::Pen | ui::PointerDeviceTypes::Mouse).

has_device

bool has_device(PointerDeviceTypes set, PointerDeviceType device)

Header: winui/core/Input.hpp.

Whether set includes device.

key_letter_index

std::optional<int> key_letter_index(Key key)

Header: winui/core/Input.hpp.

Whether key is one of the letters A-Z, and which (0 for A). Unset otherwise.

key_display_name

std::string_view key_display_name(Key key)

Header: winui/core/Input.hpp.

The name shortcut text gives key ("S", "Delete", "F4", "+" for the keypad Add), the one a menu item shows beside its label and a tooltip after its text. Empty for Key::Unknown. The named keys (Delete, Enter, the arrows, ...) come from strings().keys, and the view stays valid until the next set_strings().

operator+

KeyCombo operator+(ModifierKeys mods, Key key)

Header: winui/core/Input.hpp.

A key combination of mods and key: ui::Ctrl + ui::Key::S.

shortcut_text

std::string shortcut_text(const KeyCombo& chord)

Header: winui/core/Input.hpp.

The shortcut text for chord: the modifiers in a fixed order (Win, Ctrl, Alt, Shift) and the key, joined with "+", such as "Ctrl+S", "Ctrl+Shift+N", "Alt+Enter" or "Delete". Empty for an empty key combination. The key names come from strings().keys.

regional_number_format

const NumberFormatSymbols& regional_number_format()

Header: winui/core/NumberFormat.hpp.

The regional format: what a DecimalFormatter without symbols of its own uses. Invariant until a host sets it. Process-wide; UI thread only.

set_regional_number_format

void set_regional_number_format(NumberFormatSymbols symbols)

Header: winui/core/NumberFormat.hpp.

Sets the regional format. The window host sets it from the user's locale. Raises regional_number_format_changed() when it differs from the current one.

regional_number_format_changed

const Signal& regional_number_format_changed()

Header: winui/core/NumberFormat.hpp.

Raised when the regional format changes: a NumberBox on the default formatter reformats. An app that caches formatted text subscribes here and keeps the Subscription.

round_significant

double round_significant(double value, int digits)

Header: winui/core/NumberFormat.hpp.

value rounded to digits significant digits. NumberBox rounds its display to 10, which hides the digits floating-point arithmetic leaves behind (0.1 + 0.2 shows as 0.3). digits counts significant digits, not fraction digits. NaN and the infinities pass through.

evaluate_expression

std::optional<double> evaluate_expression(std::string_view expression, const DecimalFormatter& parser)

Header: winui/core/NumberFormat.hpp.

Evaluates an arithmetic expression of numbers, + - * / ^, parentheses and spaces. Numbers are read with parser, so in its locale: "1,5 + 2" is 3.5 where the decimal separator is ",". ^ binds tighter than * /, which bind tighter than + -, and each is left-associative. A division by zero is NaN, and anything malformed is nullopt.

bind

template <typename T>
Binding<std::vector<T>> bind(ObservableVector<T>& source)

Header: winui/core/ObservableVector.hpp.

Binding of a collection to an .items field: the field follows every insert, removal, replacement and move, row by row. ui::ForEach then passes each item to .item as T&.

A field that reads the collection in place (ui::ForEach, the views) never copies it. On a field that only takes a whole vector (a shape's .points), the binding delivers a copy of the collection when the field is built and on every change, which needs a copyable item type.

bind

template <typename T>
Binding<std::vector<T>> bind(const ObservableVector<T>& source)
    requires std::copy_constructible<T>

Header: winui/core/ObservableVector.hpp.

Binding of a collection the caller may only read. The field gets a copy of the whole collection when it is built and again after every change, as from a Property<std::vector<T>>; it never writes to the collection, so a view built from it does not reorder it by drag.

bind

template <typename T>
Binding<std::vector<T>> bind(ObservableVector<T>&& source) = delete

Header: winui/core/ObservableVector.hpp.

Deleted: a binding keeps a reference to its source, so a temporary collection cannot be bound.

bind

template <typename T>
Binding<std::vector<T>> bind(const ObservableVector<T>&& source) = delete

Header: winui/core/ObservableVector.hpp.

Deleted: a binding keeps a reference to its source, so a temporary collection cannot be bound.

item_count

template <typename T>
ItemCount item_count(const ObservableVector<T>& source)

Header: winui/core/ObservableVector.hpp.

The size of source, kept current: what an index-based collection spec's .item_count takes to follow a ui::ObservableVector. See ui::ItemCount.

item_count

template <typename T>
ItemCount item_count(const ObservableVector<T>&& source) = delete

Header: winui/core/ObservableVector.hpp.

Deleted: the count keeps a reference to its source, so a temporary collection cannot be used.

item_count

template <typename T, typename K>
ItemCount item_count(const Property<std::vector<T>>& source, K key)
    requires std::constructible_from<ItemKey<T>, K> && std::copy_constructible<K>

Header: winui/core/ObservableVector.hpp.

The size of the vector in source, kept current, with each change of the property reported as what happened to the items: what an index-based collection spec's .item_count takes to follow a ui::Property<std::vector<T>> the app assigns as a whole. The typed views (ui::ListView, ui::TileView, ui::TableView) do the same from .items and .key.

key says which item is which (a member pointer or a callable, see ui::ItemKey). An item whose key is still there is reported as moved, not as removed and inserted, so its row stays with it through a sort or a filter. Keys must be unique. The item template reads the property by index.

Example:

struct Contact
{
    int         id = 0;
    std::string name;
    friend bool operator==(const Contact&, const Contact&) = default;
};
ui::Property<std::vector<Contact>> contacts{std::vector<Contact>{{1, "Grace"}, {2, "Ada"}}};

ui::ItemCount count = ui::item_count(contacts, &Contact::id);
ui::Subscription following = count.subscribe([&](const ui::CollectionChange& /*change*/) {
    // Forward to an index-based control: notify_inserted(), notify_removed(), notify_moved() ...
});

std::vector<Contact> sorted = contacts.get();
std::ranges::sort(sorted, {}, &Contact::name);
contacts = std::move(sorted); // reported as moves

item_count

template <typename T>
ItemCount item_count(const Property<std::vector<T>>& source)

Header: winui/core/ObservableVector.hpp.

As above without a key: the items before and after an edit are kept and those in between are reported as removed, inserted or replaced. That covers appending and removing; a reorder replaces nearly everything.

item_count

template <typename T, typename... K>
ItemCount item_count(const Property<std::vector<T>>&& source, K... key) = delete

Header: winui/core/ObservableVector.hpp.

Deleted: the count keeps a reference to its source, so a temporary property cannot be used.

observe

template <typename Fn, typename... Ss>
Subscription observe(Fn fn, const Ss& ... sources)
    requires (sizeof...(Ss) > 0) && (detail::is_source<Ss> && ...) && std::invocable<Fn&, const detail::source_value_t<Ss>&...> && (std::copy_constructible<detail::source_value_t<Ss>> && ...)

Header: winui/core/Property.hpp.

Observes several sources with one handler: fn(a, b, ...) runs with the latest value of every source whenever any of them changes. Not called for the current values, as Property::observe() is not. The sources are Property or Computed values, in any mix.

The returned Subscription holds every edge, so keeping it keeps fn firing and dropping it ends all of them. It remembers each source's last value, so a source destroyed before the others stops contributing changes.

Example:

ui::Property<std::string> first;
ui::Property<std::string> last;
ui::Subscription greet = ui::observe(
    [](const std::string& f, const std::string& l) { std::println("Hello, {} {}", f, l); }, first, last);
first = "Ada"; // prints "Hello, Ada "

observe

template <typename Fn, typename... Sources>
Subscription observe(Fn fn, Sources&& ... sources) = delete
    requires (sizeof...(Sources) > 0) && (detail::is_source<Sources> && ...) && (std::is_rvalue_reference_v<Sources &&> || ...)

Header: winui/core/Property.hpp.

Deleted: the subscription keeps a reference to each source, so none of them can be a temporary.

Computed

template <typename Fn, typename... Ss>
Computed(Fn, const Ss& ...) -> Computed<std::remove_cvref_t<std::invoke_result_t<Fn&, const detail::source_value_t<Ss>& ...>>>
    requires (sizeof...(Ss) > 0) && (detail::is_source<Ss> && ...)

Header: winui/core/Property.hpp.

ui::Computed c{fn, a, b} takes its type from what fn returns.

bind

template <typename T>
Binding<T> bind(const Property<T>& source)

Header: winui/core/Property.hpp.

One-source binding: the property's value, verbatim.

Takes the property by const reference, since observing is not writing. A read-only property a host owns binds like one the app owns. The rvalue overloads are deleted because a binding keeps a reference to its source, and a temporary Property would be gone before the first change.

Example:

ui::Property<bool> online{true};
window.set_content(ui::ToggleSwitch{.checked = ui::bind(online)}); // or `.checked = online`

bind

template <typename T, typename Fn>
auto bind(const Property<T>& source, Fn fn)
    requires std::invocable<Fn&, const T&> && std::copy_constructible<Fn>

Header: winui/core/Property.hpp.

One-source binding with a transform, so a format string exists once in a program instead of once per writer. The result type is whatever fn returns. fn runs once now for the initial value and again on every change.

Example:

ui::Property<int> clicks{0};
ui::Text label{.text = ui::bind(clicks, [](int n) { return std::format("Clicks: {}", n); })};

fn must be copyable, because it is stored once per subscription edge.

bind_one_way

template <typename T>
Binding<T> bind_one_way(const Property<T>& source)

Header: winui/core/Property.hpp.

One-way binding of a property, whatever field it lands on: the control shows the property and never writes to it. The way to opt an editable field out of bind()'s two-way default, for an input that only displays state or whose edits the app validates before storing.

Example:

ui::Property<float> level{0.4f};
// The slider follows `level`; dragging it does not change `level` by itself.
// The app stores only the levels it accepts.
window.set_content(ui::Slider{
    .value            = ui::bind_one_way(level),
    .on_value_changed = [&](double v) { if (v <= 0.8) { level = static_cast<float>(v); } },
});

bind_one_way

template <typename T>
Binding<T> bind_one_way(const Property<T>&& source) = delete

Header: winui/core/Property.hpp.

Deleted: a binding keeps a reference to its source, so a temporary Property cannot be bound.

bind

template <typename T>
TwoWayBinding<T> bind(Property<T>& source)

Header: winui/core/Property.hpp.

Binding of a property the app can write, with no conversion. On an editable field (a text box's .text, a slider's .value, a toggle's .checked, a list's .selected_index, ...) it is two-way: the control shows the property, and what the user enters is written back into it, before the field's own on_*_changed handler runs. On a display field it is one-way, as there is nothing to write. A const Property and a bind() with a conversion are always one-way; bind_one_way() opts an editable field out. An editable field that can be unset takes it only from a Property<std::optional<T>>; see TwoWayField.

The equality gate of Property::set() ends the round trip: the value written back equals the one the control already shows.

Example:

ui::Property<std::string> name{"Ada"};
window.set_content(ui::VerticalStack{.content = {
    ui::TextBox{.text = ui::bind(name)},                                   // typing changes `name`
    ui::Text{.text = ui::bind(name, [](const std::string& n) { return "Hello, " + n; })},
}});

This overload also keeps ADL from picking std::bind for a non-const lvalue of a std:: type.

selects

template <typename T, typename V>
TwoWayBinding<bool> selects(Property<T>& source, V&& value)
    requires std::constructible_from<T, V> && std::equality_comparable<T>

Header: winui/core/Property.hpp.

One choice of several, written into a control's checked: the control is checked while source holds value, and checking it sets source to value. Unchecking writes nothing, since a choice is only ever left by making another one.

Every control bound through selects() to the same property is one set of choices, wherever it sits in the tree: checking one unchecks the others through the property. RadioButtons bound this way also act as one group for the keyboard and screen readers: Tab stops once on the group (on the checked button, or the first), the arrow keys move between the buttons and check the one they reach (Ctrl+arrow moves without checking), and each button reports its position in the set. A ToggleButton bound this way stays checked when clicked again, like a radio button. For one control that lists the choices itself (a SelectorBar, RadioButtons), see bind_choice().

Example:

enum class Size { Small, Medium, Large };
ui::Property<Size> size{Size::Medium};

window.set_content(ui::VerticalStack{.content = {
    ui::RadioButton{.text = "Small", .checked = ui::selects(size, Size::Small)},
    ui::Text{.text = "Fits a phone."},
    ui::RadioButton{.text = "Medium", .checked = ui::selects(size, Size::Medium)},
    ui::RadioButton{.text = "Large", .checked = ui::selects(size, Size::Large)},
}});

selects

template <typename T, typename V>
TwoWayBinding<bool> selects(Property<T>&& source, V&& value) = delete

Header: winui/core/Property.hpp.

Deleted: the binding keeps a reference to its source, so a temporary Property cannot be used.

bind_choice

template <typename T>
ChoiceBinding bind_choice(Property<T>& source, std::vector<T> choices)
    requires std::equality_comparable<T> && std::copy_constructible<T>

Header: winui/core/Property.hpp.

A property holding one of several values, bound two-way to an index field (selected_index on a SelectorBar, Sections, Carousel, PipsPager, ComboBox, RadioButtons, ListView, ...). choices lists the values in the order of the control's items: the field shows the position of the value source holds, and picking item i sets source to choices[i].

A value that is not in the list shows no selection where the field can show none (a ComboBox, a ListView). A field that always shows a selection (a Sections control, a SelectorBar) keeps the one it has, and starts on the first choice. Clearing the selection writes nothing.

For a choice made with separate controls, one per value, see selects().

Example:

enum class Filter { All, Active, Done };
ui::Property<Filter> filter{Filter::All};

ui::SelectorBar{
    .items          = {"All", "Active", "Done"},
    .selected_index = ui::bind_choice(filter, {Filter::All, Filter::Active, Filter::Done}),
};
filter = Filter::Done; // selects "Done"

bind_choice

template <typename T>
ChoiceBinding bind_choice(Property<T>&& source, std::vector<T> choices) = delete

Header: winui/core/Property.hpp.

Deleted: the binding keeps a reference to its source, so a temporary Property cannot be used.

bind

template <typename T, typename Fn>
auto bind(Property<T>& source, Fn fn)
    requires std::invocable<Fn&, const T&> && std::copy_constructible<Fn>

Header: winui/core/Property.hpp.

Same as bind(const Property&, Fn); exists so ADL never picks std::bind.

bind

template <typename Fn, typename... Ss>
auto bind(Fn fn, const Ss& ... sources)
    requires (sizeof...(Ss) > 0) && (detail::is_source<Ss> && ...) && std::invocable<Fn&, const detail::source_value_t<Ss>&...> && std::copy_constructible<Fn> && (std::copy_constructible<detail::source_value_t<Ss>> && ...)

Header: winui/core/Property.hpp.

Several-source binding: fn(a.get(), b.get(), ...), computed again whenever any of the sources changes. The function comes first, so the sources after it can be any number of Property and Computed values. A value used in more than one place is better declared once as a Computed.

The result is one-way. A change that computes the same result costs what the target's setter costs for an unchanged value, which is nothing. The binding remembers each source's last value, so a source destroyed before the others stops contributing changes. fn must be copyable, as for the one-source form.

Example:

ui::Property<bool> dirty{false};
ui::Property<bool> busy{false};

ui::Button save{
    .text    = "Save",
    .enabled = ui::bind([](bool is_dirty, bool is_busy) { return is_dirty && !is_busy; }, dirty, busy),
};

bind

template <typename T>
Binding<T> bind(const Computed<T>& source)

Header: winui/core/Property.hpp.

One-way binding of a Computed: its value, verbatim. Same as bind() of a const Property<T>.

bind

template <typename T, typename Fn>
auto bind(const Computed<T>& source, Fn fn)
    requires std::invocable<Fn&, const T&> && std::copy_constructible<Fn>

Header: winui/core/Property.hpp.

One-way binding of a Computed with a transform, as bind(const Property&, Fn).

bind

template <typename T>
Binding<T> bind(const Property<T>&& source) = delete

Header: winui/core/Property.hpp.

Deleted: a binding keeps a reference to its source, so a temporary Property cannot be bound.

bind

template <typename T, typename Fn>
auto bind(const Property<T>&& source, Fn fn) = delete

Header: winui/core/Property.hpp.

Deleted: a binding keeps a reference to its source, so a temporary Property cannot be bound.

bind

template <typename T>
Binding<T> bind(const Computed<T>&& source) = delete

Header: winui/core/Property.hpp.

Deleted: a binding keeps a reference to its source, so a temporary Computed cannot be bound.

bind

template <typename T, typename Fn>
auto bind(const Computed<T>&& source, Fn fn) = delete

Header: winui/core/Property.hpp.

Deleted: a binding keeps a reference to its source, so a temporary Computed cannot be bound.

bind

template <typename Fn, typename... Sources>
auto bind(Fn fn, Sources&& ... sources) = delete
    requires (sizeof...(Sources) > 0) && (detail::is_source<Sources> && ...) && (std::is_rvalue_reference_v<Sources &&> || ...)

Header: winui/core/Property.hpp.

Deleted: the several-source form keeps a reference to each source, so none of them can be a temporary.

strings

const Strings& strings()

Header: winui/core/Strings.hpp.

The text libwinui shows now: English until set_strings() replaces it. Process-wide; UI thread only. The reference stays valid until the next set_strings().

set_strings

void set_strings(Strings replacement)

Header: winui/core/Strings.hpp.

Replaces the text libwinui shows and raises strings_changed(): every window lays out and draws again, and the controls that hold text of their own refresh it.

strings_changed

const Signal& strings_changed()

Header: winui/core/Strings.hpp.

Raised by set_strings(). An app that caches text from strings() subscribes here and keeps the Subscription.

set_thread_check_handler

ThreadCheckHandler set_thread_check_handler(ThreadCheckHandler handler) noexcept

Header: winui/core/ThreadCheck.hpp.

Replace what a failed thread check does; nullptr restores the default. Returns the handler it replaced (nullptr for the default). Safe from any thread.

In a build with checks (LIBWINUI_THREAD_CHECKS, on by default without NDEBUG), a mutation from a thread that does not own what it mutates is reported: an element setter (anything that invalidates through Element::mark_dirty()) on an element attached to a Window, from another thread than the one that constructed the Window; a member of Window other than post(); a write to a Property, ObservableVector or Signal that has notified observers before, from another thread than its first notifying write, and a new observer from such a thread. Reading is never checked, so measuring on worker threads is fine. A detached element (built but not yet under a Window) is unchecked, so a tree may be built on a worker and handed over with Window::post().

The default handler writes the message to stderr and the debugger output, then breaks into the debugger when one is attached and aborts otherwise, as a failed assert does: the call is a data race, and what it corrupts shows up far from here.

Example:

// A test that would rather count than stop.
static std::atomic<int> failures{0};
ui::set_thread_check_handler([](const ui::ThreadCheckFailure& f) {
    std::fprintf(stderr, "%s\n", f.message.c_str());
    ++failures;
});

default_thread_check_handler

void default_thread_check_handler(const ThreadCheckFailure& failure)

Header: winui/core/ThreadCheck.hpp.

What a failed check does unless set_thread_check_handler() says otherwise: print the message, then break into an attached debugger or abort. Public so a custom handler can fall back to it.

decode_utf8

Utf8Decoded decode_utf8(std::string_view text, std::size_t pos = 0)

Header: winui/core/Utf8.hpp.

The code point starting at byte pos of text. A malformed sequence decodes to U+FFFD and takes only the bytes that belonged to it, so decoding carries on at the next one. At or past the end the result is {0, 0}.

append_utf8

void append_utf8(std::string& out, char32_t code_point)

Header: winui/core/Utf8.hpp.

Appends code_point to out as UTF-8. A surrogate or a value beyond U+10FFFF appends U+FFFD.

encode_utf8

std::string encode_utf8(char32_t code_point)

Header: winui/core/Utf8.hpp.

code_point as a UTF-8 string.

next_code_point

std::size_t next_code_point(std::string_view text, std::size_t pos)

Header: winui/core/Utf8.hpp.

The byte offset of the code point after the one at pos; text.size() at or past the end.

previous_code_point

std::size_t previous_code_point(std::string_view text, std::size_t pos)

Header: winui/core/Utf8.hpp.

The byte offset of the code point before pos; 0 at the start.

is_code_point_boundary

bool is_code_point_boundary(std::string_view text, std::size_t pos)

Header: winui/core/Utf8.hpp.

True when pos is 0, text.size(), or the first byte of a code point.

floor_code_point

std::size_t floor_code_point(std::string_view text, std::size_t pos)

Header: winui/core/Utf8.hpp.

pos moved back onto the start of the code point it falls inside, clamped to the text.

code_point_count

std::size_t code_point_count(std::string_view text)

Header: winui/core/Utf8.hpp.

How many code points text holds, a malformed sequence counting as one.

is_valid_utf8

bool is_valid_utf8(std::string_view text)

Header: winui/core/Utf8.hpp.

True when text is well-formed UTF-8: no overlong forms, no surrogates, nothing past U+10FFFF.

sanitize_utf8

std::string sanitize_utf8(std::string_view text)

Header: winui/core/Utf8.hpp.

text with every malformed sequence replaced by U+FFFD. libwinui passes text from outside, such as keyboard input, the clipboard, files and the command line, through this once.

to_utf16

std::u16string to_utf16(std::string_view text)

Header: winui/core/Utf8.hpp.

text as UTF-16, for system and library APIs that take it.

from_utf16

std::string from_utf16(std::u16string_view text)

Header: winui/core/Utf8.hpp.

text, which is UTF-16, as UTF-8.

utf16_length

std::size_t utf16_length(std::string_view text)

Header: winui/core/Utf8.hpp.

How many UTF-16 code units text takes: one per code point, two past the BMP. The UTF-16 offset of byte pos is utf16_length(text.substr(0, pos)).

utf8_offset_from_utf16

std::size_t utf8_offset_from_utf16(std::string_view text, std::size_t units)

Header: winui/core/Utf8.hpp.

The byte offset of text that lies units UTF-16 code units in, the inverse of utf16_length(). A count that ends between the two halves of a surrogate pair lands before the pair; one past the end lands on text.size().

code_points

CodePoints code_points(std::string_view text)

Header: winui/core/Utf8.hpp.

A CodePoints view over text, for a range-for. text must outlive the loop.

path_from_utf8

std::filesystem::path path_from_utf8(std::string_view text)

Header: winui/core/Utf8Path.hpp.

A path from a UTF-8 string. Use it wherever a string becomes a path: std::filesystem::path(std::string) reads the string in the system's legacy code page, which mangles characters outside it.

Example:

// A file name typed into a TextBox is UTF-8; the "ü" survives into the path.
ui::Property<std::string> file_name{"Zürich.png"};
const std::filesystem::path path = ui::path_from_utf8(file_name.get());
const ui::Bitmap picture{16, 16, ui::colors::White};
picture.write_png(path);

// path_to_utf8() goes back the other way, for a label.
ui::Property<std::string> status{"Saved " + ui::path_to_utf8(path.filename())}; // "Saved Zürich.png"

path_to_utf8

std::string path_to_utf8(const std::filesystem::path& path)

Header: winui/core/Utf8Path.hpp.

path as UTF-8, the inverse of path_from_utf8().

version_string

const char* version_string()

Header: winui/core/Version.hpp.

The version of the linked library as "major.minor.patch", e.g. "0.1.0". Compare it with VersionMajor, VersionMinor and VersionPatch to detect a header/binary mismatch with the shared library. There is no ABI promise: a shared library only works with the headers of its own version, built by the same compiler with the same options. The string is static; never free it.

allocate_visual_id

VisualId allocate_visual_id()

Header: winui/core/VisualId.hpp.

Returns a new id, unique in the process, counting up from 1. Thread-safe. Element calls this itself, so controls never need to.

Constants

Name Type Value
Handled Handling Handling::Handled See ui::Handling.
NotHandled Handling Handling::NotHandled See ui::Handling.
Proceed Decision Decision::Proceed See ui::Decision.
Cancel Decision Decision::Cancel See ui::Decision.
Unbounded float std::numeric_limits<float>::infinity() The extent of an unbounded axis in a measure offer (Element::measure).
Ctrl ModifierKeys {.ctrl = true} Ctrl, for writing a key combination: ui::Ctrl + ui::Key::S.
Shift ModifierKeys {.shift = true} Shift, for writing a key combination: ui::Ctrl + ui::Shift + ui::Key::N.
Alt ModifierKeys {.alt = true} Alt, for writing a key combination: ui::Alt + ui::Key::Enter.
Win ModifierKeys {.win = true} The Windows logo key, for writing a key combination.
ThreadChecksEnabled bool LIBWINUI_THREAD_CHECKS != 0 Whether this build checks thread affinity (see set_thread_check_handler()); LIBWINUI_THREAD_CHECKS as a constant.
ReplacementCharacter char32_t 0xFFFD U+FFFD, what malformed input decodes to.
VersionMajor int LIBWINUI_VERSION_MAJOR Major version of the headers being compiled against.
VersionMinor int LIBWINUI_VERSION_MINOR Minor version of the headers being compiled against.
VersionPatch int LIBWINUI_VERSION_PATCH Patch version of the headers being compiled against.
InvalidVisualId VisualId 0 The id that marks no element. allocate_visual_id() never returns 0.