单位/表格创造第二个自我并控制它---德尔福

时间:2012-02-08 20:40:13

标签: delphi

是否可以告诉Unit1 Form1创建另一个自我,

Application.CreateForm(TForm1, Form1);

并通过第一个form1来分辨原始form1组件和第二个新form1组件之间的区别。

4 个答案:

答案 0 :(得分:1)

简单的方法是定义另一个名为Form1Copy: TForm1的全局变量,并在项目源中为Application.CreateForm添加另一个Form1Copy

更好的方法是避免使用Application.CreateForm,如果TForm1是您拥有的唯一表单,或者它不是主表单并使用以下代码:

var
  Form1, Form1Copy: TForm1;
...

procedure InitializeMyForms;
begin
  Form1 := TForm1.Create(nil);
  Form1Copy := TForm1.Create(nil);

  ... //Do extra stuff

  Form1.Show;
  Form1Copy.Show;
end;

答案 1 :(得分:1)

看,如果您允许表单在关闭时释放内存,则根本不需要变量....

第1步

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

第2步

  TForm1.Create(Application);
   TForm1.Create(Application);
   TForm1.Create(Application);

第3步 接下来,要从程序的其他区域引用您的表单,有多种方法。您可以使用屏幕对象或application.components,如果它是MdiChildren,您可以使用MdiParents.MdiChildren属性......就像这样。

for i := 0 to Screen.FormCount - 1 do
begin
  if Screen.Forms[i] is TForm1 then
    TForm1(Screen.Forms[i]).MyPublicMethod;
end;

答案 2 :(得分:0)

面向对象的方法是创建Form1Factory并让Form1Factory创建和管理Form1实例。例如,如果您需要向所有Form1实例发送事件,或者处理表单关闭时发生的事件,如果必须通知相同类型的其他表单,那么这将是交给工厂对象的工作。 / p>

你可以创建一个TObjectList<TForm1>,这样你就可以得到那些对象的列表,这可以让你不必像其他答案那样迭代Screen.Forms。 David H的评论确实是你答案的关键;您不需要该全局变量。从Form1.pas中取出,然后继续迭代和测试,直到找到解决方案。

不是让表单创建自己的另一个副本,为什么不让它通过委托(回调函数)告诉表单工厂这样做。之后您可以决定是否希望工厂对象从池中创建和重用表单对象,而不是始终构建新的表单对象。

答案 3 :(得分:0)

如果不采用所有面向对象并且不使用意大利面条的全局变量,这样做的简单方法是让控制另一个表单的表单保存对它需要控制的表单的引用。无论是相同形式还是其他形式类都无关紧要。虽然在后一种情况下,您需要将表单的单元添加到接口部分的uses子句中。

TForm1 = class(TForm)
private
  FFormToControl: TForm2; // Class member so initialized to nil by the compiler.
end;

然后在代码中的某处,您需要实例化您想要控制的表单。

FFormToControl := TForm2.Create(<Owner>);
FFormToControl.Show;

您可以使用ApplicationSelf或nil。这取决于您希望拥有者的身份,这取决于您希望控制FFormToControl的生命周期的人。如果在应用程序关闭之前它会一直存在Application就行了。如果在释放Form1时应释放它,请使用Selfnil。 Self将确保VCL的所有权系统能够解决问题。使用nil意味着你必须自己释放它。

之后您可以简单地调用方法并设置TForm2类的属性:

FFormToControl.DoSomethingCool;
FFormToControl.EditBackgroundColors := clRed;

如果第二种形式可以存在并在TForm1实例的生命周期内关闭,那么您需要在使用其任何方法和属性之前检查该表单是否已实例化:

if Assigned(FFormToControl) then begin
  FFormToControl.DoSomethingCool;
  FFormToControl.EditBackgroundColors := clRed;
end;

当FFormToControl在TForm1的构造函数(或OnCreate)之外的某个地方实例化并在TForm1的析构函数(或OnDestroy)之前释放时,你也应该这样做,因为你可以永远不确定FFormToControl是否被实例化。在这种情况下,你最好使用nil作为FFormToControl的所有者,你应该确保在释放FFormToControl时通知TForm1。例如,通过响应OnDestroy事件并在其处理程序中将FFormToControl设置为nil。

FFormToControl := TForm2.Create(<Owner>);
FFormToControl.OnDestroy := HandleForm2Destroy;
FFormToControl.Show;


procedure TForm1.HandleForm2Destroy(Sender: TObject);
begin
  if Sender = FFormToControl then begin
    FFormToControl := nil;
  end;
end;

注意: 当您从自己的方法创建和使用表单时,您必须小心避免无限循环创建下一个实例。

相关问题