Status Bar Guide
TTMSFNCStatusBar is a panel-based status bar that displays multiple independently styled sections. Each panel in the Panels collection has its own Style, width, alignment, and content. Supported styles cover plain text, HTML, images, dates, times, progress bars, and fully owner-drawn content.
Adding panels
Add panels to the Panels collection and set each panel's Style and Width. Use AutoSize := True on the main text panel to let it fill remaining space.
// Add four panels at runtime: text, date, time, and a progress bar
procedure TForm1.FormCreate(Sender: TObject);
var
p: TTMSFNCStatusBarPanel;
begin
// Text panel that stretches to fill remaining space
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsHTML;
p.Text := 'Ready';
p.AutoSize := True;
// Date panel
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsDate;
p.Width := 80;
// Time panel
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsTime;
p.Width := 60;
// Progress bar panel
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsProgress;
p.Width := 120;
p.Progress.Min := 0;
p.Progress.Max := 100;
p.Progress.Position := 0;
end;
// Update the progress bar from a background task callback
procedure TForm1.UpdateProgress(APercent: Integer);
begin
TMSFNCStatusBar1.Panels.Items[3].Progress.Position := APercent;
end;
Panel styles
| Style | Content |
|---|---|
spsHTML |
HTML-formatted text with optional anchor links |
spsText |
Plain text |
spsEllipsText |
Text clipped with an ellipsis |
spsImage |
Single image from a BitmapContainer with optional text |
spsImageList |
Sequence of images from a BitmapContainer |
spsDate |
Current date, formatted by DateFormat |
spsTime |
Current time, formatted by TimeFormat |
spsProgress |
Colour-coded progress bar |
spsOwnerDraw |
Fully custom drawing via OnDrawCustomPanel |
// Panel styles demonstrated: HTML text, image, and owner-draw
procedure TForm1.FormCreate(Sender: TObject);
var
p: TTMSFNCStatusBarPanel;
begin
TMSFNCStatusBar1.BitmapContainer := BitmapContainer1;
// HTML text with a coloured status indicator
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsHTML;
p.Text := '<font color="#00AA00">●</font> Online';
p.Width := 80;
// Single image with optional label
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsImage;
p.ImageIndex := 0; // index into BitmapContainer1
p.Text := 'Saved';
p.AutoSize := True;
// Owner-draw: full custom rendering
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsOwnerDraw;
p.Width := 40;
end;
procedure TForm1.TMSFNCStatusBar1DrawCustomPanel(Sender: TObject;
AGraphics: TTMSFNCGraphics; ARect: TRectF; APanel: TTMSFNCStatusBarPanel);
begin
AGraphics.DrawEllipse(ARect);
end;
Progress bar panels and click events
The Progress sub-object on each panel controls the min/max range and three colour-level thresholds. Setting Button := True makes the panel respond to OnPanelLeftClick and OnPanelRightClick.
// Colour-coded progress bar with level thresholds and click event
procedure TForm1.FormCreate(Sender: TObject);
var
p: TTMSFNCStatusBarPanel;
begin
p := TMSFNCStatusBar1.Panels.Add;
p.Style := spsProgress;
p.Width := 150;
p.Progress.Min := 0;
p.Progress.Max := 100;
p.Progress.Level1Perc := 70; // green up to 70 %
p.Progress.Level2Perc := 90; // yellow 70-90 %
// red 90-100 %
p.Progress.Position := 55;
// Make the panel a clickable button
p.Button := True;
end;
procedure TForm1.TMSFNCStatusBar1PanelLeftClick(Sender: TObject; PanelIndex: Integer);
begin
if PanelIndex = 0 then
ShowMessage('Progress: ' + IntToStr(TMSFNCStatusBar1.Panels.Items[0].Progress.Position) + '%');
end;
Increment the progress bar position with Panel.Progress.StepIt to advance by one, or set Position directly from a progress callback.
Links and controls in panels
HTML panels (spsHTML) can host anchor links. Use standard <a href="...">
markup in the panel Text, then handle the status bar's anchor-click to react
to the link. The URLColor property on a panel sets the colour used to render
those links so they stand out against the panel background.
To embed a live control — a button, a combo box, a small indicator — rather than just formatted text, drop the control on the form and parent it to the status bar; the panel reserves its width and the control is positioned within it. This is useful for a "Cancel" button next to a progress panel or a quick-action combo in the corner of the bar.
Combining panel styles, progress tracking, and click events
Build a status bar with a resizable text panel, a live progress panel, and a clickable date panel. Note that OnPanelLeftClick reports the panel index, not the panel object — index into Panels to inspect the clicked panel.
{ Inside your form's OnCreate: }
procedure TForm1.FormCreate(Sender: TObject);
var
pText, pProg, pDate: TTMSFNCStatusBarPanel;
begin
TMSFNCStatusBar1.BeginUpdate;
try
// Auto-sizing text panel
pText := TMSFNCStatusBar1.Panels.Add;
pText.Style := spsHTML;
pText.AutoSize := True;
pText.Text := 'Ready';
// Progress panel - three colour thresholds
pProg := TMSFNCStatusBar1.Panels.Add;
pProg.Style := spsProgress;
pProg.Width := 120;
pProg.Progress.Min := 0;
pProg.Progress.Max := 100;
pProg.Progress.Position := 0;
// Clickable date panel
pDate := TMSFNCStatusBar1.Panels.Add;
pDate.Style := spsDate;
pDate.Width := 90;
pDate.Button := True;
finally
TMSFNCStatusBar1.EndUpdate;
end;
TMSFNCStatusBar1.OnPanelLeftClick := DoStatusPanelClick;
end;
// OnPanelLeftClick passes the panel INDEX, not the panel object.
procedure TForm1.DoStatusPanelClick(Sender: TObject; PanelIndex: Integer);
begin
if TMSFNCStatusBar1.Panels[PanelIndex].Style = spsDate then
ShowMessage('Date panel clicked: ' + DateToStr(Now));
end;
// Drive the progress panel and the text panel together from a worker callback.
procedure TForm1.SimulateProgress(APercent: Integer);
begin
TMSFNCStatusBar1.Panels[1].Progress.Position := APercent;
TMSFNCStatusBar1.Panels[0].Text := Format('Processing... %d%%', [APercent]);
end;
Wrap multi-panel construction in BeginUpdate/EndUpdate so the bar lays out and repaints once instead of after every Panels.Add.
High-DPI panel icons
When the display scale changes, the status bar rescales the metrics it owns:
PanelAppearance.Font, and for every panel already in the collection its
Width, MinWidth, and Offset. Those are therefore authored once at design
DPI. Panel images are not rescaled, because a spsImage or spsImageList
panel draws a bitmap from the shared BitmapContainer and a bitmap has a fixed
pixel count — an icon authored for a 100% display turns soft at 150% or 200%.
Read the status bar's ResourceScaleFactor (the display scale it resolves image
resources against) and fill the container with the matching asset set.
uses
System.SysUtils, FMX.TMSFNCUtils, FMX.TMSFNCBitmapContainer,
FMX.TMSFNCStatusBar;
procedure TForm1.LoadScaledStatusIcons;
var
Suffix: string;
Item: TTMSFNCBitmapItem;
Panel: TTMSFNCStatusBarPanel;
begin
{ ResourceScaleFactor is the display scale the status bar resolves image
resources against: 1.0 at 96 DPI, 1.5 at 144 DPI, 2.0 at 192 DPI. }
if TMSFNCStatusBar1.ResourceScaleFactor >= 2 then
Suffix := '@2x'
else if TMSFNCStatusBar1.ResourceScaleFactor >= 1.5 then
Suffix := '@1.5x'
else
Suffix := '';
TMSFNCBitmapContainer1.Items.Clear;
Item := TMSFNCBitmapContainer1.Items.Add;
Item.Name := 'connected';
Item.Bitmap.LoadFromFile('connected' + Suffix + '.png');
Item := TMSFNCBitmapContainer1.Items.Add;
Item.Name := 'syncing';
Item.Bitmap.LoadFromFile('syncing' + Suffix + '.png');
TMSFNCStatusBar1.BeginUpdate;
try
TMSFNCStatusBar1.BitmapContainer := TMSFNCBitmapContainer1;
{ Panel widths, MinWidth, Offset and PanelAppearance.Font stay in design
units - the status bar rescales those itself when the display scale
changes, and the artwork above supplies the extra pixels. }
Panel := TMSFNCStatusBar1.Panels.Add;
Panel.Style := spsImage;
Panel.ImageIndex := 0;
Panel.Text := 'Connected';
Panel.Width := 110;
Panel.MinWidth := 90;
finally
TMSFNCStatusBar1.EndUpdate;
end;
if TTMSFNCUtils.IsHighDPIScale(Self) then
TMSFNCStatusBar1.Panels.Items[0].Hint :=
Format('Icons loaded at %.2fx', [TTMSFNCUtils.GetDPIScale(Self)]);
end;
One ordering constraint follows from the rescale being per existing panel: panels added after a display-scale change are stored exactly as you assign them, so keep panel construction in a single routine that always uses design units instead of spreading width assignments across the form.
Common pitfalls
- Multiple
AutoSizepanels. Auto-sizing distributes the remaining width; giving more than one panelAutoSize := Truemakes their final widths hard to predict. Keep a single auto-sizing panel (usually the main text panel) and give the rest fixedWidthvalues. - Expecting a panel object in the click handler.
OnPanelLeftClick/OnPanelRightClickpassPanelIndex: Integer. ReadPanels[PanelIndex]to get the panel. - Clicks without
Button. A panel only raises click events when itsButtonproperty isTrue. Set it on every panel that should be interactive. - Rebuilding panels without
BeginUpdate. Adding or restyling several panels outside aBeginUpdate/EndUpdatepair causes repeated relayout and flicker.