2012-04-02 51 views
-1

我正在Delphi5工作在組件/表單銷燬之前是否可以顯示錶單?

我想在組件在項目運行時被銷燬之前出現一個自定義窗體。

是否可以在自定義組件中執行此操作?換句話說,我可以在定製組件在運行時被銷燬之前顯示錶單嗎?當它被放置的表單被關閉時?

我試圖把下面的組件的析構函數,但我得到一個訪問衝突錯誤時,窗體被關閉:

destructor TqqFormLogger.Destroy; 
begin 
    if NOT (csDesigning in ComponentState) then 
    SurveyForm.Click; 

    inherited Destroy; 
end; 
+2

做你正在做的事情沒有問題。不可能說爲什麼它不適合你。什麼是SurveyForm?任何更多代碼的機會,所以我們可以看到AV在哪裏。 – 2012-04-02 21:11:49

+0

對不起,沒有那麼清楚。我所擁有的是一個名爲「FormLogger」的組件,它放置在我們項目的所有表單上。在項目運行時,該組件會創建一個TButton(稱爲SurveyButton),如果單擊它,將打開一個表單(SurveyForm)。到目前爲止,這部分工作正常。但是,我們希望每次關閉表單時都打開SurveyForm(即觸發SurveyButton.Click事件)。這似乎是SurveyButton時。點擊是在我的組件的析構函數中觸發的,承載組件的主窗體已經被銷燬。有解決方案嗎?謝謝 – user1202134 2012-04-05 14:42:31

+0

表單自動調用設計時組件上的FreeNotification()(它依次調用窗體的FreeNotification()方法)。您的組件可以覆蓋它的'Notification()'方法來檢測表單何時被釋放。或者,如果您有任何在關閉時沒有立即釋放的表單,則您的組件的構造函數可以將事件處理程序分配給表單的「OnClose」事件。 – 2012-04-05 16:04:16

回答

0

看一看重寫BeforeDestruction()方法,而不是析構函數。

但是爲什麼在組件層?爲什麼不在父窗體的OnClose事件中執行?

+1

這爲什麼會有所作爲?推測問題是SurveyForm不好。這就是BeforeDestruction,OnClose等的情況。 – 2012-04-02 21:37:11

+0

'BeforeDestruction()'在任何析構函數之前被調用,所以它是一個好的地方,在它的析構函數(特別是隱含的析構函數)有機會觸及任何東西。但更重要的是,在窗體的任何子控件開始銷燬之前觸發父窗體的OnClose事件,所以這可能是一個計時問題,在父窗體關閉後但在TqqFormLogger之前,「SurveyForm」被釋放銷燬。 – 2012-04-02 22:38:40

+0

爲了簡化我的問題:是否有可能有組件控制或中斷它的父(所有者)窗體的關閉事件(銷燬)過程,以便在窗體關閉之前對其自己進行一些處理? – user1202134 2012-04-05 15:36:20

1

一般來說,AV是某些代碼試圖調用一個不再存在的東西的例程的信號。

從這個角度看,一個AV爲這個特定的析構函數的結果可能表明兩種情況之一:

  1. SurveyForm不存在了,或者
  2. 代碼爲SurveyForm.Click結果預計將組件的存在,以是真的,但組件無論如何都會被銷燬。

名稱Click暗示SurveyForm是一個按鈕式控件。如果該控件不是你的組件的一部分,而是組件所在表單的一部分,那麼前者(情況1)當然可以是真的:表單的析構函數已經銷燬了SurveyForm,現在即將銷燬你的組件。你可以通過使用BeforeDestruction來防止這種情況,正如雷米已經提到的那樣。另外(但只是一般性的提示,而不是解決你的問題),你可以通過註冊該組件給你自己來通知它的銷燬,從而防止使用被銷燬的組件。與FreeNotification結合覆蓋Notification爲此在你無組件:

procedure TqqFormLogger.SetSurveyForm(Value: TForm); 
begin 
    FSurveyForm := Value; 
    FSurveyForm.FreeNotification(Self); 
end; 

procedure TqqFormLogger.Notification(AComponent: TComponent; 
    Operation: TOperation); 
begin 
    inherited Notification(AComponent, Operation); 
    if (AComponent = FSurveyForm) and (Operation = opRemove) then 
    FSurveyForm := nil; 
end; 

destructor TqqFormLogger.Destroy; 
begin 
    if FSurveyForm <> nil then 
    ... 

如果控制確實是你的組件的一部分,那麼我懷疑背後Click代碼允許組件的析構函數的過程使用無論如何(案2)。例如,在發佈消息(手動或由於VCL或Windows內部結果)時,將在消息驅動或處理之前調用inherited Destroy

簡而言之:現在的問題太籠統了,無法給出具體的答案。

+0

'SurveyForm'仍然會在'Click'方法被調用的地方生存,因爲它在'TComponent.Destroy'執行之前不會死亡。 – 2012-04-02 22:38:01

+0

+1任何時候一個組件都有一個對外部組件的引用,如果外部組件過早或亂序釋放,使用'FreeNotification()'是個好主意。 – 2012-04-02 22:41:32

+0

@DavidHeffernan:但我們還不知道何時/何地調用了與TqqFormLogger.Destroy相關的SurveyForm.Destroy,或者即使SurveyForm與TqqFormLogger的父表單相同。 – 2012-04-02 22:42:36

相關問題