TTMSFNCTabSet / TTMSFNCPageControl
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.

Removing tabs
To remove an existing tab, you can use the tabs collection directly or use the RemoveTab helper method as demonstrated below.
BeforeAfter
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.
BeforeAfter
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.
- 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.
- 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.
- 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.
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
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;
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;
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.
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.
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).
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.
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;
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.
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.
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;
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;

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.