Skip to content

ProgressBar

Header: winui/ui/status/ProgressBar.hpp. Spec: winui/ui/status/ProgressBar.hpp.

A thin horizontal bar showing determinate progress, or an endless sweep while the duration is unknown.

Determinate, a pill-shaped accent indicator covers the fraction of [min(), max()] that value() has reached, over a 1 DIP track; it jumps to each new value without animating. Indeterminate, two bars sweep across in a 2-second loop. show_paused() / show_error() tint the indicator in the caution / critical color (error wins) and freeze an indeterminate sweep into one full-width bar. The bar is 3 DIPs tall and 200 DIPs wide unless its slot is narrower; it takes no input and has no disabled state.

Under Aero it is the era's bar instead: 15 DIPs tall, framed and glossy, with a glint that crosses the filled part at 200 DIPs a second and rests a second between passes. An indeterminate Aero bar runs the glint over the empty track.

Under Windows 9x it is 16 DIPs tall: a face-colored well with a 1 DIP sunken edge, filled with highlight-colored chunks two thirds as wide as they are tall, 2 DIPs apart. Under Windows 3.x and Windows 1.x it is one solid block inside a 1 DIP frame, black on white under Windows 1.x. Indeterminate, each sweeps a band across the well: five chunks under Windows 9x, a quarter of the bar under the other two. ui::ProgressBar is the declarative form.

Example:

ui::Property<double> progress{0.0};

window.set_content(ui::VerticalStack{
    .spacing  = 12,
    .content  = {
        ui::ProgressBar{.value = progress, .width = 200.0f,
                               .accessibility = {.name = "Download progress"}},
        ui::ProgressBar{.width = 200.0f},
        ui::Button{.text = "Step", .on_click = [&] { progress += 10.0; }},
    },
});

// Imperatively:
auto bar = std::make_unique<ui::ProgressBarControl>(/*value=*/0.0, /*min=*/0.0, /*max=*/1.0);
bar->on_value_changed([](double v) { /* v is already clamped to [0, 1] */ });
bar->set_value(0.25);
bar->set_show_paused(true); // amber indicator

ui::ProgressBar

A determinate or indeterminate horizontal progress bar. Builds a ui::ProgressBarControl.

Example:

ui::Property<double> progress{0.0};

window.set_content(ui::VerticalStack{
    .spacing  = 8,
    .content  = {
        ui::ProgressBar{.value = progress, .width = 200.0f},
        ui::ProgressBar{.width = 200.0f}, // no value: an indeterminate sweep
        ui::Button{.text = "Step", .on_click = [&] { progress += 10.0; }},
    },
});

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

