web-dev-qa-db-ja.com

Delphiでいくつかのコンポーネントを含むフォームをプログラムで作成する方法

私はDelphi7を使用しており、プログラムでフォームを作成しようとしています。これが私のフォームクラススタブです:

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;

enter image description here

プログラムで作成されたフォームにコンポーネントを追加する方法がわかりません(実行時ではなく、ソースコードに)。学生フォームに[OK]ボタンを追加し、キャプションとフォームの高さと幅を設定するコードを書くのを手伝ってもらえますか(コードは学生フォームファイルに記述する必要があります)。

任意の提案や例を高く評価します。ありがとうございました。

10
Mikhail

デフォルト(つまり、すべてのデフォルト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がプロセスを強制終了すると、メモリは最終的に解放されます。
19
NGLN

その場でコントロールを使用してモーダルフォームを作成するのは簡単です。

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;
4