I searched a lot in google to get a clearer info on how I could solve my current issue, but I got scalability of components as the best answer, that's... not yet my issue.
So, long story short: I want to realign components on my form after the user resizes the window, the form is populated dinamically from a SQL query, this is the constructor code:
procedure TForm2.MakeWindow;
var
dummyMaskedit, dummyEdit: TEdit;
dummyMemo: TMemo;
dummyCombobox: TComboBox;
dummyLabel: TLabel;
dummyLBox: TListBox;
dummybutton: TButton;
i, f: integer;
buffer, workarea: double;
begin
FDQDB.Close;
FDQDB.Open('SELECT * FROM Defs WHERE active = 1');
i := 0;
f := 1;
buffer := Layout1.Width;
workarea := Layout1.Width;
SetLength(aMasks, 0);
while not FDQDB.Eof do
begin
case AnsiIndexStr(FDQDB.FieldByName('comptype').AsString,
['tedit', 'tcombobox', 'tmaskedit', 'tlistbox']) of
0: // TEdit
begin
dummyEdit := TEdit.Create(self);
dummyEdit.Parent := Form2.Layout1;
dummyEdit.Width := FDQDB.FieldByName('size').AsInteger;
if buffer - dummyEdit.Width >= 0 then
begin
buffer := buffer - dummyEdit.Width - 8;
dummyEdit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyEdit.Position.X := workarea - buffer - dummyEdit.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyEdit.Width - 8;
dummyEdit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyEdit.Position.X := workarea - buffer - dummyEdit.Width + 5;
end;
dummyEdit.Name := 'field' + IntToStr(f);
inc(f);
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyEdit.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyEdit.Position.Y - 17;
Position.X := dummyEdit.Position.X;
end;
end;
1: // TComboBox
begin
dummyCombobox := TComboBox.Create(self);
dummyCombobox.Parent := Form2.Layout1;
dummyCombobox.Width := FDQDB.FieldByName('size').AsInteger;
if buffer - dummyCombobox.Width >= 0 then
begin
buffer := buffer - dummyCombobox.Width - 8;
dummyCombobox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyCombobox.Position.X := workarea - buffer -
dummyCombobox.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyCombobox.Width - 8;
dummyCombobox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyCombobox.Position.X := workarea - buffer -
dummyCombobox.Width + 5;
end;
dummyCombobox.Name := 'field' + IntToStr(f);
dummyCombobox.Items.Delimiter := '|';
dummyCombobox.Items.StrictDelimiter := true;
dummyCombobox.Items.DelimitedText :=
AnsiUpperCase(FDQDB.FieldByName('combovalue').AsString);
inc(f);
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyCombobox.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyCombobox.Position.Y - 17;
Position.X := dummyCombobox.Position.X;
end;
end;
2: // TMaskEdit
begin
dummyMaskedit := TEdit.Create(self);
dummyMaskedit.Parent := Form2.Layout1;
dummyMaskedit.Width := FDQDB.FieldByName('size').AsInteger;
if buffer - dummyMaskedit.Width >= 0 then
begin
buffer := buffer - dummyMaskedit.Width - 8;
dummyMaskedit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyMaskedit.Position.X := workarea - buffer -
dummyMaskedit.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyMaskedit.Width - 8;
dummyMaskedit.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyMaskedit.Position.X := workarea - buffer -
dummyMaskedit.Width + 5;
end;
dummyMaskedit.Name := 'field' + IntToStr(f);
inc(f);
SetLength(aMasks, length(aMasks) + 1);
Masks.field := dummyMaskedit.Name;
Masks.mask := FDQDB.FieldByName('mask').AsString;
aMasks[length(aMasks) - 1] := Masks;
dummyMaskedit.OnExit := MaskTextExit;
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyMaskedit.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyMaskedit.Position.Y - 17;
Position.X := dummyMaskedit.Position.X;
end;
end;
3: // TListBox
begin
dummyLBox := TListBox.Create(self);
dummyLBox.Parent := Form2.Layout1;
dummyLBox.Width := FDQDB.FieldByName('size').AsInteger;
inc(i);
buffer := workarea;
if buffer - dummyLBox.Width >= 0 then
begin
buffer := buffer - dummyLBox.Width - 8;
dummyLBox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyLBox.Position.X := workarea - buffer - dummyLBox.Width + 5;
end
else
begin
inc(i);
buffer := workarea;
buffer := buffer - dummyLBox.Width - 8;
dummyLBox.Position.Y := Panel2.Position.Y + 22 + (45 * i);
dummyLBox.Position.X := workarea - buffer - dummyLBox.Width + 5;
end;
dummyLBox.Name := 'field' + IntToStr(f);
inc(f);
SetLength(aMasks, length(aMasks) + 1);
Masks.field := dummyLBox.Name;
Masks.mask := FDQDB.FieldByName('mask').AsString;
aMasks[length(aMasks) - 1] := Masks;
dummyLabel := TLabel.Create(self);
with dummyLabel do
begin
Parent := dummyLBox.Parent;
Text := FDQDB.FieldByName('Descricao').AsString;
Position.Y := dummyLBox.Position.Y - 17;
Position.X := dummyLBox.Position.X;
end;
dummybutton := TButton.Create(self);
with dummybutton do
begin
Parent := dummyLBox.Parent;
Text := '+';
Width := 20;
Position.X := dummyLBox.Width + dummyLBox.Position.X + 3;
Position.Y := dummyLBox.Position.Y;
Name := 'ba' + dummyLBox.Name;
OnClick := ButtonsAddClick;
end;
dummybutton := TButton.Create(self);
with dummybutton do
begin
Parent := dummyLBox.Parent;
Text := '-';
Width := 20;
Position.X := dummyLBox.Width + dummyLBox.Position.X + 3;
Position.Y := dummyLBox.Position.Y + 28;
Name := 'br' + dummyLBox.Name;
OnClick := ButtonsRemClick;
end;
end;
end;
FDQDB.Next;
end;
FDQDB.Close;
end;
That works nice and pretty on the windowed state of the application, this code is applied to the onCreate event of the form:
procedure TForm2.FormCreate(Sender: TObject);
begin
FDCDB.Params.Database := ExtractFilePath(ParamStr(0)) + 'window.db';
MakeWindow;
end;
The first form, main form of the application, is the one that summons the new form that has the components built in runtime:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;
end;
The second form has a TLayout, just like the first form. Then, when I create the form I bring the TLayout of the second form to the first. So far so good, it works when the application is launched in windowed mode. But when I put form1 in fullscreen mode, then click the Button that creates the form2, the components stays on the same position as in windowed mode. I've tried changing the workarea variable to these:
Screen.width, //components behave as the application were in fullscreen the whole time
Screen.WorkAreaWidth, //same as screen.width
(Layout1.Parent as TLayout).Width, //invalid typecast
(Layout1.GetParentComponent as TLayout).Width //invalid typecast
None of them worked. I wanna be able to adjust the position of the components on the screen based on its visual width, so if the user resizes the window before creating the new form, the components gets aligned properly. Anyone knows a solution for that? Thanks in advance
But when I put form1 in fullscreen mode, then click the Button that creates the form2, the components stays on the same position as in windowed mode.
At TForm1.SpeedButton1Click()
you call Application.CreateForm(TForm2, Form2);
which triggers TForm2.FormCreate(Sender: TObject);
which calls MakeWindow
. At this point Form2
knows only about the design time size.
After MakeWindow
is done, the TForm1.SpeedButton1Click()
continues:
Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;
but these do not anymore affect the layout of the controls.
You need to set Form2.Layout1.Width
before you call MakeWindow
, for example:
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;
MakeWindow; // remove it from TForm2.FormCreate()
end;