Delphi获取(并销毁)表单的实例

j.k*_*par -4 forms delphi

在使用"主窗体"上的TPanel的应用程序中,为了显示其他窗体,我需要不仅能够在TPanel上显示这些窗体,而且还能够使用主窗口上的控件(按钮)关闭和销毁它们形成.

目标是遵循 - 许多按钮,每个按钮在主窗体上的一个面板上显示特定的形式.然后,一个按钮,杀死当前正在显示的任何可能的形式(=嵌入在面板上).另外,每当触发一些"打开"按钮时,应该调用相同的关闭/终止动作,因此如果面板上显示某个表单,则应该用新表单替换它.

要在TPanel中显示表单,我使用以下内容:

procedure TMainForm.Button1Click(Sender: TObject);
begin
  if not assigned(form4) then
    form4:= TForm4.Create(Panel2);
  form4.Parent:= Panel2;
  form4.Show;
end;
Run Code Online (Sandbox Code Playgroud)

现在,为了关闭窗口,使用主窗体上的另一个按钮,我尝试了各种方法,包括CloseWindow方法,使用句柄或指针等.最有希望的方式,是这样的:

procedure TMainForm.Button2Click(Sender: TObject);
begin
  Panel2.controls[0].Free;
end;
Run Code Online (Sandbox Code Playgroud)

它实际上关闭了表单,但由于FreeAndNil没有使用,重复单击Button1,导致一系列令人讨厌的异常,因为表单(在这种情况下为form4)已被释放,但对它的引用没有,所以assigned()方法返回是的,然后我尝试为某个不再存在的东西赋值form4.Parent:= Panel2;.Action:= caFree嵌入式表单上的onClose 也没有帮助,因为onClose操作根本没有被触发...放置FreeAndNil(Form4)Form4的onDestroy事件,也会导致一系列以"无效指针操作"开头的异常.

运用

procedure TMainForm.Button2Click(Sender: TObject);
begin
  FreeAndNil(Panel2.controls[0]);
end;
Run Code Online (Sandbox Code Playgroud)

导致以下错误: [dcc32 Error] Unit3.pas(47): E2197 Constant object cannot be passed as var parameter

那么获取嵌入式表单实例的正确方法是什么,能够使用FreeAndNil(......表单......)?我无法通过名称来解决它,主要是因为我不知道当前显示的是什么形式.我需要能够找到基于事实的表单实例,它属于TPanel主窗体上,然后完全销毁它,以便再次单击Button1,再次显示它,然后再单击Button2将再次关闭并销毁它.

Tom*_*erg 5

解决方案的关键是Vcl.Forms.TFormClass.从文档:

TFormClass是TForm的元类.它的值是TForm或其后代之一的类引用.

并使用如下:

首先,FormN从定义将在主窗体面板中显示的窗体的所有单元中抛弃全局变量.你不需要它们,删除它们会阻止你犯错误.

其次,在主窗体中,添加一个私有声明CurrentForm: TForm和一个私有声明procedure ShowForm

...
private
  CurrentForm: TForm;
  procedure ShowForm(aFormClass: TFormClass);
...
Run Code Online (Sandbox Code Playgroud)

由于aFormClass: TFormClass参数,您可以传入任何表单类型.

为应该创建和显示面板中的表单的按钮编写事件处理程序,类似于:

procedure TForm25.ShowFormAClick(Sender: TObject);
begin
  ShowForm(TForm26);
end;
Run Code Online (Sandbox Code Playgroud)

并编写ShowForm()方法:

procedure TForm25.ShowForm(aFormClass: TFormClass);
begin
  CurrentForm.Free;
  CurrentForm := aFormClass.Create(self);
  CurrentForm.Parent := Panel1;
  CurrentForm.Show;
end;
Run Code Online (Sandbox Code Playgroud)

最后还要编写应该隐藏当前显示的任何表单的按钮的事件处理程序:

procedure TForm25.ShowNothingClick(Sender: TObject);
begin
  FreeAndNil(CurrentForm);
end;
Run Code Online (Sandbox Code Playgroud)