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.
Most of the code is in the contructor of the form, where the layout dimensions and managed controls are initialized :
__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
The layout is updated in the OnResize event :
void __fastcall TForm1::FormResize(TObject *Sender)
The TStackLayout is also updated when the visibility of a control is changed, to properly stack the remaining visible controls :
void __fastcall TForm1::ButtonCClick(TObject *Sender)
ButtonB->Visible = !ButtonB->Visible;
ButtonC->Caption = ButtonB->Visible ? “Hide B” : “Show B”;