線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:3652
推到 Plurk!
推到 Facebook!

多個Form被執行關閉時, Close該如何寫

缺席
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-09-18 12:18:23 IP:61.67.xxx.xxx 未訂閱

請問各位:

我有一個狀況

Form1 有 Button1

procedure TForm1Click(Sender: TObject);
begin
Form2:= TForm2.Create(self);

Form2.Show;

end;

在Form2的onClose

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

問題:

當button1執行4次時, 會建立4個Form2, 但Form2.name分別為 Form2_1, Form2_2, Form2_3, Form2_4(此部份是由Delphi自己命名的, 我並未指定), 而就目前的寫法 Form2:=nil一旦被執行(假設我是關閉 Form2_3), 然後我再去關閉 Form2_1, Form2_2都會引發錯誤, 我要如何在 Close上寫, 才可以做到關閉Form2_1, 實際是Form2_1:= nil, 關閉Form2_2, 實際是Form2_2:= nil的寫法, 謝謝!



aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-09-18 22:28:34 IP:61.229.xxx.xxx 未訂閱
我非delphi的當前使用者。但猜問題可能的情形。也許不對,但目前也還沒人回應,就插花一下吧!

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

===================引 用 文 章===================

問題:

當button1執行4次時, 會建立4個Form2, 但Form2.name分別為 Form2_1, Form2_2, Form2_3, Form2_4(此部份是由Delphi自己命名的, 我並未指定), 而就目前的寫法 Form2:=nil一旦被執行(假設我是關閉 Form2_3), 然後我再去關閉 Form2_1, Form2_2都會引發錯誤, 我要如何在 Close上寫, 才可以做到關閉Form2_1, 實際是Form2_1:= nil, 關閉Form2_2, 實際是Form2_2:= nil的寫法, 謝謝!



------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2006-09-18 23:20:47 IP:61.67.xxx.xxx 未訂閱

謝謝回應

但這不是一個合法的寫法, self是反應一個TObject, 無法指定 nil的格式

aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2006-09-19 02:07:00 IP:61.229.xxx.xxx 未訂閱

謝謝你的回應,也讓我學習到不能直接把 self 值設成NIL !

不過我剛自己試了 bcb 的程式。
this = NULL; 是行不通的,但 (void *) this = NULL; 是可以的。
而我追cpu的 反組譯程式,this 是指向instance的位址沒錯。就是和form2這個位址,二個指標變數 this 與 form2的內容是一樣的。
但,delphi裡沒有指標,但對應的是reference,其實也是指標的一種,屬於 implicit derefence pointer。內容放的也是記憶體位址。
不過 self 應該是reference 型別不知是否也可以強型傳成Pointer( ),類似(void *) this = NULL;

不過終就我還是錯了! ,因為認真的看了你的程式才發現,你要的是把一個reference的變數設定成nil而已。我自己都頭昏的想把指向物件的指標變成null,真是神經了。想了想,有點奇怪的是,通常需要把reference變數設成nil是為了類似這樣的敘述 if not Assigned( ref ) then ref := TXxxx.Create(AOwner)以避開建二次… 我剛也查了我以前的舊書 delphi 2 發展手冊,也有看到類似你要 Action := caFree; 然後到OnDestory事件上加一句 ref := nil。說明有提到事實上caFree 時整個物件已經釋放,「變數」本身的值還是存在,於是為了在Assigned的判別中正常運作,需要把此變數設成nil 。

但你的例子是使用了 一個Global reference variable (Form2) ,以此來跨二個unit,且是唯一一個變數來接受你動態的傳reference 給 Form2。第一次產生時,Form2的值是指向第一個產生的實體,二個次Form2是指向第二個實體……,無論幾次create,都只用一個Form2的變數來接。當第一個instance close的時候,Form2指向nil,即不指向任何地方。第二個instance close的時候,Form2再度的被nil,此時沒義意了因為重複設定Form2為nil n 次是沒什麼意義的。

因為PD兄肯定是高手,我想應該會覺得我講一堆沒用很煩的話。我想表達的意思是這個程式本身的「目的」問題。因為:
1 / NIL 一個變數不代表instance的釋放,只是該變數被指定為0。通常會NIL是為了判別變數是否指向任何物件用。
2/ 若要用NIL的方法來判別多instance,那麼就一定要定義n個變數來被NIL,這樣才有意義,但這樣就失去動態create的意義了,總不可能 fm 1 := xxx.create ; fm2 := xxx.create; fm3 := xxx.create..... fm1 := nil; fm2 :=nil; fm3 := nil.......
3/但若一定要知道某form是否被關了,那可以用Name的屬性來判別。既然delphi已經為此自動加序數名進去,應該可以設定一個global的integer變數,而在Form2.oOnCreate事件加入 i ,而要判別哪個form有無被關時,則用loop的方式配合 i值和Name屬性來找。

所以,若是單純為了釋放,就不用去nil任何變數,因為沒必要。若是為了要判別,那NIL的方式在動態建立物件時是不可行的,理由如2。所只剩下上面的第三點的方式可以達成吧!

不知是否還有其他的應用?? 廢話很多,請見諒唷!



===================引 用 文 章===================

