2012-05-15 76 views
4

如何创建(当我想表明它)和destroy(当我想隐藏它)帧主TForm的?帧'align = alClient。德尔福TFRAME创建/销毁

我尝试这样做:

形式:

unit main; 

interface 

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

type 
    TFormMain = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    f1: TFrame1; 
    f2: TFrame2; 
    end; 

var 
    FormMain: TFormMain; 

implementation 

{$R *.dfm} 

procedure TFormMain.FormCreate(Sender: TObject); 
begin 
    f1 := TFrame1.Create(Self); 
    f1.Parent := Self; 
end; 

end. 

第一帧:

unit uFrame1; 

interface 

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

type 
    TFrame1 = class(TFrame) 
    btn1: TButton; 
    procedure btn1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

implementation 

{$R *.dfm} 

uses main, uFrame2; 

procedure TFrame1.btn1Click(Sender: TObject); 
begin 
    Self.Free; 
    FormMain.f2 := TFrame2.Create(FormMain); 
    FormMain.f2.Parent := FormMain; 
end; 

end. 

第二帧:

unit uFrame2; 

interface 

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

type 
    TFrame2 = class(TFrame) 
    lbl1: TLabel; 
    btn1: TButton; 
    procedure btn1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

implementation 

{$R *.dfm} 

uses main, uFrame1; 

procedure TFrame2.btn1Click(Sender: TObject); 
begin 
    Self.Free; 
    FormMain.f1 := TFrame1.Create(FormMain); 
    FormMain.f1.Parent := FormMain; 
end; 

end. 

但是当我点击FrameStart或帧1按钮(TForm的FORMCREATE工作正常,即它会创建并显示FrameStart)访问vialataions崩溃。

德尔福7

With the first frameWith the second frame

+4

Self.Free? 0_o,我不知道该VCL的事件处理代码就可以搞定 - 与形式,这并不工作,例如http://stackoverflow.com/questions/708847/delphi-is-it-ok-for-a-形式到自由 - 它自 –

+1

Self.free是好的,只是没有做任何自我,打完电话后,你会得到像访问冲突。 –

+0

它与XE2很好地合作......我不能复制 – Whiler

回答

9

不能调用这些事件处理程序Self.Free。当事件处理程序返回时,下一个执行的VCL代码仍使用对刚刚释放的对象的引用。这就是访问违规来自哪里。如果您在完全调试模式下使用FastMM运行,那么您将看到一条有用的诊断消息。

这些帧将有自杀更迂回的方式。发送一个CM_RELEASE消息给帧,要求它在帧上调用Free。您发布消息,而不是发送消息,以便首先处理所有正在进行的消息。您需要添加一个消息处理程序到框架以响应消息。

+2

和鲍里斯链接显示的一些[实例](http://stackoverflow.com/a/2502613/596852)... – Whiler

+0

这是正确的!但是我不能用问题代码重现AV(至少在Delphi 2009中)。 – TLama

+1

@tlama这就是这种AV的性质。以快速MM全面调试模式运行,您将看到一些操作。这个错误是经典之一。 –

3

你已经有了一些。

这种东西背后的基本思想。

添加私有财产的MainForm的持有框架。

在按钮单击处理

假设你只需要一次一个做

if assigned(fMyFrame) then 
begin 
    fMyFrame.Free; 
    fMyFrame := nil; 
end; 
fMyFrame := TSomeFrame.Create(self); 
fMyFrame.Parent := self; 
fMyFrame.blah... 

如果你只是想摆脱它,而不是取代它

if assigned(fMyFrame) then 
begin 
    fMyFrame.Free; 
    fMyFrame := nil; 
end; 

如果你想你框架提出另一个框架,在那里重复上述内容。

如果你想在框架你在一个帧提高到是兄弟姐妹,如拥有相同的Parent,则不要使用Form1 var。

fMyNextFrame.Parent = self.Parent; 

有一个巨大的,你可以改善这一点,一旦你得到它的工作方式号码,它是接口和还是继承了经典的场景,但首先弄清楚这一点了。

mySomething := TMySomething.Create(); 

你现在可以做点什么了。 免费电话后,它不是不能,它不会也不会让其他任何东西。

不要做self.free,就像在汽油桶里玩火柴一样。它会伤害....

+0

这并没有完成。您需要将事件处理程序移动到表单方法才能正常工作。这就打破了使用框架的目的。 –

+0

同意,但有些事情必须管理对框架的引用,那就是需要管理框架的生命周期。我试图在整个管理层面进行讨论,应该选择除Frame之外的其他内容。 –