Skip to content

TTMSFNCTabSet / TTMSFNCPageControl

TTMSFNCUIPack51

Properties

Property name Description
ActivePageIndex/ActiveTabIndex Property to get or set the active page/tab
BitmapContainer Property to assign a TTMSFNCBitmapContainer instance in order to retrieve bitmaps via a name.
ButtonsAppearance Appearance of the scroll, insert and close buttons in the menu.
Fill The background fill appearance of the tabset/pagecontrol.
Interaction Various properties to control interaction with the tabset/pagecontrol.
Layout Properties to change the layout of the tabset/pagecontrol.
Options Additional options to configure the look and feel of the tabset/pagecontrol.
Stroke The stroke of the background of the TabSet/PageControl.
TabAppearance The global tab appearance applied to each tab with UseDefaultAppearance set to True.
Tabs A collection used to add / remove new or existing tabs / pages.
TabSize Options to specify the size of the tabs.

Methods

Method name Description
AddTab / AddPage Adds a new tab / page
CancelEditing Cancels editing if editing is active.
CloseInplaceEditor Closes the inplace editor if editing is active and applies updates the tab text value or cancels the changes
FindNextTab Returns the next tab based on the tab index.
FindPreviousTab Returns the previous tab based on the tab index.
FocusNextTab Focuses the next tab based on the tab index.
FocusPreviousTab Focuses the previous tab based on the tab index.
FocusTab Focuses a specify tab.
InsertTab / InsertPage Inserts a new tab / page
IsEditing Returns a boolean if editing is active.
IsTabEnabled Returns a boolean if a tab is enabled.
IsTabVisible Returns a boolean if a tab is visible.
MoveTab / MovePage Moves a tab to a new index.
RemoveTab / RemovePage Removes an existing tab / page.
ScrollToTab Scrolls to a specific tab.
SelectNextTab Selects the next tab.
SelectPreviousTab Selects the previous tab.
SelectTab Selects a specific tab.
StopEditing Stops editing and applies the changes to the tab.
XYToCloseButton Returns the menu close button at a specific X/Y coordinate.
XYToCloseTab Returns the tab close indicator at a specific X/Y coordinate.
XYToInsertButton Returns the menu insert button at a specific X/Y coordinate.
XYToScrollNextButton Returns the menu scroll next button at a specific X/Y coordinate.
XYToScrollPreviousButton Returns the menu scroll previous button at a specific X/Y coordinate.
XYToTab Returns the tab at a specific X/Y coordinate.
XYToTabListButton Returns the menu tab list button at a specific X/Y coordinate.

Events

Event name Description
OnAchorTabClick Event called when an anchor is clicked at a specific tab.
OnAfterDrawMenuButton Event called after the menu button is drawn.
OnAfterDrawTabBackground Event called after the background of the tab is drawn.
OnAfterDrawTabBadge Event called after the badge of the tab is drawn.
OnAfterDrawTabBitmap Event called after the bitmap of a tab is drawn.
OnAfterDrawTabCloseButton Event called after the close button of a tab is drawn.
OnAfterDrawTabProgress Event called after the progress of a tab is drawn.
OnAfterDrawTabText Event called after the text of a tab is drawn.
OnBeforeChangeTab Event called before the active tab will change.
OnBeforeCloseTab Event called before a tab will be closed.
OnBeforeDrawMenuButton Event called before the menu button is drawn.
OnBeforeDrawTabBadge Event called before the badge of a tab is drawn.
OnBeforeDrawTabBitmap Event called before the bitmap of a tab is drawn.
OnBeforeDrawTabCloseButton Event called before the close button of a tab is drawn.
OnBeforeDrawTabProgress Event called before the progress indication of a tab is drawn.
OnBeforeDrawTabText Event called before the text of a tab is drawn.
OnBeforeInsertTab Event called before a new tab is inserted.
OnBeforeOpenInplaceEditor Event called before the inplace editor is opened.
OnBeforeReorderTab Event called before the tab is reordered.
OnBeforeUpdateTab Event called before the tab is updated with the new value after editing.
OnChangeTab Event called after the active tab has changed.
OnCloseInplaceEditor Event called after the inplace editor is closed.
OnCloseTab Event called after the tab is closed.
OnCustomizeInplaceEditor Event called to customize the inplace editor.
OnGetInplaceEditor Event called to get a custom inplace editor class
OnGetInplaceEditorRect Event called to get the inplace editor rectangle.
OnInsertTab Event called after a new tab is inserted.
OnOpenInplaceEditor Event called after the inplace editor is opened.
OnReorderTab Event called after a tab is reordered.
OnUpdateTab Event called after a tab is updated via editing.

Adding new tabs

