11

我正在使用 Delphi 7,并且正在尝试以编程方式创建表单。这是我的表单类存根:

unit clsTStudentInfoForm;

interface

    uses Forms;

    type
        TStudentInfoForm = class (TForm)

        end;

implementation


end.

我的主表单上还有一个按钮(这只是一个常规表单,应该在运行时创建并显示上面的表单),单击它会创建学生表单并将其显示为模式窗口。它确实显示了表格,但上面没有任何内容。您唯一能做的就是单击窗口右上角的关闭按钮将其关闭。

procedure TLibraryForm.btnShowStudentIfoFormClick(Sender: TObject);
var
    f : TStudentInfoForm;
begin
    f := TStudentInfoForm.CreateNew(Self);
    f.ShowModal;
    f.Free;
    f := nil;
end;

在此处输入图像描述

我不知道如何将组件添加到以编程方式创建的表单中(不是在运行时,而是在源代码中)。你能帮我写一些代码,在学生表单中添加一个 Okay 按钮,并设置标题和表单的高度和宽度(代码必须写在学生表单文件中)吗?

任何建议和示例将不胜感激。谢谢你。

4

2 回答 2

21

默认情况下(即:使用所有默认 IDE 配置设置),会自动创建新设计的表单。只会显示主要形式,而次要形式可以显示:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
  Form3.ShowModal;
end;

禁用此自动创建选项是一种很好的常见做法。转到:工具>(环境)选项>(VCL)设计器>模块创建选项,然后禁用/取消选中自动创建表单和数据模块选项。

相反,仅在需要时创建(已经设计好的)表单:

procedure TForm1.Button1Click(Sender: TObject);
var
  Form: TForm2;
begin
  Form := TForm2.Create(Self);
  Form.Show;
end;

这也说明不需要辅助表单的全局变量,最好尽快删除它们以防止错误使用:

type
  TForm2 = class(TForm)
  end;

//var
//  Form2: TForm2;  << Always delete these global variable

implementation

如果您不想使用表单设计器设置此类辅助表单,则需要在运行时在代码中创建所有控件。如下:

unit Unit2;

interface

uses
  Classes, Forms, StdCtrls;

type
  TForm2 = class(TForm)
  private
    FButton: TButton;
  public
    constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
  end;

implementation

{ TForm2 }

constructor TForm2.CreateNew(AOwner: TComponent; Dummy: Integer = 0);
begin
  inherited CreateNew(AOwner);
  FButton := TButton.Create(Self);
  FButton.SetBounds(10, 10, 60, 24);
  FButton.Caption := 'OK';
  FButton.Parent := Self;
end;

end.

如您所见,我使用了CreateNew构造函数。这对于衍生品是必要的:T(Custom)Form

使用CreateNew而不是Create创建表单,而不使用关联的 .DFM 文件对其进行初始化。CreateNew如果TCustomForm后代不是TForm对象或 的后代,则始终使用TForm

对于所有其他容器控件(例如TPanelTFrame等),您可以覆盖默认构造函数Create

按如下方式调用此表格:

procedure TForm1.Button1Click(Sender: TObject);
var
  Form: TForm2;
begin
  Form := TForm2.Create(nil);
  try
    Form.ShowModal;
  finally
    Form.Free;
  end;
end;

或者:

procedure TForm1.Button1Click(Sender: TObject);
begin
  FForm := TForm2.CreateNew(Application);
  FForm.Show;
end;

在最后一种情况下,表单在关闭时并没有被释放而是隐藏,因此您需要将其引用存储在私有字段 ( FForm) 中并稍后释放它。或者您可以自动执行此操作:

unit Unit2;

interface

uses
  Classes, Forms, StdCtrls;

type
  TForm2 = class(TForm)
  private
    FButton: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  public
    constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
  end;

implementation

{ TForm2 }

constructor TForm2.CreateNew(AOwner: TComponent; Dummy: Integer = 0);
begin
  inherited CreateNew(AOwner);
  OnClose := FormClose;
  FButton := TButton.Create(Self);
  FButton.SetBounds(10, 10, 60, 24);
  FButton.Caption := 'OK';
  FButton.Parent := Self;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

end.

现在,您可以在不存储引用的情况下调用它:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TForm2.CreateNew(Self).Show;
end;

您是否通过 、SelfApplication作为nil新表单的所有者取决于您希望何时自动销毁它,以防您不手动或通过OnClose事件释放它。使用

  • Self: 当调用表单被销毁时,将销毁新表单。这在调用表单不是主表单时特别有用。
  • Application: 将在应用程序结束时销毁新表单。这将是我的首选。
  • nil: 不会破坏新表单并在应用程序结束时导致内存泄漏。但是,当 Windows 终止进程时,内存最终会被释放。
于 2013-04-19T21:41:01.387 回答
8

动态创建带有控件的模态表单很容易:

procedure CreateGreetingForm;
var
  frm: TForm;
  lbl: TLabel;
  edt: TEdit;
  btn: TButton;
begin

  frm := TForm.Create(nil);
  try
    lbl := TLabel.Create(frm);
    edt := TEdit.Create(frm);
    btn := TButton.Create(frm);
    frm.BorderStyle := bsDialog;
    frm.Caption := 'Welcome';
    frm.Width := 300;
    frm.Position := poScreenCenter;

    lbl.Parent := frm;
    lbl.Top := 8;
    lbl.Left := 8;
    lbl.Caption := 'Please enter your name:';

    edt.Parent := frm;
    edt.Top := lbl.Top + lbl.Height + 8;
    edt.Left := 8;
    edt.Width := 200;

    btn.Parent := frm;
    btn.Caption := 'OK';
    btn.Default := true;
    btn.ModalResult := mrOk;
    btn.Top := edt.Top + edt.Height + 8;
    btn.Left := edt.Left + edt.Width - btn.Width;

    frm.ClientHeight := btn.Top + btn.Height + 8;
    frm.ClientWidth := edt.Left + edt.Width + 8;

    if frm.ShowModal = mrOk then
      ShowMessageFmt('Welcome, %s', [edt.Text]);

  finally
    frm.Free;
  end;

end;
于 2013-04-19T20:33:26.340 回答