2012-05-15 102 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之外的其他內容。 –