Recent

Author Topic: [solved] How to arrange tabs of a TPageControl  (Read 2144 times)

Muso

  • Sr. Member
  • ****
  • Posts: 362
[solved] How to arrange tabs of a TPageControl
« on: August 18, 2025, 02:26:56 pm »
I use Lazarus 4.2 and I have a TPageControl. I use its option "nboMultiLine".
By default there is one tab in the first line and the 3 others in the second line see the attached PNG.
(by the way, how can one insert images inline to a forum post?)
But I want to have 4 tabs and each 2 of them should be in a line of tabs.
I only get this when I decrease the width of the TPageControl, see the attached GIF.But I want to keep the width of the TPageControl because as it works with fewer width it should work also with more available width. But I can#t find out how this is done.
« Last Edit: August 18, 2025, 10:49:32 pm by Muso »

Zvoni

  • Hero Member
  • *****
  • Posts: 3230
Re: How to arrange tabs of a TPageControl
« Reply #1 on: August 18, 2025, 02:46:56 pm »
IIRC, the Multiline-Property/Option has to do with multilined CAPTIONS of the Tabs, not how many Tabs are on the Control in how many lines
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12019
  • Debugger - SynEdit - and more
    • wiki
Re: How to arrange tabs of a TPageControl
« Reply #2 on: August 18, 2025, 03:05:53 pm »
Afaik (but not checked) the nboMultiline flag is simple send to the OS (at least on Windows), and the OS then decides how it wraps the tabs.

I would expect other OS/WS (if they support multiline at all) to also control that by the OS/WS (and not in the LCL).

If you want to control it yourself, you may need a custom drawn component. Or have 2 individual TTabControls, but then there would be no auto wrap at all.

Zvoni

  • Hero Member
  • *****
  • Posts: 3230
Re: How to arrange tabs of a TPageControl
« Reply #3 on: August 18, 2025, 03:11:26 pm »
Afaik (but not checked) the nboMultiline flag is simple send to the OS (at least on Windows), and the OS then decides how it wraps the tabs.

https://lazarus-ccr.sourceforge.io/docs/lcl/comctrls/tcustomtabcontrol.options.html

Quote
nboMultiLine
    Enables word wrapped or multi-line captions on tabs. Used to read or write the value for the MultiLine property.
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Muso

  • Sr. Member
  • ****
  • Posts: 362
Re: How to arrange tabs of a TPageControl
« Reply #4 on: August 18, 2025, 03:40:41 pm »
IIRC, the Multiline-Property/Option has to do with multilined CAPTIONS of the Tabs, not how many Tabs are on the Control in how many lines
For me "MultiLine" or "nboMulitLine" are always set to the same value. And this option decided how many tab line I get:

wp

  • Hero Member
  • *****
  • Posts: 13334
Re: How to arrange tabs of a TPageControl
« Reply #5 on: August 18, 2025, 06:20:45 pm »
Two solutions:

By default the width of a tab is determined by the length of the caption. By using the TabWidth property it can be adjusted to any width. The trick here is to adjust the TabWidth such that it stretches over half of the ClientWidth of the parent - this way the PageControl can accomodate only two tabs per row and then must wrap the next tabs into the next row (provided that the Multiline options is active). When you put this code into the OnResize event handler of the PageControl's parent, this layout of two tabs per row will be independent of the pagecontrol's Width:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormResize(Sender: TObject);  // For PageControl directly on the form
  2. begin
  3.   PageControl1.TabWidth := (ClientWidth - 10) div 2;  // 10 subtracted for some unknown margins
  4. end;
A disadvantage is that multi-lined Pagecontrol are not supported in all widgetsets...

Another solution combines some controls to a "faked" pagecontrol - well, you will have to accept something which does not look exactly like a TPageControl, but it serves the same purpose:
  • Drop a panel on the form (or the parent which will contain the pagecontrol). Select Align = alTop.
  • Drop four speedbuttons on this panel, place them anywhere
  • Go to property "ChildSizing" of the panel, set its "Layout" to "cclLeftToRightThenTopToBottom" and "ControlsPerLine" to 2 - now the speedbuttons are arranged nicely in two rows.
  • Drop a TNotebook on the form (or the parent of the "faked" pagecontrol). Set Align = alClient. Like a TPageControl, a TNotebook can have several pages, but there are no tabs. Therefore, you need the Speedbuttons - they serve as tabs...
  • Right-click on the TNotebook and add four pages - you will not see the pages in the designer form, but in the object tree. For adding controls to each page, select it first in the object tree.
  • Now return to the speedbuttons and specifiy in the "Tab" "Tag" property the index of the notebook page associated with the button.
  • Write the following handler and assign it to each speedbutton's OnClick event:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.SpeedButton1Click(Sender: TObject);
  2. begin
  3.   Notebook1.PageIndex := (Sender as TSpeedButton).Tag;
  4. end;

To give you idea what this looks like I am attaching a simple dummy project with both solutions.
« Last Edit: August 19, 2025, 11:37:18 am by wp »

Muso

  • Sr. Member
  • ****
  • Posts: 362
Re: How to arrange tabs of a TPageControl
« Reply #6 on: August 18, 2025, 07:30:14 pm »
By default the width of a tab is determined by the length of the caption. By using the TabWidth property it can be adjusted to any width. The trick here is to adjust the TabWidth such that it stretches over half of the ClientWidth of the parent - this way the PageControl can accomodate only two tabs per row and then must wrap the next tabs into the next row (provided that the Multiline options is active)...

many thanks! This works well (I only need it for LCL under Windows).

However, I found this way a bug: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/41801

n7800

  • Hero Member
  • *****
  • Posts: 594
  • Lazarus IDE contributor
    • GitLab profile
Re: How to arrange tabs of a TPageControl
« Reply #7 on: August 18, 2025, 10:29:32 pm »
    • Now return to the speedbuttons and specifiy in the "Tab" property the index of the notebook page associated with the button.
    • Write the following handler and assign it to each speedbutton's OnClick event:
    Code: Pascal  [Select][+][-]
    1. procedure TForm1.SpeedButton1Click(Sender: TObject);
    2. begin
    3.   Notebook1.PageIndex := (Sender as TSpeedButton).Tag;
    4. end;

    @wp, I think you meant to write "Tag" and not "Tab"?

    wp

    • Hero Member
    • *****
    • Posts: 13334
    Re: [solved] How to arrange tabs of a TPageControl
    « Reply #8 on: August 18, 2025, 10:57:03 pm »
    Yes, of course.

    n7800

    • Hero Member
    • *****
    • Posts: 594
    • Lazarus IDE contributor
      • GitLab profile
    Re: [solved] How to arrange tabs of a TPageControl
    « Reply #9 on: August 19, 2025, 01:14:08 am »
    Then maybe edit the post? I'm sure someone else will find this thread and want to use this method.

    EDITED: Thanks )
    « Last Edit: August 20, 2025, 08:18:54 am by n7800 »

     

    TinyPortal © 2005-2018