在Delphi XE中将一个类作为过程的参数传递

6
我需要做的是像这样的事情:
procedure A(type_of_form);
var form: TForm;
begin
  form := type_of_form.Create(application);
  form.showmodal;
  freeandnil(form);
end;

我为每个动态创建的表单都这样做了:

form1 := TForm1.Create(application);
form1.showmodal;
freeandnil(form1);

我在A过程中要做的事情更加复杂,但问题在于如何使表单的创建变得普遍化。也许可以使用@操作符……我真的不知道。

感谢任何建议!

2个回答

8
procedure Test(AMyFormClass: TFormClass);
var
 form: TForm;
begin
  form := AMyFormClass.Create(Application); // you can use nil if you Free it in here
  try
    form.ShowModal;
  finally
    form.Release; // generally better than Free for a Form
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Test(TForm2);
end;

form.Free 在这里就可以了。值得指出的是,只有在表单的构造函数是 TForm 构造函数的重写时,才能起作用。 - David Heffernan
@David,你是说如果构造函数命名为Create,并且具有匹配的参数,如果它隐藏了后代构造函数,那么这种方法就行不通了? - Marcus Adams
2
@Marcus,没错。你需要使用虚拟构造函数才能让通过类引用实例化的方法起作用。否则,无论类引用中包含什么内容,你都会得到一个TMyForm - David Heffernan
代码的问题(也许在我的问题中)是它不够通用。只有TMyForm的形式可以作为参数传递。想法是使用需要以相同方式创建、使用和处理的“大量”表单调用函数。尽管每个表单都从TForm继承了所有内容,但它们都有自己的类。 - Speaker
@David。你指出的是正确的。继承虚拟链规则适用于此处。如果链在中间某处被打破,它可能不会返回最初期望的结果。 - Francesca
1
@user 这个答案中的代码可以满足你的需求并且是通用的。如果它不能解决你的问题,那么你还没有问对问题。只要它们都有一个共同的祖先,你可以执行 Test(TMySuperDuperClass)Test(MyOtherFantasticForm) - David Heffernan

3
您所要求的基本上是TApplication.CreateForm()所做的事情,例如:
Application.CreateForm(TForm1, form1); 
form1.ShowModal; 
FreeAndNil(form1); 

您可以通过以下方式模拟调用TApplication.CreateForm(),而无需实际调用它:
procedure A(AClassType: TFormClass); 
var
  form: TForm; 
begin 
  form := AClassType.Create(Application); 
  try
    form.ShowModal; 
  finally
    FreeAndNil(form);
  end; 
end; 

...

begin
  A(TForm1); 
end;

是的...代码与其他代码相似(并且类似于CreateForm方法)...哈哈...我从未意识到! - Speaker
只是另一个问题... 释放表单的最佳方式是什么?Form.release?还是FreeAndNil(Form)我以前使用过FreeAndNil... 但是... - Speaker
2
TForm.Release()仅在窗体需要从其事件处理程序内部释放自己时使用。释放被延迟,直到控制返回到主消息循环,以确保TForm不被任何东西使用。如果您知道TForm不再使用(在这种情况下是这样),则可以立即调用Free()。对于像此示例中的局部变量的简单用法,FreeAndNil()过于复杂。没有必要将不再使用的指针设置为nil。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接