Coloring segments and custom drawing
Each LED in the bar carries its own colors, so the strip can do more than show a
single-color level: a green-amber-red layout turns the bar into a zoned meter that
signals safe, warning, and danger ranges at a glance. When the per-segment colors
are not enough — you want icons, labels, or fully bespoke shapes — the control
exposes before- and after-draw hooks for each LED. This chapter covers both: per
-segment coloring through the Leds items and custom rendering through the draw
events.
Per-segment colors
Every entry in the Leds collection is a TTMSFNCWidgetLEDBarItem with three
color properties and an explicit State:
| Property | Meaning |
|---|---|
OnColor |
Color drawn when the LED is lit. Defaults to red. |
OffColor |
Color drawn when the LED is unlit. Defaults to maroon. |
BaseColor |
Convenience setter: assigning it sets OnColor to the base color and OffColor to a darker variant. Defaults to red. |
State |
Whether this individual LED is lit. The control's Value sets this for you. |
These are direct TTMSFNCGraphicsColor values — write Led.OnColor := gcLime,
not Led.OnColor.Color := …. (The bar's own Fill and Stroke are graphics
objects with a .Kind/.Color, but the per-LED item colors are plain color
values.) Setting BaseColor is the quickest way to theme a zone, because it
derives a matching dimmed off-color automatically.
Custom draw hooks
Two hooks let you take over rendering for individual LEDs:
OnBeforeDrawLed(Sender, AGraphics, ARect, AIndex, var ADefaultDraw)fires before each LED is painted. SetADefaultDraw := Falseto suppress the built-in LED and draw your own; leave itTrueto keep the default and just overlay extra content.OnAfterDrawLed(Sender, AGraphics, ARect, AIndex)fires after the default LED is drawn, for overlays such as a tick mark or a label on top of the segment.
AGraphics is the drawing surface, ARect is the bounds of that LED, and
AIndex is its zero-based position in the bar.
Combining zones with a custom hook
The snippet below builds a green-amber-red meter through BaseColor, then wires
an OnBeforeDrawLed handler that keeps the default LED rendering and frames every
second segment — combining per-segment coloring with custom drawing on one bar.
procedure TForm1.StyleLEDBarZones;
var
I: Integer;
Led: TTMSFNCWidgetLEDBarItem;
begin
FBar.Leds.BeginUpdate;
try
for I := 0 to FBar.Leds.Count - 1 do
begin
Led := FBar.Leds[I];
// Item colors are direct TTMSFNCGraphicsColor values (not stroke objects).
if I < 6 then
Led.BaseColor := gcLime // sets OnColor and a darker OffColor
else if I < 8 then
Led.BaseColor := gcGold
else
Led.BaseColor := gcRed;
end;
finally
FBar.Leds.EndUpdate;
end;
// Combine zones with a custom draw hook for the lit/unlit split.
FBar.OnBeforeDrawLed := DoBeforeDrawLed;
FBar.Value := 7;
end;
procedure TForm1.DoBeforeDrawLed(Sender: TObject; AGraphics: TTMSFNCGraphics;
ARect: TRectF; AIndex: Integer; var ADefaultDraw: Boolean);
begin
// Keep the built-in LED rendering; only annotate every second segment.
ADefaultDraw := True;
if (AIndex mod 2 = 0) then
begin
AGraphics.Stroke.Kind := gskSolid;
AGraphics.Stroke.Color := gcSilver;
AGraphics.DrawRectangle(ARect);
end;
end;
Pitfalls
- Item colors are plain color values. Use
Led.OnColor := gcRed; there is no.Colorsub-property on the item colors. Only the bar-levelFill/Strokegraphics objects use.Kind/.Color. BaseColoroverwritesOnColorandOffColor. AssignBaseColorfirst, then overrideOnColor/OffColorindividually if you need a custom off shade — not the other way around.Valueresets everyState. Setting the control'sValuerecomputes the lit/unlit state of all LEDs. If you toggleLeds[i].Stateby hand, do it after the lastValueassignment, or it will be overwritten.- In
OnBeforeDrawLed, forgetting to keepADefaultDraw := Trueleaves the LED blank when you only meant to overlay — set it explicitly.