謝謝回應

但這不是一個合法的寫法, self是反應一個TObject, 無法指定 nil的格式

------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2006-09-19 02:10:11 IP:61.229.xxx.xxx 未訂閱
補剛上面打錯了一件事: 不是delphi沒有指標,而是delphi處理物件時,並不用指標來接,而是用reference變數來接。
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#6 引用回覆 回覆 發表時間:2006-09-19 14:26:01 IP:61.67.xxx.xxx 未訂閱

感謝 aftcast 兄詳細的說明:

昨天我的問題已經解決, 首先

大多數人使用 if not Assign(..) then Form.Create(...) 來避免二次建窗, 但我的需求是要多窗開出, 所以不能加這樣的寫法, 至於在 onclose 會加這兩組參數的原因是

一般人在關窗, 都是在 button上寫 Form2.Close, 而在呼叫的Form2的Form1上寫

try

Form2:= Tform2.Create(slef);

finally

Form2.Free;

end;

事實上這個Form2並未真正自記憶體中被釋放, 只要執行數次, 系統資源立刻大幅減少, 因此指定Action:= caFree, 可以讓 Form2確實自記憶體配置被清除, 可是還有一個Form2的變數, 如果不指定 Form2:= nil 的話, 當你使用if not Assing(Form2) , 事實上 Form2的變數已不是 nil值, 因此必須指定 Form2:= nil才可以徹底將Form2變數給釋放, 可是當我使用多窗來Create時, 第2個Form2的變數名稱已經不是Form2了, 而是 Form2_1, 因為這是全域變數F不能有重覆, 這也就是我在Form2.OnClose寫 Form2:= nil, 當某一個Form2被釋放是沒有問題, 但如果有第二個Form2窗被開啟的話, 這個Form2被釋放時, Delphi仍以 Form2來釋放, 但Form2變數已經前一個Form2給放掉, 自然就會出現Access Error 的錯誤(其實應該是Form2_1:= nil), 後來我解決的方法是在

Form2.onDestroy 上寫 Form2:= nil; 這樣去編譯, 執行都很正常了, 當然我不是很清楚 onDestroy到底做了那些事, 只是把這個經驗提供給各位做參考!

P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#7 引用回覆 回覆 發表時間:2006-09-19 14:29:34 IP:61.67.xxx.xxx 未訂閱

上文有些誤植, 因為討論內容無法修正, 特此在修正

if Assing(...) ==> 正確為 if Assigned(...)

try

Form2:= TForm2.Create(self);

少寫一行 Form2.ShowModal;

finally

end;

pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2006-09-22 23:29:25 IP:219.134.xxx.xxx 未訂閱
不知道我看明白你的问题没有。按我对你的问题的理解,我认为你对 Form2 是个啥东西,理解有错误。

在 TFomr2 的单元里,Delphi 自动地帮你在 interface 部分声明了一个: var Form2: TForm2;

并且,delphi 自动地在工程那个单元里,自动地帮你写了:Application.CreateForm(Form2, TForm2);

要知道,这个类型为 TForm2 的变数 Form2 是一个其它单元也可以看到的一个 TForm2 的实例。

如果你有很多个 TForm2 的实例,也就是你要同时 Show 很多个 Form2 出来,就不应该用 Form2 这个变数!而应该为每个窗口,单独命名一个 TForm2 类型的变数。

否则,问题很严重。


===================引 用 文 章===================

感謝 aftcast 兄詳細的說明:

昨天我的問題已經解決, 首先

大多數人使用 if not Assign(..) then Form.Create(...) 來避免二次建窗, 但我的需求是要多窗開出, 所以不能加這樣的寫法, 至於在 onclose 會加這兩組參數的原因是

一般人在關窗, 都是在 button上寫 Form2.Close, 而在呼叫的Form2的Form1上寫

try

Form2:= Tform2.Create(slef);

finally

Form2.Free;

end;

事實上這個Form2並未真正自記憶體中被釋放, 只要執行數次, 系統資源立刻大幅減少, 因此指定Action:= caFree, 可以讓 Form2確實自記憶體配置被清除, 可是還有一個Form2的變數, 如果不指定 Form2:= nil 的話, 當你使用if not Assing(Form2) , 事實上 Form2的變數已不是 nil值, 因此必須指定 Form2:= nil才可以徹底將Form2變數給釋放, 可是當我使用多窗來Create時, 第2個Form2的變數名稱已經不是Form2了, 而是 Form2_1, 因為這是全域變數F不能有重覆, 這也就是我在Form2.OnClose寫 Form2:= nil, 當某一個Form2被釋放是沒有問題, 但如果有第二個Form2窗被開啟的話, 這個Form2被釋放時, Delphi仍以 Form2來釋放, 但Form2變數已經前一個Form2給放掉, 自然就會出現Access Error 的錯誤(其實應該是Form2_1:= nil), 後來我解決的方法是在

Form2.onDestroy 上寫 Form2:= nil; 這樣去編譯, 執行都很正常了, 當然我不是很清楚 onDestroy到底做了那些事, 只是把這個經驗提供給各位做參考!

系統時間:2024-03-29 2:18:34
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!