By default the TabSet is initialized with three tabs. Adding new tabs can be done by using The tabs collection directly or by using the helper methods as demonstrated below.

TMSFNCTabSet1.Tabs.Clear;
TMSFNCTabSet1.AddTab('New Tab');
TTMSFNCUIPack52

Removing tabs

To remove an existing tab, you can use the tabs collection directly or use the RemoveTab helper method as demonstrated below.

TMSFNCTabSet1.RemoveTab(0);
Before

TTMSFNCUIPack53

After

TTMSFNCUIPack54

Moving tabs

To move a tab to a different location, changing the index of the tab collection item is sufficient, or you can also use the MoveTab method as demonstrated below. You might notice here that the ActiveTabIndex is set to the new index. The MoveTab automatically changes the ActiveTabIndex.

TMSFNCTabSet1.MoveTab(0, 1);
Before

TTMSFNCUIPack55

After

TTMSFNCUIPack56

Modes

The TabSet supports different modes to display tabs. The mode can be change with the TabSize.Mode property. Below is a description of each mode.

  • tsmAutoSize Automatically resizes / stretches all tabs to fit in the available size of the TabSet. No scrolling capabilities as each tab will be displayed.

TTMSFNCUIPack57

  • tsmFixedSize Sets a fixed width on the tab. Scrolling is available if the amount of tabs that need to be displayed exceed the available size of the TabSet. The default width is 100.

TTMSFNCUIPack58

  • tsmFixedSize Sets a fixed width on the tab. Scrolling is available if the amount of tabs that need to be displayed exceed the available size of the TabSet. The default width is 100.

TTMSFNCUIPack59

  • tsmFixedSizeAutoShrink Sets a fixed width on the tab. When the amount of tabs is going to exceed the available size of the TabSet, the tabs are automatically resized to fit the available size of the TabSet. No scrolling capabilities as each tab will be displayed.

TTMSFNCUIPack60

Position

The TabSet supports 4 positions, changing the position is done with the Layout.Position property. Each tab can handle rotation for non-HTML formatted text. HTML formatted text is shown horizontally in case the tab is rotated 90 degrees. The rotation angle is fixed depending on the tab position. The default position is tlpTop. Alternative values to control the position are tlpLeft, tlpRight and tlpBottom as shown in the configuration below

TTMSFNCUIPack61

Appearance

Each tab has different states (normal, hover, down active and disabled). Each state is represented with a fill and a stroke under TabAppearance. When the UseDefaultAppearance property is set to False, the properties under each tab are applied to allow changing the appearance of a single tab. Each tab has a color for the background and text for each state. By default the UseDefaultAppearance property is set to False. Below is a sample to indicate the difference between the states and the purpose of the UseDefaultAppearance property.

var
 I: Integer;
begin
 TMSFNCTabSet1.TabAppearance.Fill.Color := gcLightcoral;
 TMSFNCTabSet1.TabAppearance.ActiveFill.Color := gcCrimson;
 TMSFNCTabSet1.TabAppearance.TextColor := gcWhitesmoke;
 TMSFNCTabSet1.TabAppearance.ActiveTextColor := gcWhite;
 for I := 0 to TMSFNCTabSet1.Tabs.Count - 1 do
 begin
 TMSFNCTabSet1.Tabs[I].Color := gcSteelBlue;
 TMSFNCTabSet1.Tabs[I].ActiveColor := gcLightsteelblue;
 TMSFNCTabSet1.Tabs[I].TextColor := gcWhite;
 TMSFNCTabSet1.Tabs[I].ActiveTextColor := gcDarkblue;
 end;
end;

TTMSFNCUIPack62

In the above code, you notice that the tabs are responsible for the actual appearance. Note that the UseDefaultAppearance is set to False by design, which allows to further customize the appearance of each tab separately. If we would set the UseDefaultAppearance property to True, the appearance would change and take on the properties from the global TabAppearance as demonstrated in the following sample.

var
 I: Integer;
begin
 TMSFNCTabSet1.TabAppearance.Fill.Color := gcLightcoral;
 TMSFNCTabSet1.TabAppearance.ActiveFill.Color := gcCrimson;
 TMSFNCTabSet1.TabAppearance.TextColor := gcWhitesmoke;
 TMSFNCTabSet1.TabAppearance.ActiveTextColor := gcWhite;
 for I := 0 to TMSFNCTabSet1.Tabs.Count - 1 do
 begin
 TMSFNCTabSet1.Tabs[I].Color := gcSteelBlue;
 TMSFNCTabSet1.Tabs[I].ActiveColor := gcLightsteelblue;
 TMSFNCTabSet1.Tabs[I].TextColor := gcWhite;
 TMSFNCTabSet1.Tabs[I].ActiveTextColor := gcDarkblue;
 TMSFNCTabSet1.Tabs[I].UseDefaultAppearance := True;
 end;
