Как программно создать форму с парой компонентов на ней в Delphi

Я работаю с 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;

введите описание изображения здесь

Я понятия не имею, как добавлять компоненты в программно созданную форму (не во время выполнения, а в исходный код). Можете ли вы помочь мне написать код, который добавляет кнопку ОК в форму ученика, а также задает заголовок, высоту и ширину формы (код должен быть записан в файл формы ученика)?

Будем очень признательны за любые предложения и примеры. Спасибо.


person Mikhail    schedule 19.04.2013    source источник
comment
Чтобы создать форму с элементами управления полностью во время выполнения, посмотрите пример Dialogs.CreateMessageDialog.   -  person NGLN    schedule 20.04.2013


Ответы (2)


По умолчанию (то есть со всеми параметрами конфигурации 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.

Для всех других контейнерных элементов управления (таких как TPanel, TFrame и т. Д.) Вы можете переопределить конструктор по умолчанию Create.

Назовите эту форму следующим образом:

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

Or:

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;

Передаете ли вы, Self, Application или nil в качестве владельца новой формы, зависит от того, когда вы хотите, чтобы она была автоматически уничтожена, если вы не освободите ее вручную или через событие OnClose. С использованием

  • Self: уничтожит новую форму при уничтожении вызывающей формы. Это особенно полезно, когда вызывающая форма не является основной.
  • Application: уничтожит новую форму при завершении приложения. Это был бы мой предпочтительный выбор.
  • nil: не уничтожит новую форму и приведет к утечке памяти при завершении работы приложения. Хотя в конечном итоге память будет высвобождена, когда Windows завершит процесс.
person NGLN    schedule 19.04.2013
comment
Большое спасибо. Это как раз то, что прописал врач. Но гарантирует ли вызов такой формы TForm2.CreateNew (Self) .Show, что она будет удалена при закрытии? - person Mikhail; 20.04.2013
comment
@NGLN, хорошее объяснение. Большое спасибо, ваш ответ решил мою проблему. - person ; 02.07.2017
comment
чувак, ты сэкономил мне много работы здесь, отлично, действительно отличное прохождение - person Wh1T3h4Ck5; 23.04.2020

Создавать модальные формы с элементами управления на лету очень просто:

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;
person Andreas Rejbrand    schedule 19.04.2013
comment
Прохладный. Но я хочу упаковать эти элементы управления в файл класса формы. - person Mikhail; 20.04.2013
comment
@Mikhail: Тогда сделай это в FormCreate вместо своего TStudentInfoForm. Но если у вас есть файл класса формы, вы можете разложить его визуально, и в первую очередь не нужно делать это в коде. - person Ken White; 20.04.2013
comment
@KenWhite: Не делайте этого в событии класса OnCreate. Вместо этого пусть класс переопределит свой конструктор. - person Remy Lebeau; 20.04.2013
comment
@Remy: Это была не моя точка зрения, которую, по-видимому, вы перестали читать. :-) Если вы хотите поместить элементы управления в форму в ее объявлении, вы также можете использовать .dfm по умолчанию и создать его визуально, где вы можете упорядочить его, подключить обработчики событий и установить свойства. Но вы правы - в обычном случае конструктор будет правильным. Если вы просто делаете это один раз без видимой причины, FormCreate в порядке, потому что никто другой не будет создавать форму. Это не похоже на то, что вы создаете компонент для повторного использования; нет необходимости резервировать мероприятие для другого разработчика. - person Ken White; 20.04.2013