1

設計時に 5 つのフォームを作成しました。各フォームのインスタンスを動的に作成し、タブに配置する必要があります。

私の質問:フォーム名が文字列の配列にあり、次のようにプロシージャを呼び出す場合:

ShowForm(FormName[3]);// To show the 3rd form on a tab page.

各フォームの新しいインスタンスを定義して作成するにはどうすればよいですか?

これは私が今持っているものです:

procedure TForm1.ShowFormOnTab(pProcName:String);
var
  NewForm: TfrmSetupItemCategories;//***HERE IS MY PROBLEM***

  NewTab: TTabSheet;
  FormName: String;

begin
  NewTab := TTabSheet.Create(PageControl1);
  NewTab.PageControl:= PageControl1;
  NewTab.Caption:='hi';
  PageControl1.ActivePage :=  NewTab;

  if pProcName='ProcfrmSetupItemCategories' Then
     begin
       NewForm:=TfrmSetupItemCategories.Create(NewTab);
       NewTab.Caption := NewForm.Caption;
     end;
  if pProcName='ProcfrmZones' Then
     begin
       NewForm:=TfrmZones.Create(NewTab);
       NewTab.Caption := NewForm.Caption;
     end;
.
.
.
end;

「 HERE IS MY PROBLEM 」と書かれた行は、助けが必要な場所です。このように、NewForm を 2 番目のフォームの変数として再利用することはできません...

注: 私の問題はタブではありません。むしろ、同じ変数名を使用してフォームの新しいインスタンスを作成しています。

4

3 に答える 3

8

NewForm変数をTFormとして宣言します。

var
  NewForm: TForm;
begin
  NewForm := TMyForm.Create(Tab1); //compiles OK
  NewForm := TMyOtherForm.Create(Tab2); //also compiles OK
end;

TMyFormとTMyOtherFormはどちらもTFormの派生物であると想定しています。

ドライ

次のように、クラス参照変数を使用して繰り返しコードを減らすこともできます。

procedure TForm1.ShowFormOnTab(pProcName:String);
var
  NewForm: TForm;
  ClassToUse: TFormClass;
  NewTab: TTabSheet;
  FormName: String;

begin
  NewTab := TTabSheet.Create(PageControl1);
  NewTab.PageControl:= PageControl1;
  NewTab.Caption:='hi';
  PageControl1.ActivePage :=  NewTab;

  if pProcName='ProcfrmSetupItemCategories' then
    ClassToUse := TfrmSetupItemCategories
  else if pProcName='ProcfrmZones' then
    ClassToUse := TfrmZones
  else
    ClassToUse := nil;
  if Assigned(ClassToUse) then
  begin
    NewForm := ClassTouse.Create(NewTab);
    NewTab.Caption := NewForm.Caption;
    //if you access custom properties or methods, this is the way:
    if NewForm is TfrmZones then
      TfrmZones(NewForm).ZoneInfo := 'MyInfo';
  end;
end;

クラスを登録してから、文字列からフォームを作成します

Rufo卿が彼のコメントで指摘しているように、クラスをさらに登録することもできます(これがラザロでできるかどうかはわかりませんが、その演習はあなた次第です)。

まず、ShowFormOnTabメソッドを呼び出す前に、インスタンス化するフォームクラスをクラス名から登録します。次に例を示します。

procedure TMainForm.FormCreate(Sender: TObject);
begin
  RegisterClass(TfrmSetupItemCategories);
  RegisterClass(TfrmZones);
  //and other classes
end;

次に、コードを変更して、クラス名文字列からクラス参照を取得できます。

procedure TForm1.ShowFormOnTab(pProcName:String);
var
  NewForm: TForm;
  ClassToUse: TFormClass;
  ClassNameToUse: string;
  NewTab: TTabSheet;
  FormName: String;

begin
  NewTab := TTabSheet.Create(PageControl1);
  NewTab.PageControl:= PageControl1;
  NewTab.Caption:='hi';
  PageControl1.ActivePage :=  NewTab;
  //get rid of 'Proc' and add the T
  //or even better, pass directly the class name
  ClassNameToUse := 'T' + Copy(pProcName, 5, MaxInt);
  ClassToUse := TFormClass(FindClass(ClassNameToUse));

  if Assigned(ClassToUse) then
  begin
    NewForm := ClassTouse.Create(NewTab);
    NewTab.Caption := NewForm.Caption;
    //if you access custom properties or methods, this is the way:
    if NewForm is TfrmZones then
      TfrmZones(NewForm).ZoneInfo := 'MyInfo';
  end;
end;

そうすれば、コードは任意の数のクラスで同じままになります。

詳細については、delphi.about.comの文字列からDelphiフォームを作成するをご覧ください。

于 2012-12-11T08:13:36.513 に答える
3

変数を祖先タイプとして宣言します。

var
  NewForm: TForm;

また

var
  NewForm: TCustomForm;

欠点:自分で宣言したフォームのメソッドを呼び出す場合は、変数を特定のクラスにキャストする必要があります。

NewFormが実行時に実際にTMyFormであることをコンパイラーにチェックさせる場合は、「ソフト」キャストを使用します。

(NewForm as TMyForm).MyMethod;

NewFormがTMyFormであることが確実な場合(作成したばかりの場合など)、「ハード」キャストを使用することもできます。

TMyForm(NewForm).MyMethod;
于 2012-12-11T08:13:43.577 に答える
0

登録されたクラスを使用すると、使用されるフォームの初期化で、次のように短縮できます

Function CreateAndDock(pc:TPageControl;const FormName:String):Boolean;
begin
  Result := false;
  if Assigned(GetClass(FormName)) and GetClass(FormName).InheritsFrom(TCustomForm)   then
  With TFormClass( GetClass(FormName)).Create(pc.Owner) do
    begin
     ManualDock(pc);
     Show;
     Result := true;
    end;
end;

procedure TForm4.Button1Click(Sender: TObject);
begin
   ShowMessage(IntToStr(Integer(CreateAndDock(pagecontrol1,'TDockForm'))));
   ShowMessage(IntToStr(Integer(CreateAndDock(pagecontrol1,'TNotExists'))));
end;
于 2012-12-11T12:35:14.647 に答える