如何在屏幕调整大小后在运行时处理组件的重新对齐 delphi.



>我在谷歌上搜索了很多,以获得有关如何解决当前问题的更清晰信息,但我得到了组件的可扩展性作为最佳答案,那就是......还不是我的问题。

所以,长话短说:我想在用户调整窗口大小后重新对齐表单上的组件,表单是从 SQL 查询动态填充的,这是构造函数代码:

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;

这在应用程序的窗口状态上工作得很好,此代码应用于表单的onCreate事件:

procedure TForm2.FormCreate(Sender: TObject);
begin
FDCDB.Params.Database := ExtractFilePath(ParamStr(0)) + 'window.db';
MakeWindow;
end;

第一个窗体(应用程序的主窗体(是调用具有运行时内置组件的新窗体的窗体:

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;
end;

第二种形式有一个 TLayout,就像第一种形式一样。然后,当我创建表单时,我将第二个表单的 TLayout 带到第一个表单。到目前为止一切顺利,当应用程序以窗口模式启动时,它可以工作。 但是,当我将 form1 置于全屏模式,然后单击创建 form2 的按钮时,组件将保持在与窗口模式相同的位置。我尝试将工作区变量更改为这些:

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

他们都没有工作。 我希望能够根据组件的视觉宽度调整组件在屏幕上的位置,因此如果用户在创建新窗体之前调整窗口大小,组件将正确对齐。 有人知道解决方案吗?提前致谢

但是当我将form1置于全屏模式时,然后单击按钮 创建 Form2,组件保持与 中相同的位置 窗口模式。

TForm1.SpeedButton1Click(),您调用Application.CreateForm(TForm2, Form2);触发TForm2.FormCreate(Sender: TObject);调用MakeWindow。此时,Form2只知道设计时间大小。

完成后MakeWindowTForm1.SpeedButton1Click()继续:

Form2.Layout1.parent := Self.Layout1.Parent;
Form2.Layout1.Width := Self.Layout1.Width;

但这些不再影响控件的布局。

您需要在调用MakeWindow之前设置Form2.Layout1.Width,例如:

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;

窗体具有 ClientWidth 和 ClientHeight 属性,这些属性在 OnResize 中运行良好,可以根据可用区域动态调整控件的大小。OnResize 在窗体可见之前触发。例如,要有一个 Memo1,周围有 100 边框:

procedure TForm1.FormResize(Sender: TObject);
begin
memo1.Position.X := 100;  // Only needs to be done once but here so all code is in one spot
memo1.Position.Y := 100;
memo1.Width := form1.ClientWidth - 200;
memo1.Height := form1.ClientHeight - 200;
end;

最新更新