end;

TTMSFNCUIPack63

Interaction

The TabSet supports interaction in various ways, through the mouse and keyboard. By default, clicking on a tab will set the active tab and show an optional focus indication. The home, end and arrow keys can be used to navigate through the different tabs. When Interaction.CloseTabWithKeyboard and Interaction.InsertTabWithKeyboard is true, the TabSet destroys or hides (depending on Options.CloseAction) the tab with the Delete key and inserts a new tab with the insert key. Pressing the F2 or Return key on the keyboard will start editing when Interaction.Editing is true.

When the mode is set to tsmFixedSize, tsmAutoTabSize and the amount of tabs exceed the available size of the TabSet, scroll buttons appear to allow scrolling through the tabs. By default, the scroll buttons will change the active tab but when Interaction.SelectTabScroll is set to False, the scroll buttons will only navigate through the tabs by changing the focused tab. To make the focused tab active, the Space or Return key can be used.

Inserting tabs via the tab insert button

New tabs can be inserted programmatically, but also via user interaction. When setting the Options.InsertMode to timTab a new special insert tab appears.

TTMSFNCUIPack64

Clicking on this tab will insert a new tab and via the OnBeforeInsertTab the index can be set at which position the tab needs to be inserted. By default this is always at the last position. Optionally, the insert tab button can be changed to a menu button via the timMenu option. This button has the same purpose but it stays visible inside the menu instead of as an additional special tab.

Closing tabs via the tab close button

Tabs can be removed / closed programmatically via the free action or setting the visible property to false, but can also be closed via a tab or menu close button. Setting the Options.CloseMode to tcmTab will show an additional close button at each tab. Clicking the close button will destroy or hide the tab depending on the Options.CloseAction. In case the Options.CloseAction is ttcaFree the tab will be destroyed. In case the Options.CloseAction is ttcaHide, the tab visible propery will be set to False and the tab will be displayed in the separate invisible tab list, available when the Options.TabListButton is set to true.

TTMSFNCUIPack65

Reorder

Reordering can be enabled by setting the Interaction.Reorder property to true. When pressing the finger/left-mouse button on a tab and dragging left or right, up or down depending on the position, the tab will detach from its current position and will navigate the to where the finger/left-mouse button is currently located. When releasing the finger/left-mouse button the new tab position is detected and the tab will move to the new location. Events can determine if a tab can be moved or moved to (OnBeforeReorderTab & OnReorderTab).

TMSFNCTabSet1.Interaction.Reorder := True; 

TTMSFNCUIPack66

Editing

Editing can be enabled by setting the Interaction.Editing property to true. When selecting a tab, pressing the F2 or clicking on the text area will start editing and show the default inplace editor (TEdit). The event OnBeforeOpenInplaceEditor is called to determine if a tab can be edited. The editor class itself can be changed to support custom inplace editors (demonstrated in a separate sample) and the editor class is retrieved via the OnGetInplaceEditor event. Before the editing is shown, but after the event that is called to determine if a tab can be edited the editor is further customized via the optional OnCustomizeInplaceEditor event. By default, the text rectangle is used as coördinates for the inplace editor, but this can also be customized via the OnGetInplaceEditorRect. After the inplace editor is configured and approved, the OnAfterOpenInplaceEditor is called. In this event, the Parent of the inplace editor is already set.

TMSFNCTabSet1.Interaction.Editing := True;

TTMSFNCUIPack67

After editing is done, pressing the Return or F2 will apply changes in the inplace editor. The OnCloseInplaceEditor event is called which will contain parameters to control the text that is being applied to the tab. After optionally changing the value, the OnBeforeUpdateTab and OnUpdateTab event are called. The OnBeforeUpdateTab can be used to specify if a tab can be updated.

When pressing the Escape key, The OnCloseInplaceEditor is called with different parameters and the changes are cancelled. Custom inplace editor

As mentioned, the TabSet supports editing via a custom inplace editor. In this sample, we create, customize and use a TComboBox as inplace editor. The code below demonstrates this behavior.

procedure TForm1.FormCreate(Sender: TObject);
begin
 TMSFNCTabSet1.Interaction.Editing := True;
 TMSFNCTabSet1.TabSize.Mode := tsmFixedSize;
 TMSFNCTabSet1.TabSize.Width := 120;
 TMSFNCTabSet1.Width := 400;
end;

procedure TForm1.TMSFNCTabSet1CustomizeInplaceEditor(Sender: TObject;
 ATabIndex: Integer; AInplaceEditor: TControl);
var
 cbo: TComboBox;
