Skip to content

Styled Buttons and Panels with VCL Styles Demo

Overview

In the first page of this demo shows a comprehensive side-by-side comparison of standard VCL buttons and TStyledButton across all installed VCL Styles, demonstrating how StyledComponents maintain consistent appearance regardless of the active VCL Style.

The second page shows a comprehensive side-by-side comparison of the standard VCL panels and TStyledPanel across all installed VCL styles, demonstrating how StyledComponents maintain a consistent look regardless of the active VCL style.

What You'll Learn

  • How TStyledButton renders independently of VCL Styles
  • Comparison with standard TButton across all VCL Styles
  • Different button styles (PushButton, SplitButton, CommandLink)
  • Creating hundreds of buttons dynamically
  • FAB (Floating Action Button) mode
  • TStyledPanel rendering with VCL Styles
  • Per-button VCL Style assignment (Delphi 10.4+)

Demo Layout

The demo has two main tabs:

1. Styled Buttons Tab

Styled Button VCL Styles Demo

Two side-by-side scrollable panels:

Left Panel: Standard VCL Buttons

  • One TButton for each installed VCL Style
  • Buttons use StyleName property (Delphi 10.4+)
  • Shows how each VCL Style affects standard buttons
  • Renders differently based on active style

Right Panel: TStyledButton

  • One TStyledButton for each VCL Style name
  • Uses StyleClass to identify each style
  • Consistent rendering regardless of active VCL Style
  • Modern, predictable appearance

2. Styled Panels Tab

Styled Panel VCL Styles Demo

Similar layout comparing:

  • Standard TPanel (left)
  • TStyledPanel (right)

Both with StyleName for each VCL Style.

Render Options

Same as VCL (AsVCLComponent)

pascal
StyledButton.AsVCLComponent := True;

Renders like standard VCL button (maintains VCL Style appearance).

Rounded Buttons

pascal
// All buttons with btRounded
RenderRadioGroup.ItemIndex := RENDER_ROUNDED;

Round Rectangle Buttons

pascal
// All buttons with btRoundRect
RenderRadioGroup.ItemIndex := RENDER_ROUNDRECT;

Rectangle Buttons

pascal
// All buttons with btRect
RenderRadioGroup.ItemIndex := RENDER_RECTANGLE;

FAB (Floating Action Buttons)

pascal
// Circular icon buttons
RenderRadioGroup.ItemIndex := RENDER_FAB;
Button.StyleDrawType := btEllipse;
Button.Images := ImageList;
Button.ImageAlignment := iaCenter;

Button Style Options

Push Button (bsPushButton)

Standard clickable button:

pascal
Button.Style := bsPushButton;

Split Button (bsSplitButton)

Button with dropdown menu:

pascal
Button.Style := bsSplitButton;
Button.DropDownMenu := PopupMenu1;

Button with main caption and hint:

pascal
Button.Style := bsCommandLink;
Button.Caption := 'Action';
Button.CommandLinkHint := 'Description of action...';

Command links are taller and include explanatory text.

Dynamic Button Creation

The demo creates buttons dynamically for all installed VCL Styles:

Get Available Styles

pascal
procedure BuildStyleList;
var
  I: integer;
begin
  FStyleNames := TStringList.Create;
  for I := 0 to High(TStyleManager.StyleNames) do
    FStyleNames.Add(TStyleManager.StyleNames[i]);
  FStyleNames.Sorted := True;
end;

Create VCL Buttons

pascal
procedure CreateVCLButton(AColumn, ATop: Integer; AStyleName: string);
var
  LButton: TButton;
begin
  LButton := TButton.Create(Self);
  LButton.SetBounds(AColumn * LWidth + MARGIN,
    ATop, LWidth, LHeight);
  LButton.Style := bsPushButton;  // or bsSplitButton, bsCommandLink
  {$IFDEF D10_4+}
  LButton.StyleName := AStyleName;  // Per-button style
  {$ENDIF}
  LButton.Caption := AStyleName;
  LButton.Parent := LeftScrollBox;
end;

Create Styled Buttons

pascal
procedure CreateStyledButton(AColumn, ATop: Integer; AStyleName: string);
var
  LButton: TStyledButton;
  LAsVcl: Boolean;
begin
  LAsVcl := RenderRadioGroup.ItemIndex = RENDER_SAME_AS_VCL;

  LButton := TStyledButton.CreateStyled(Self,
    DEFAULT_CLASSIC_FAMILY,
    AStyleName,  // Use style name as class
    DEFAULT_APPEARANCE,
    DEFAULT_STYLEDRAWTYPE,
    DEFAULT_CURSOR,
    not LAsVcl);  // AsVCLComponent parameter

  LButton.SetBounds(AColumn * LWidth + MARGIN,
    ATop, LWidth, LHeight);

  case RenderRadioGroup.ItemIndex of
    RENDER_ROUNDED: LButton.StyleDrawType := btRounded;
    RENDER_ROUNDRECT: LButton.StyleDrawType := btRoundRect;
    RENDER_RECTANGLE: LButton.StyleDrawType := btRect;
    RENDER_FAB:
    begin
      LButton.StyleDrawType := btEllipse;
      LButton.Images := ImageList;
      LButton.ImageAlignment := iaCenter;
      LButton.ImageIndex := I mod ImageList.Count;
    end;
  end;

  LButton.Caption := AStyleName;
  LButton.Parent := RightScrollBox;
