【问题标题】:How i can to Destroy (free) a Form from memory?我怎样才能从内存中销毁(免费)表格?
【发布时间】:2011-06-05 03:11:07
【问题描述】:

我的项目中有 2 个表单(Form1 和 Form2),Form1 是自动创建表单,但 Form2 是可用表单。 如何创建 Form2 并卸载 Form1?

我在此代码中收到“访问验证”错误。

这是Form1代码:

1.  uses Unit2;
//*********
2.  procedure TForm1.FormCreate(Sender: TObject);
3.  var a:TForm2;
4.  begin
5.      a := TForm2.Create(self);
6.      a.Show;
7.      self.free;  // Or self.destory;
8.  end;

谢谢。


我将“Serg”代码修改为:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Application.CreateForm(TForm2, Form2);
  Release;
end;

end.

///

program Project1;
uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Form1:= TForm1.Create(Application);
  Application.Run;
end.

但是这个项目启动然后自动退出,为什么? 我想显示 Form1,当我们单击 Button1 时,显示 Form2 和 free(Release) Form1。我该怎么办?

【问题讨论】:

  • 你正在从构造函数调用析构函数。
  • 看看这篇关于 application.mainform 的帖子:stackoverflow.com/questions/25666626/…>

标签: delphi delphi-xe


【解决方案1】:

销毁表单时,最好使用 Release。

Release 几乎和 free 一样,但它会等待待处理的消息以避免崩溃。

你永远不应该使用 Destroy。 Free/Release 调用析构函数。

Self 是当前对象(在您的代码 Form1 中,因此 self.Free 会杀死当前表单。这会导致访问冲突。Form1 是自动创建的,它也是自动销毁的,因此您不应该自己销毁它。如果不想要了,藏起来吧。

如果你想稍后处理它,你应该保留对新创建的表单的引用。

你修改后的代码应该是这样的:

uses Unit2;

TForm1 = class (TForm)
private
  FChild : TForm2;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FChild := TForm2.Create(nil);
  Hide; // Hides form 1
  FChild.Show;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  FChild.Release;
end;

但是为什么要在第一个表单的创建表单中创建另一个表单。为什么不完全删除第一个表单而只使用第二个表单(自动创建)?

【讨论】:

  • 谢谢 Gamecat。在我的项目中,我有很多表单。form1 是在我的应用程序启动时设置一些配置的表单。我想显示 form1,当用户设置该配置时,然后卸载 form1 并显示 form2。你有更好的主意吗?
  • 当我使用您修改过的代码时,Form1 可见约 1 秒钟,然后隐藏。为什么? (我想完全看不见form1)
  • @User,那以后会咬你的。第一个自动创建的表单被指定为主表单,当主表单被销毁时,应用程序终止,即使还有其他表单仍然存在。请改为:在您的 DPR 文件中,使用 Form1 := TForm1.Create(nil); Form1.ShowModal; Form1.Free; 创建并显示配置表单 之后,使用通常的 Application.CreateForm(Form2, TForm2) 自动创建 Form2。如需更详细的回复,请发布一个新问题,例如“如何在主表单之前显示配置表单?”
  • 不使用该版本代替 Free 导致我偏头痛。从来不知道这条重要的建议。
  • 请注意,今天 Release() 已被弃用
【解决方案2】:

你正在尝试做一些奇怪的事情。

你不能在不关闭应用程序的情况下释放主窗体,所以你的 Form1 不应该是自动创建的窗体,Form1 和 Form2 都应该手动创建。

首先,您应该像这样编辑您的项目源以手动创建 Form1:

program Project9;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Form1:= TForm1.Create(Application);
  Application.Run;
end.

Form1.OnCreate 应该写成

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.CreateForm(TForm2, Form2);
  Release;
end;

这将使 Form2 成为您应用程序的主要表单。正如已经回答的那样,您应该使用 Release 方法来释放表单。

【讨论】:

  • 感谢您的回复。如果我想向 Form1 添加一个按钮并输入 Application.CreateForm(TForm2, Form2);发布;在其中,我必须将代码修改为???? (如果我将此代码放入按钮应用程序启动然后退出)
  • @user482923:如果您有更多问题,请将它们作为新问题提出,并附上详细的描述和代码,而不是 cmets。 cmets中的问题很难理解和回答。
【解决方案3】:

如果 Form1 是“自动创建”,则它归应用程序对象所有 - 您不应在代码中释放它。如果 Form1 拥有 Form2,应用程序会清理两者。

我会这样做,但不确定它是否符合您的要求:

procedure TForm1.FormCreate(Sender: TObject);
var a:TForm2;
begin
  a := TForm2.Create(nil);
  try
    a.Show;
 finally
   freeandNil(a);
 end; 
end;

【讨论】:

  • 表单会显示然后立即销毁,没有时间交互
  • 不应该是 Free 而不是 FreeAndNil 吗?
  • 当然 mjn 是正确的。如果您显示非模态,那么立即释放将毫无用处。在这种情况下,您应该在 TForm.OnClose 事件中决定要对表单执行的操作: TForm1.FormClose(Sender: TObject; var Action: TCloseAction); TCloseAction 是一个有 4 个成员的枚举:(caNone, caHide, caFree, caMinimize);将传递给事件的 Action 变量设置为您需要的行为。
  • 我错了,我从来没有看到使用 FreeAndNil 的理由,总是 .Free;
  • 是的 - 在许多情况下它并不是真正需要的 - 好的代码永远不应该真正使用它。我只是出于习惯而这样做,因为我天生偏执,哈哈。尽管有人可能会争辩说它使用了额外的处理器周期,但我严重怀疑这在我们的现代环境中是否有任何意义。
【解决方案4】:
begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

...

procedure TForm1.FormClose(Sender: TObject; var CanClose: Boolean);
begin
  if MessageDlg ('Are you want to exit?', mtConfirmation,
      [mbYes, mbNo], 0) = mrNo then
    CanClose := False;
end;

所以,就是这样……

【讨论】:

    【解决方案5】:

    如果 Form1 应该做的只是初始化某些东西但不显示,请考虑改用数据模块。这些无法显示,但仍可以自动创建。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-06
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 1970-01-01
      • 2023-01-28
      相关资源
      最近更新 更多