begin
 cbo := (AInplaceEditor as TComboBox);
 cbo.Items.Add('Audi');
 cbo.Items.Add('BMW');
 cbo.Items.Add('Mercedes');
 cbo.ItemIndex := cbo.Items.IndexOf(TMSFNCTabSet1.Tabs[0].Text);
end;

procedure TForm1.TMSFNCTabSet1GetInplaceEditor(Sender: TObject;
 ATabIndex: Integer; var AInplaceEditorClass: TTMSFNCTabSetInplaceEditorClass);
begin
 AInplaceEditorClass := TComboBox;
end;

TTMSFNCUIPack68

Progress indication

Each tab has the ability to show progress, in the form of a rectangular or circular progress indicator. The Progress and ProgressMax properties determine the visual representation. By default, the ProgressMax property is 100.

TMSFNCTabSet1.Tabs[0].ProgressKind := tpkRectangular;
TMSFNCTabSet1.Tabs[0].Progress := 50;
TMSFNCTabSet1.Tabs[0].ProgressKind := tpkCircular;
TMSFNCTabSet1.Tabs[0].Progress := 50;

TTMSFNCUIPack69

Optionally, the progress indicator can also be configured in marquee mode with the ProgressMode property. The progress indicator will, independent of the ProgressKind property setting, continuously indicate a busy operation. The ProgressColor property is used to further customize the appearance of the progress indicator for each tab separately.

Badges

Each tab can show a badge, which is placed in the upper right corner relative to its position. To show a badge, enter a value for the Badge property at a specific tab.

TMSFNCTabSet1.Tabs[0].Badge := ‘Hello’;

TTMSFNCUIPack71

Custom drawing

Each element in the TabSet can be customized via the TabAppearance or ButtonAppearance properties. When the UseDefaultAppearance property on tab level is set to False, further customizations can be applied using the color and text color properties for each state. Even if these customizations are not sufficient, the TabSet exposes a set of events for custom drawing. Below is a sample that demonstrates this.

In this sample we took the badge sample from the previous chapter, we draw a rectangle instead of a rounded rectangle, and change the font name and color.

TMSFNCTabSet1.Tabs[0].Badge := ‘Hello’;
procedure TForm1.TMSFNCTabSet1BeforeDrawTabBadge(Sender: TObject;
 AGraphics: TTMSFNCGraphics; ATabIndex: Integer; ARect: TRectF; AText: string;
 var ADefaultDraw: Boolean);
begin
 ADefaultDraw := False;
 AGraphics.DrawRectangle(ARect);
 AGraphics.Font.Color := gcWhite;
 AGraphics.Font.Name := 'Comic Sans MS';
 AGraphics.DrawText(ARect, AText, False, gtaCenter);
end;

TTMSFNCUIPack72

The next sample is customization of the close button. The close button is custom drawn, but it might be useful to show a close button icon instead. Implementing the OnBeforeDrawTabCloseButton will help you with this.

procedure TForm1.FormCreate(Sender: TObject);
begin
 TMSFNCTabSet1.Options.CloseMode := tcmTab;
 TMSFNCTabSet1.TabAppearance.CloseSize := 20;
end;
procedure TForm1.TMSFNCTabSet1BeforeDrawTabCloseButton(Sender: TObject;
 AGraphics: TTMSFNCGraphics; ATabIndex: Integer; ARect: TRectF;
 AState: TTMSFNCTabSetButtonState; var ADefaultDraw: Boolean);
begin
 ADefaultDraw := False;
 AGraphics.DrawBitmap(ARect, TMSFNCBitmapContainer1.FindBitmap('close'));
end;
TTMSFNCUIPack73

Note that in this sample, the close bitmap is actually the same bitmap for each state, but when a separate bitmap for each state is preferrable then this can be handled easily via the AState parameter.

PageControl

The PageControl inherits from the TabSet and adds the ability to show pages that act as a container for other controls. There is a separate Pages property that inherits from the Tabs collection and exposes PageControl specific event handlers. Except for the page containers there is no difference in properties and appearance, so all the above code is also valid for the PageControl.

Performance

The TabSet/PageControl is optimized for handling a large amount of tabs/pages. When the amount of tabs/pages are less than or equal to 10 then you can safely use the code above as-is. If the amount of tabs/pages exceed this number it is recommended to wrap the code with a BeginUpdate/EndUpdate code block. This block bundles all recalculate and repaint instructions in to one call and makes sure that adding 1000 tabs do not result in a time and resource consuming task.

TMSFNCTabSet1.BeginUpdate;
for I := 1 to 1000 do
 TMSFNCTabSet1.Tabs.Add;
TMSFNCTabSet1.EndUpdate;