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.

Activating a page

Set ActivePageIndex or assign ActivePage directly:

Pascal
TMSFNCPageControl1.ActivePageIndex := 1;
// or
TMSFNCPageControl1.ActivePage := TMSFNCPageControl1.Pages[1];

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

Reordering pages

Pascal
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:

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 TabAppearance.CloseButton = True).

Collapsible mode

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

Pascal
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:

Combining tab appearance with page eventsPascalC++
// 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
}

See also