ui::ProgressBar{
    .value, .min, .max, .show_paused, .show_error, .style, .margin, .width, .height,
    .min_width, .min_height, .max_width, .max_height, .horizontal_alignment,
    .vertical_alignment, .visible, .tool_tip, .accessibility, .on_value_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
value ui::Binding<std::optional<double>> Value, clamped to [min, max]; the filled share of the bar. Unset (the default) is an endless sweep, for work whose length is unknown.
min double 0.0 The value of the empty bar. Fixed at build time.
max double 100.0 The value of the full bar. Fixed at build time.
show_paused ui::Binding<bool> {false} The indicator in the caution color, and an indeterminate sweep frozen into a full bar.
show_error ui::Binding<bool> {false} As show_paused, in the critical color.
on_value_changed ui::Callback<void(double)> The new (clamped) value, whenever a bound value moves 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::ProgressBar> 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, accessibility every spec carries (conventions).

build

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

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

ui::ProgressBarControl

Derives from ui::Element, ui::RangeValueProvider.

A thin horizontal bar showing determinate progress, or an endless sweep while the duration is unknown.

Determinate, a pill-shaped accent indicator covers the fraction of [min(), max()] that value() has reached, over a 1 DIP track; it jumps to each new value without animating. Indeterminate, two bars sweep across in a 2-second loop. show_paused() / show_error() tint the indicator in the caution / critical color (error wins) and freeze an indeterminate sweep into one full-width bar. The bar is 3 DIPs tall and 200 DIPs wide unless its slot is narrower; it takes no input and has no disabled state.

Under Aero it is the era's bar instead: 15 DIPs tall, framed and glossy, with a glint that crosses the filled part at 200 DIPs a second and rests a second between passes. An indeterminate Aero bar runs the glint over the empty track.

Under Windows 9x it is 16 DIPs tall: a face-colored well with a 1 DIP sunken edge, filled with highlight-colored chunks two thirds as wide as they are tall, 2 DIPs apart. Under Windows 3.x and Windows 1.x it is one solid block inside a 1 DIP frame, black on white under Windows 1.x. Indeterminate, each sweeps a band across the well: five chunks under Windows 9x, a quarter of the bar under the other two. ui::ProgressBar is the declarative form.

Example:

ui::Property<double> progress{0.0};

window.set_content(ui::VerticalStack{
    .spacing  = 12,
    .content  = {
        ui::ProgressBar{.value = progress, .width = 200.0f,
                               .accessibility = {.name = "Download progress"}},
        ui::ProgressBar{.width = 200.0f},
        ui::Button{.text = "Step", .on_click = [&] { progress += 10.0; }},
    },
});

// Imperatively:
auto bar = std::make_unique<ui::ProgressBarControl>(/*value=*/0.0, /*min=*/0.0, /*max=*/1.0);
bar->on_value_changed([](double v) { /* v is already clamped to [0, 1] */ });
bar->set_value(0.25);
bar->set_show_paused(true); // amber indicator

ProgressBarControl

ProgressBarControl(double value = 0.0, double min = 0.0, double max = 100.0)

A determinate bar; max below min is raised to min, and value is clamped into the range.

min

double min() const

The value at which the bar is empty; 0 by default.

max

double max() const

The value at which the bar is full; 100 by default.

set_range

void set_range(double min, double max)

Sets both ends (max below min becomes min) and re-clamps value(), firing on_value_changed() if that moves it. Always marks the bar for redraw.

value

double value() const

The value, always within [min(), max()]; 0 by default. Ignored while indeterminate.

set_value

void set_value(double value)

Clamps into the range (to min() for an empty range). Does nothing, and fires no callback, when the clamped value is unchanged. Otherwise redraws and fires on_value_changed().

is_indeterminate

bool is_indeterminate() const

Whether it shows an endless sweep instead of a filled share; false by default.

set_indeterminate

void set_indeterminate(bool indeterminate)

Redraws only. Turning the sweep on always restarts its phase from the beginning.

show_paused

bool show_paused() const

The indicator in the caution color; false by default.

set_show_paused

void set_show_paused(bool show_paused)

Marks the bar for redraw.

show_error

bool show_error() const

The indicator in the critical color, winning over show_paused(); false by default.

set_show_error

void set_show_error(bool show_error)

Marks the bar for redraw.

on_value_changed

void on_value_changed(Callback<void(double)> handler)

Fired with the new, clamped value whenever value() changes. Replaces any previous handler.

parallel_measure_safe

bool parallel_measure_safe() const override

True: measuring reads nothing shared.

automation_role

AutomationRole automation_role() const override

ProgressBar, with a range value that UI Automation can read but not set, since the bar takes no input.

measure_override

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

200 x 3 DIPs (15 tall under Aero), the width capped at a bounded available width.

render_override

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

Draws the track, then the determinate indicator or the two clipped sweep bars.

tick_override

void tick_override(Duration delta) override

Advances the indeterminate sweep's phase clock while indeterminate and neither paused nor in error; a determinate bar ignores ticks, except under Aero, where the glint runs while there is progress to show.

Tests

  • tests/test_progress_bar.cpp