You have a C++ builder application, with some complex forms, and you’d like them to properly react to window resizing.
You heavily used anchors and alignment, but reached the limits of these features. For example, as soon as you have 3 controls in a row and that your form is resized, you can’t get them to grow proportionaly. If some controls must sometimes be hidden, you can’t get their neighbours to automatically shift to fill the holes.
Dealing with these situations manually is painful and costly, you miss Java layouts.
There’s no builtin features solving these problems in older versions of C+ Builder (<= 6), but you might find helpful my GitHub CppBuilderFormLayoutDemo project, which contains a couple of classes inspired from Java Layout Managers, along with a C++ Builder 6 demo project.
The code can be downloaded here. The main layout managers classes are :
- TGridLayout (h / cpp) : splits the form area in rows and columns
- TStackLayout (h / cpp) : horizontal or vertical stack of controls. If a control is not visible, its next neigbour fills the hole.
The demo project main form looks like :
Most of the code is in the contructor of the form, where the layout dimensions and managed controls are initialized :
[code lang=cpp]
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner), mainLayout(MainPanel, 3, 3), statusLayout(StatusPanel)
{
// Configuring main layout
mainLayout.ColDef(0)->SetMinWidth(200); // Column 0 must be at least 200 pixels wide
mainLayout.ColDef(1)->SetFixedWidth(100); // Column 1 is always 100 pixels wide
mainLayout.RowDef(0)->SetMinHeight(100); // Row 0 is at least 100 pixels high
mainLayout.RowDef(1)->SetFixedHeight(50); // Row 1 is at always 50 pixels high
mainLayout.SetControl(0, 0, Panel1); // Panel1 is in cell [0, 0]
mainLayout.MergeCells(0, 0, 1, 0); // Cells [0, 0] and [1, 0] are merged together
mainLayout.SetControl(1, 0, Panel2); // Panel2 is in cell [1, 0]
mainLayout.SetControl(2, 0, Panel3);
mainLayout.SetControl(0, 1, Panel4);
mainLayout.SetControl(1, 1, Panel5);
mainLayout.SetControl(2, 1, Panel6);
mainLayout.SetControl(0, 2, Panel7);
mainLayout.SetControl(1, 2, Panel8);
mainLayout.SetControl(2, 2, Panel9);
// configuring status layout
statusLayout.Controls().push_back(ButtonA);
statusLayout.Controls().push_back(ButtonB);
statusLayout.Controls().push_back(ButtonC);
statusLayout.SetAlignment(TStackLayout::RIGHT);
statusLayout.SetOrientation(TStackLayout::HORIZONTAL);
mainLayout.Align();
statusLayout.Align();
}
[/code]
The layout is updated in the OnResize event :
[code lang=cpp]
void __fastcall TForm1::FormResize(TObject *Sender)
{
mainLayout.Align();
statusLayout.Align();
}
[/code]
The TStackLayout is also updated when the visibility of a control is changed, to properly stack the remaining visible controls :
[code lang=cpp]
void __fastcall TForm1::ButtonCClick(TObject *Sender)
{
ButtonB->Visible = !ButtonB->Visible;
ButtonC->Caption = ButtonB->Visible ? “Hide B” : “Show B”;
statusLayout.Align();
}
[/code]
Hi!
I recently started using C++Builder 10.1.
Is there still no built in automatic layout system?
You are implying there is, but I’ve found no good documentation about them.
Hi Mikko,
I wrote there’s no builtin form layout manager in C++ Builder versions <= 6 because I didn't work with more recent versions... I would expect Borland/Inprise/Embarcadero or whoever owns C++ Builder now to have added this feature since, but I honestly don't have a clue. Sorry for the false hope, and good luck with your project.