2010-01-15 78 views
1

這裏已經討論過了,但不是詳細說明。如何關閉Delphi中的非模態窗體

我在嘗試讓非模態子窗體關閉時遇到了麻煩。我讓它通知父母,但我得到抽象的錯誤和其他例外。我究竟做錯了什麼?父母是否必須釋放非模態形式,或者不要再嘗試通過該變量來訪問它?

主要形式有:

NonModal := NonModalTForm.Create(Self); 
NonModal.Callback := Callback; 
NonModal.Show; 

Procedure TForm.Callback; // called by non-modal form when closing 
begin 
    FreeAndNil(NonModal); // or should this just be NonModal := nil so I don't try to access a dangling pointer? 
end; 

在NonModal.pas

procedure NonModalTForm.FormClose; 
begin 
    Callback; // calls parent 
end; 
+5

你的代碼是切斷你正在坐的分支的編程等價物。 – 2010-01-16 00:48:08

回答

6

使用隱藏,如果你想顯示窗口以後。

如果要關閉它,請使用Close。 (關閉主窗口,關閉應用程序)。 關閉的確切操作取決於表單參數。

看近距離的來源:

procedure TCustomForm.Close; 
var 
    CloseAction: TCloseAction; 
begin 
    if fsModal in FFormState then 
    ModalResult := mrCancel 
    else 
    if CloseQuery then begin 
     if FormStyle = fsMDIChild then 
     if biMinimize in BorderIcons then 
      CloseAction := caMinimize 
     else 
      CloseAction := caNone 
     else 
     CloseAction := caHide; 
     DoClose(CloseAction); 
     if CloseAction <> caNone then 
     if Application.MainForm = Self then 
      Application.Terminate 
     else if CloseAction = caHide then 
      Hide 
     else if CloseAction = caMinimize then 
      WindowState := wsMinimized 
     else 
      Release; 
    end; 
end; 

但要小心免費。在左邊的窗口隊列中可能會有一些消息會導致崩潰。更好地使用Release來清理窗口。因爲它在釋放它之前等待消息。

4

你正在做你不應該做的事情。
在NonModalForm的onClose事件中,您調用一些直接釋放它的代碼,但它仍然在事件處理程序執行中,因此最終會產生一個無效的自身對象。
這就是爲什麼在表單上使用Release而不是Free的情況。

正如Gamecat指出的那樣,只需簡單地調用Close即可......
VCL的美妙之處在於它非常簡單。

+0

>>作爲Gamecat指出了這一點,只是簡單地調用Close ...... << 你說調用它本身是從非模態的FormClose本身調用的回調過程中關閉?不會觸發非Modal表單的第二個OnClose事件?或者你是說VCL足夠聰明,不會再次調用非Modal的FormClose。 – RobertFrank 2010-01-16 00:28:45

+2

你的'回調函數與這個討論無關,湯姆。正如你注意到的,你在表單的OnClose事件處理函數中調用它。這意味着在回調函數被調用時,*您的表單已經**了**關閉*,所以您的整個問題都沒有意義:您不需要學習如何關閉表單,因爲您已經完成即使你不知道你是如何管理它的。 – 2010-01-16 00:52:26

+0

沒有回調過程,我如何避免父指向非模態表單的內存泄漏和/或懸掛指針?我必須釋放NonModal指向的內存並將NonModal設置爲零,所以我知道它沒有被使用。 我可以看到的唯一解決辦法是又邏輯的另一層:非模態形式,在關閉時,調用回調到母體,它設置一個標誌「非模態形式封閉」爲True。後來(當本身關閉或想重新使用非模態形式,它會檢查這個標誌,並釋放內存。 對不起,這個揮之不去,但我真的試圖找出了這一點,而不 – RobertFrank 2010-01-17 00:41:48

10

您可以致電close從FormClose事件以外的其他地方關閉窗體。在FormClose情況下,只需設置等於行動,以執行下列操作之一:

  • caFree - 處置形式的完全
  • caMinimize - 最小化形式
  • caHide - 隱藏形式
  • caNone - 忽略收盤

例如:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
    Action := caFree; 
end; 
3

當其他組件被釋放時,VCL已經有了一個通知組件的機制。你可以這樣使用它;

type 
    TfrmParent = class(TForm) 
    btnShowChild: TButton; 
    procedure btnShowChildClick(Sender: TObject); 
    private 
    FChild: TfrmChild; 
    public 
    procedure Notification(AComponent: TComponent; Operation: TOperation); override; 
    end; 


procedure TfrmParent.btnShowChildClick(Sender: TObject); 
begin 
    // Check status of child 
    if FChild = nil then 
    begin 
    // Child does not exist, create it 
    FChild:= TfrmChild.Create(Application); 
    FChild.Show; 

    // Ask Child to notify us when it is destroyed 
    FChild.FreeNotification(Self); 
    end 
    else 
    begin 
    // Child already exists 
    FChild.Show; 
    end; 
end; 

procedure TfrmParent.Notification(AComponent: TComponent; 
    Operation: TOperation); 
begin 
    inherited; 

    if (AComponent = FChild) and (Operation = opRemove) then 
    begin 
    // FChild is about to be freed, so set reference to Child to nil 
    FChild:= nil; 
    end; 
end; 

創建子窗體後,使用創建的窗體的FreeNotification方法來註冊自己,當子窗體被破壞收到通知。

要對通知作出反應,請覆蓋通知方法。在那裏,你可以找出哪個組件被銷燬,並將其與記住的子表單引用進行比較。當您收到通知時,只需將對子窗體的引用設置爲零。

在孩子TfrmChild本身,你不必做任何事情,但什麼skamradt寫道:就在參數Actionb設置爲caFree在OnClose事件。

+4

+1。當'Self'傳遞給'TfrmChild.Create()'而不是'Application'時,甚至不需要調用'FreeNotification()' - VCL中的所有權管理負責通知調用。 – mghie 2010-01-18 04:58:28

+0

這裏唯一的工作決定。只有它將封閉格式設置爲「nil」。工作很好。我不知道爲什麼有更少的選票 – 2017-06-10 08:46:50

-2

不使用callback

只需撥打FreeAndNil(Self);以釋放是爲表單創建的所有內存資源。

記住這是你的實現代碼創建的自由對象。由Delphi設計的表單設計器創建的對象非常好。

+0

我不認爲這個答案補充了已經給出的其他人。其次,作爲[這個答案](http://stackoverflow.com/a/2075484/757830)(特別是[這個評論])(http://stackoverflow.com/questions/2075405/how-to-close -non-modal-form-in-delphi#comment2006057_2075484))聲明,釋放其事件處理程序中的表單實際上是不行的。對不起,-1。 – NGLN 2013-12-11 21:40:13