Pages and navigation
TTMSFNCPageControl combines a tab strip with full-height page containers. Every TTMSFNCPageControlPage in the Pages collection owns a Container — a panel that fills the component area when that page is active. The tab strip behaviour (appearance, scrolling, close buttons, reordering) is inherited from TTMSFNCTabSet.
Adding and removing pages
At design time, right-click the component and choose New page or Remove page. At runtime:
var
Page: TTMSFNCPageControlPage;
Btn: TButton;
begin
TMSFNCPageControl1.BeginUpdate;
try
TMSFNCPageControl1.Pages.Clear;
Page := TMSFNCPageControl1.AddPage('Overview');
Btn := TButton.Create(Page.Container);
Btn.Parent := Page.Container;
Btn.Text := 'Click me';
TMSFNCPageControl1.AddPage('Details');
TMSFNCPageControl1.AddPage('Settings');
TMSFNCPageControl1.ActivePageIndex := 0;
finally
TMSFNCPageControl1.EndUpdate;
end;
end;
TTMSFNCPageControlPage *Page;
TButton *Btn;
TMSFNCPageControl1->BeginUpdate();
try
{
TMSFNCPageControl1->Pages->Clear();
Page = TMSFNCPageControl1->AddPage("Overview");
Btn = new TButton(Page->Container);
Btn->Parent = Page->Container;
Btn->Text = "Click me";
TMSFNCPageControl1->AddPage("Details");
TMSFNCPageControl1->AddPage("Settings");
TMSFNCPageControl1->ActivePageIndex = 0;
}
__finally
{
TMSFNCPageControl1->EndUpdate();
}
AddPage returns the new TTMSFNCPageControlPage. Access its Container to place controls inside the page.
Activating a page
Set ActivePageIndex or assign ActivePage directly:
TMSFNCPageControl1.ActivePageIndex := 1;
// or
TMSFNCPageControl1.ActivePage := TMSFNCPageControl1.Pages[1];
The previous page container is hidden and the new one shown immediately.
Reordering pages
TMSFNCPageControl1.MovePage(0, 2); // move first page to position 2
Page-change events
OnBeforeChangePage fires before the active page switches and lets you cancel the change. OnChangePage fires after the switch completes:
procedure TForm1.TMSFNCPageControl1BeforeChangePage(Sender: TObject;
ACurrentPageIndex, ANewPageIndex: Integer; var ACanChange: Boolean);
begin
// Prevent leaving the first page when validation fails
if (ACurrentPageIndex = 0) and not ValidateForm then
ACanChange := False;
end;
procedure TForm1.TMSFNCPageControl1ChangePage(Sender: TObject;
APreviousPageIndex, ACurrentPageIndex: Integer);
begin
Caption := Format('Page %d of %d', [ACurrentPageIndex + 1,
TMSFNCPageControl1.Pages.Count]);
end;
void __fastcall TForm1::TMSFNCPageControl1BeforeChangePage(TObject *Sender,
int ACurrentPageIndex, int ANewPageIndex, bool &ACanChange)
{
// Prevent leaving the first page when validation fails
if ((ACurrentPageIndex == 0) && !ValidateForm())
ACanChange = false;
}
void __fastcall TForm1::TMSFNCPageControl1ChangePage(TObject *Sender,
int APreviousPageIndex, int ACurrentPageIndex)
{
Caption = Format("Page %d of %d", ARRAYOFCONST((ACurrentPageIndex + 1,
TMSFNCPageControl1->Pages->Count)));
}
OnBeforeClosePage and OnClosePage fire when a tab's close button is clicked (requires TabAppearance.CloseButton = True).
Collapsible mode
Set Collapsed := True to hide all page containers while keeping the tab strip visible — useful for accordion-style layouts:
TMSFNCPageControl1.Collapsed := True;
Toggle it back with Collapsed := False to restore the active page.
Combining tab appearance with page events
The example below builds a page control with close buttons and cancels navigation away from an unsaved edit page:
// Setup: enable close buttons and page guards
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
Page: TTMSFNCPageControlPage;
begin
TMSFNCPageControl1.TabAppearance.CloseButton := True;
for I := 0 to 2 do
begin
Page := TMSFNCPageControl1.AddPage('Document ' + IntToStr(I + 1));
Page.Tag := 0; // 0 = clean, 1 = modified
end;
TMSFNCPageControl1.ActivePageIndex := 0;
end;
// Guard: block navigation away from a modified page
procedure TForm1.TMSFNCPageControl1BeforeChangePage(Sender: TObject;
ACurrentPageIndex, ANewPageIndex: Integer; var ACanChange: Boolean);
begin
if TMSFNCPageControl1.Pages[ACurrentPageIndex].Tag = 1 then
begin
if MessageDlg('Unsaved changes. Leave anyway?', TMsgDlgType.mtConfirmation,
[mbYes, mbNo], 0) <> mrYes then
ACanChange := False;
end;
end;
// Guard: confirm before closing a tab
procedure TForm1.TMSFNCPageControl1BeforeClosePage(Sender: TObject;
APageIndex: Integer;
var ACloseAction: TTMSFNCPageControlPageCloseAction);
begin
if MessageDlg('Close this document?', TMsgDlgType.mtConfirmation,
[mbYes, mbNo], 0) <> mrYes then
ACloseAction := pcaCancel;
end;
// Setup: enable close buttons and page guards (the close button is a per-page setting)
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TTMSFNCPageControlPage *Page;
for (int I = 0; I <= 2; I++)
{
Page = TMSFNCPageControl1->AddPage("Document " + IntToStr(I + 1));
Page->CloseButton = true;
Page->Tag = 0; // 0 = clean, 1 = modified
}
TMSFNCPageControl1->ActivePageIndex = 0;
}
// Guard: block navigation away from a modified page
void __fastcall TForm1::TMSFNCPageControl1BeforeChangePage(TObject *Sender,
int ACurrentPageIndex, int ANewPageIndex, bool &ACanChange)
{
if (TMSFNCPageControl1->Pages->Tabs[ACurrentPageIndex]->Tag == 1)
{
if (MessageDlg("Unsaved changes. Leave anyway?", System::Uitypes::TMsgDlgType::mtConfirmation,
TMsgDlgButtons() << System::Uitypes::TMsgDlgBtn::mbYes << System::Uitypes::TMsgDlgBtn::mbNo, 0) != mrYes)
ACanChange = false;
}
}
// Guard: confirm before closing a tab
void __fastcall TForm1::TMSFNCPageControl1BeforeClosePage(TObject *Sender,
int APageIndex, TTMSFNCPageControlPageCloseAction &ACloseAction)
{
if (MessageDlg("Close this document?", System::Uitypes::TMsgDlgType::mtConfirmation,
TMsgDlgButtons() << System::Uitypes::TMsgDlgBtn::mbYes << System::Uitypes::TMsgDlgBtn::mbNo, 0) != mrYes)
ACloseAction = Fmx::Tmsfncpagecontrol::ttcaNone; // ttcaNone keeps the page open
}