Table of Contents

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.

LED bar widget with colored segments and custom drawing LED bar widget with colored segments and custom drawing

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. Set ADefaultDraw := False to suppress the built-in LED and draw your own; leave it True to 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 .Color sub-property on the item colors. Only the bar-level Fill/Stroke graphics objects use .Kind/.Color.
  • BaseColor overwrites OnColor and OffColor. Assign BaseColor first, then override OnColor/OffColor individually if you need a custom off shade — not the other way around.
  • Value resets every State. Setting the control's Value recomputes the lit/unlit state of all LEDs. If you toggle Leds[i].State by hand, do it after the last Value assignment, or it will be overwritten.
  • In OnBeforeDrawLed, forgetting to keep ADefaultDraw := True leaves the LED blank when you only meant to overlay — set it explicitly.

See also