Table of Contents

Progress and rating

TTMSFNCProgressBar displays a horizontal or vertical fill that represents a numeric value between Minimum and Maximum. The same base class powers TTMSFNCRating, which divides the bar into discrete blocks so users can tap or drag to set a star-style rating.

Basic usage

Set Minimum, Maximum, and Value at design time or runtime. The bar redraws immediately when Value changes:

// Show progress of a background operation
procedure TForm1.StartOperation;
begin
  TMSFNCProgressBar1.Minimum := 0;
  TMSFNCProgressBar1.Maximum := 100;
  TMSFNCProgressBar1.Value   := 0;
end;

procedure TForm1.UpdateProgress(APercent: Integer);
begin
  TMSFNCProgressBar1.Value := APercent;
end;

Shape and segmented display

Layout.Shape switches between psHorizontalLine (default) and psVerticalLine. Layout.Blocks splits the filled area into equal segments with Layout.Spacing pixels of gap between them:

TMSFNCProgressBar1.Layout.Shape   := psVerticalLine;
TMSFNCProgressBar1.Layout.Blocks  := 8;
TMSFNCProgressBar1.Layout.Spacing := 2;

Displaying the value label

Set Layout.ShowValue to True to draw a text label. Layout.ValueType controls the content:

Value Label shows
pvtPercentage Percentage of the range (default)
pvtValue The raw numeric Value
pvtCustom The string you assign to CustomValue

Position the label with Layout.TextPosition (ptpStart, ptpCenter, ptpEnd, ptpProgressEnd, ptpFollowCenter, ptpFollowEnd, ptpProgressCenter). Rotate the label with Layout.TextOrientation (ptoHorizontal, ptoLeft, ptoRight, ptoUpsideDown).

Add Layout.Prefix and Layout.Suffix strings to wrap the label, for example '%'.

Appearance and threshold levels

Appearance.Fill styles the filled (active) portion; Appearance.DefaultLevelFill styles the unfilled (inactive) background. Use the Levels collection to change colour automatically when Value crosses a threshold:

// Vertical segmented bar with percentage label
procedure TForm1.ConfigureProgressBar;
begin
  with TMSFNCProgressBar1 do
  begin
    // Five equal blocks with gaps between them
    Layout.Blocks  := 5;
    Layout.Spacing := 3;
    Layout.Shape   := psVerticalLine;

    // Label: "72%" centred inside the filled area
    Layout.ShowValue    := True;
    Layout.ValueType    := pvtPercentage;
    Layout.Decimals     := 0;
    Layout.Suffix       := '%';
    Layout.TextPosition := ptpCenter;

    // Progress fill colour and background
    Appearance.Fill.Color            := $0015A34A;
    Appearance.DefaultLevelFill.Color := $00E0E0E0;
  end;
end;

// Threshold-based colour change using Levels
procedure TForm1.AddLevels;
var
  L: TTMSFNCCustomProgressBarLevel;
begin
  TMSFNCProgressBar1.Levels.Clear;

  L := TTMSFNCCustomProgressBarLevel(TMSFNCProgressBar1.Levels.Add);
  L.LevelPosition := 50;               // switches at 50 %
  L.Fill.Color    := $000080FF;        // blue above 50 %

  L := TTMSFNCCustomProgressBarLevel(TMSFNCProgressBar1.Levels.Add);
  L.LevelPosition := 80;
  L.Fill.Color    := $00E53935;        // red above 80 %
end;

Appearance.Stacked makes multiple levels stack visually from left to right rather than replacing each other.

Rating control

TTMSFNCRating shares the same base API. Set Layout.Blocks to the number of rating steps and enable interaction:

Property Effect
Interaction.SnapToValue Click snaps to the nearest block
Interaction.SlideToValue Drag slides to a new rating
Interaction.KeyboardSupport Arrow keys change the value
Interaction.ReadOnlyMode Disables all mouse and keyboard input
// Five-star interactive rating control
procedure TForm1.ConfigureRating;
begin
  with TMSFNCRating1 do
  begin
    Minimum := 0;
    Maximum := 5;
    Value   := 0;

    // Five discrete star blocks; click to snap to nearest integer
    Layout.Blocks    := 5;
    Layout.Spacing   := 4;
    Layout.ShowValue := False;

    // Allow the user to drag or click a new rating
    Interaction.SnapToValue := True;
    Interaction.SlideToValue := True;
    Interaction.KeyboardSupport := True;
  end;
end;

// React when the user changes the rating
procedure TForm1.TMSFNCRating1ValueChanged(Sender: TObject; AValue: Single);
begin
  StatusLabel.Text := Format('Rating: %.0f / 5', [AValue]);
end;

Use OnSlideValueChanged, OnSnapValueChanged, or OnKeyboardValueChanged to react after a change, and their *Change counterparts (with var AAllow: Boolean) to cancel one.

Custom draw hook

OnBeforeDrawBlock fires before each block is rendered and lets you fully replace its drawing by setting ADefaultDraw := False. OnBeforeDrawValue fires before the label and receives the current text string so you can override it:

procedure TForm1.TMSFNCProgressBar1BeforeDrawBlock(Sender: TObject;
  AGraphics: TTMSFNCGraphics; ARect: TRectF;
  ACorners: TTMSFNCGraphicsCorners;
  var AAllow, ADefaultDraw: Boolean);
begin
  AGraphics.Fill.Color := $00FF9800;
  ADefaultDraw := True;  // let the bar draw, but fill colour is already set
end;

Combining blocks, levels, and a custom label

The example below builds a segmented upload indicator that changes colour at 75 % and 90 % and shows a "12 MB / 50 MB" label using pvtCustom:

// Segmented upload progress bar with threshold colours and a custom label
procedure TForm1.FormCreate(Sender: TObject);
begin
  with TMSFNCProgressBar1 do
  begin
    Minimum := 0;
    Maximum := 100;
    Value   := 0;

    Layout.Blocks       := 10;
    Layout.Spacing      := 2;
    Layout.Shape        := psHorizontalLine;
    Layout.ShowValue    := True;
    Layout.ValueType    := pvtCustom;   // controlled via OnBeforeDrawValue
    Layout.TextPosition := ptpCenter;

    // Base fill (0–50 %)
    Appearance.Fill.Color := $00519657;

    // Amber above 75 %
    with TTMSFNCCustomProgressBarLevel(Levels.Add) do
    begin
      LevelPosition := 75;
      Fill.Color    := $00E69820;
    end;

    // Red above 90 %
    with TTMSFNCCustomProgressBarLevel(Levels.Add) do
    begin
      LevelPosition := 90;
      Fill.Color    := $00C62828;
    end;
  end;
end;

// Supply a friendly "12 MB / 50 MB" label instead of a percentage
procedure TForm1.TMSFNCProgressBar1BeforeDrawValue(Sender: TObject;
  AGraphics: TTMSFNCGraphics; AText: string; ARect: TRectF;
  APosition: TTMSFNCProgressBarTextPosition;
  AOrientation: TTMSFNCProgressBarTextOrientation;
  var AAllow: Boolean; var ADefaultDraw: Boolean);
begin
  TMSFNCProgressBar1.CustomValue :=
    Format('%d MB / %d MB',
      [Round(TMSFNCProgressBar1.Value / TMSFNCProgressBar1.Maximum * 50), 50]);
end;