end;

Layout Algorithm

Buttons are arranged in a grid:

pascal
LColumn := (I mod ButtonsInColumn);  // Column position
LRow := (I div ButtonsInColumn);     // Row position
Top := LRow * (ButtonHeight + MARGIN);
Left := LColumn * (ButtonWidth + MARGIN);

The number of columns adjusts based on panel width.

Responsive Resizing

The demo recalculates layout on resize:

pascal
procedure TfmStyledButtonVCLStyles.FormResize(Sender: TObject);
begin
  if LeftPanel.Width <> ClientWidth div 2 then
  begin
    LeftPanel.Width := ClientWidth div 2;
    CreateAllButtons(False);  // Rebuild layout
  end;
end;

Mouse Wheel Scrolling

Enhanced scrolling for large button lists:

pascal
procedure ScrollBoxMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
  msg, code: Cardinal;
  i, n: Integer;
begin
  Handled := True;
  if ssShift in Shift then
    msg := WM_HSCROLL
  else
    msg := WM_VSCROLL;

  if WheelDelta > 0 then
    code := SB_LINEUP
  else
    code := SB_LINEDOWN;

  n := Mouse.WheelScrollLines * 4;  // Speed up
  for i := 1 to n do
  begin
    LeftScrollBox.Perform(msg, code, 0);
    RightScrollBox.Perform(msg, code, 0);
  end;

  LeftScrollBox.Perform(msg, SB_ENDSCROLL, 0);
  RightScrollBox.Perform(msg, SB_ENDSCROLL, 0);
end;

VCL Styles Comparison

The demo shows how each VCL Style affects rendering:

Standard TButton

  • Appearance changes with active VCL Style
  • Each button can have StyleName (10.4+)
  • Inconsistent across styles
  • Limited customization

TStyledButton

  • Consistent appearance across all VCL Styles
  • Independent rendering (GDI+)
  • Full customization options
  • Modern, predictable look

Key Observations

1. Independence from VCL Styles

TStyledButton renders the same regardless of:

  • Active VCL Style
  • Windows theme
  • System colors

2. Per-Button Styling (Delphi 10.4+)

Standard TButton can use StyleName:

pascal
Button1.StyleName := 'Windows10 Blue';
Button2.StyleName := 'Glow';

But still limited compared to TStyledButton customization.

3. AsVCLComponent Property

When set to True, TStyledButton mimics VCL rendering:

pascal
StyledButton.AsVCLComponent := True;

Useful for gradual migration or hybrid interfaces.

Styled Panels Comparison

The second tab shows TStyledPanel vs. TPanel:

Standard TPanel

  • Uses VCL Style colors
  • Requires ParentBackground := False for styling
  • Appearance varies by style

TStyledPanel

  • Consistent styled rendering
  • Independent of VCL Styles
  • Full customization options

Interactive Controls

For Buttons

  • Render Options: Same as VCL, Rounded, RoundRect, Rectangle, FAB
  • Style Options: PushButton, SplitButton, CommandLink
  • Enabled Checkbox: Enable/disable all buttons
  • Outline Checkbox: Use outline appearance

For Panels

  • Render Options: Same as VCL, Rounded, RoundRect, Rectangle
  • Show Caption: Toggle panel captions
  • Outline Checkbox: Use outline appearance

Performance

The demo creates hundreds of buttons:

  • ~50+ VCL Styles × 2 = 100+ buttons total
  • Dynamic creation/destruction
  • Efficient layout calculation
  • Smooth scrolling

Use Cases

1. Style Independence

Applications that must look the same regardless of VCL Style.

2. Custom Branding

Corporate colors and styles that don't match any VCL Style.

3. Modern UI

Web-like or Material Design interfaces.

4. Consistent Multi-Platform

Same look across different Windows versions.

Technical Details

Source Location

Demos/source/StyledButtonVCLStylesForm.pas

Supported Versions

  • All Delphi versions (XE6+)
  • Per-button StyleName requires Delphi 10.4+

Key Constants

pascal
const
  RENDER_SAME_AS_VCL = 0;
  RENDER_ROUNDED = 1;
  RENDER_ROUNDRECT = 2;
  RENDER_RECTANGLE = 3;
  RENDER_FAB = 4;

  STYLE_PUSHBUTTON = 0;
  STYLE_SPLITBUTTON = 1;
  STYLE_COMMANDLINK = 2;

Button Sizing

  • Width: 150px (180px for CommandLinks)
  • Height: 28px (68px for CommandLinks)
  • Margin: 4px
  • FAB: 56x56px

Best Practices

1. Consistent Rendering

Use TStyledButton when you need:

  • Same look across VCL Styles
  • Custom branding
  • Modern appearance

2. VCL Compatibility

Use AsVCLComponent := True when:

  • Migrating gradually
  • Need VCL Style integration
  • Hybrid interfaces

3. Performance

For large button counts:

  • Create dynamically
  • Use flow panels
  • Implement virtual scrolling

See Also

Released under Apache License, Version 2.0.