Skip to main content
Table of Contents

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:

Adding and removing pagesPascalC++
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.

Page control with Overview, Details and Settings pages; the active Overview page container hosts edits and a button Page control with Overview, Details and Settings pages; the active Overview page container hosts edits and a button

Activating a page

Set ActivePageIndex or assign ActivePage directly:

Inline example 1PascalC++
TMSFNCPageControl1.ActivePageIndex := 1;
// or
TMSFNCPageControl1.ActivePage := TMSFNCPageControl1.Pages[1];
TMSFNCPageControl1->ActivePageIndex = 1;
// Or select a page object directly.
TMSFNCPageControl1->ActivePage = TMSFNCPageControl1->Pages[1];

The previous page container is hidden and the new one shown immediately.

Reordering pages

Inline example 2PascalC++
TMSFNCPageControl1.MovePage(0, 2); // move first page to position 2
TMSFNCPageControl1->MovePage(0, 2);

Page-change events

OnBeforeChangePage fires before the active page switches and lets you cancel the change. OnChangePage fires after the switch completes:

Page-change eventsPascalC++
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 Options.CloseMode := tcmTab, which draws a close button on each tab, plus CloseButton = True on the page, which is the default).

Collapsible mode

Set Collapsed := True to hide all page containers while keeping the tab strip visible — useful for accordion-style layouts:

Inline example 3PascalC++
TMSFNCPageControl1.Collapsed := True;
TMSFNCPageControl1->Collapsed = true;

Toggle it back with Collapsed := False to restore the active page.

Collapsed page control showing only its tab strip above the form content Collapsed page control showing only its tab strip above the form content

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:

Combining tab appearance with page eventsPascalC++
// Setup: enable close buttons and page guards (Options.CloseMode draws the buttons, Page.CloseButton opts each page in)
procedure TForm1.FormCreate(Sender: TObject);
var
  I: Integer;
  Page: TTMSFNCPageControlPage;
begin
  TMSFNCPageControl1.Options.CloseMode := tcmTab;
  for I := 0 to 2 do
  begin
    Page := TMSFNCPageControl1.AddPage('Document ' + IntToStr(I + 1));
    Page.CloseButton := True;
    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,
        [TMsgDlgBtn.mbYes, TMsgDlgBtn.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,
      [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo], 0) <> mrYes then
    ACloseAction := ttcaNone; // ttcaNone keeps the page open
end;
// Setup: enable close buttons and page guards (Options->CloseMode draws the buttons, Page->CloseButton opts each page in)
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  TTMSFNCPageControlPage *Page;

  TMSFNCPageControl1->Options->CloseMode = tcmTab;
  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
}
Page control with three document tabs, each with a close button, and the second document active Page control with three document tabs, each with a close button, and the second document active

See also