2012-04-30 28 views
2

我希望我能解釋這個問題很好得體!德爾福TForm的OnCreate中被多次調用

我試圖實現ReWire的音頻設備作爲德爾福.dll文件。如果你不知道什麼是ReWire,不要擔心。最重要的是,我的代碼編譯成一個.dll,和我從ReWire的系統調用到我的.dll文件打開顯示器,檢查顯示被打開,並再次將其關閉。

當我得到的電話會議到發佈,我做了以下內容:

if not Assigned(form) then 
    form := TMyForm.Create(nil); 
    form.Show; 

其中form全局變量我的德爾福圖書館內(也許有問題嗎?)。我已經迷上了MyFormOnCreate事件做一些有趣的事情做準備一樣東西的數組我想工作。

到目前爲止,一切都很好。我的表單中有一個小按鈕,打開了一個TOpenDialog。我發現只要對話關閉,OnCreate事件就會在我的表單中再次觸發!

我檢查了OnDestroy沒有被調用,所以我不知道爲什麼OnCreate被再次調用。

不幸的是我真的不知道什麼樣的信息是相關的,但這裏的待命堆棧第一次(在首次設立的形式):

First call stack

正如預期的那樣,ReWire的是使調用我的.dll來啓動Panel應用程序,所以我創建了我的表單。太好了,事情看起來不錯。

然後我的表單裏面,我開了一個小對話框,選擇一個文件,並做一些操作。出左外野,OnCreate被再次調用,而這裏的調用堆棧時間:

Second call stack

這是呼叫的瘋狂派對!收割機(底部)是我使用來測試我的應用程序的ReWire的主機,但我不知道發生了什麼事情該堆棧跟蹤裏面,因爲沒有它是我的代碼。突然之間,當我不認爲應該的時候,事件才被調用,因爲OnDestroy甚至沒有被調用。

我能想到的唯一的其他重要的事情是,如果我打印出Sender的地址,它的每一次不同,所以它以某種方式再被什麼創建,但我檢查,我只調用MyForm.Create一次。

任何想法如何這種類型的事情會發生?

+1

這是行不通的。你有兩個VCL實例。一個在你的exe中,另一個在DLL中。將其全部靜態鏈接到一個exe文件中。或使用包。 –

+0

首先通過拋棄OnCreate邏輯,然後看看你是否可以使用它。然後,將邏輯移動到發佈在OnShow處理程序上的WM_USER消息處理程序上的新函數。這樣用戶可以更早地看到表單,並且可以看到設置發生(無延遲)。這將允許您分開兩部分,並且一箇中的錯誤將更容易識別。 – mj2008

+0

非常感謝您的幫助,每個人!答案與@Remy Lebeau建議的類似,並在他的迴應下的評論中詳細說明。我非常感謝大家的意見!我對David Heffernan的評論有點擔心 - 我對所有這些VCL的東西都很陌生,所以如果別的東西變得瘋狂的話,我一定會考慮如何讓VCL實例保持一致! – aardvarkk

回答

4

在第一個堆棧跟蹤中,OnCreate調用之前調用TCustomForm.Create(),這是正確的行爲。在第二堆棧跟蹤,該OnCreate調用是由到TObject.Create(),而不是一個電話,這是不正確的行爲之前。這導致我認爲事件處理程序中的按鈕OnClick正在構建一個VMT較差的對象,或者以其他方式破壞了內存,導致錯誤地跳到代碼中,而這些代碼恰好被您的類佔用。無論哪種方式,仔細檢查您的OnClick邏輯的錯誤。

+0

這很接近問題的結果。我昨天晚上才發現它(今天早上?)。我用代碼實例化了一個對象:'my_obj:= my_obj.Create',而不是'my_obj:= TMyClass.Create'。愚蠢的錯誤。不幸的是,它顯然是*有效的語法,並且在執行時不會導致錯誤/異常。因此,在未初始化的變量上調用函數之後,發生了各種各樣的瘋狂行爲。切換到正確的語法可以解決問題。非常感謝你的幫助! – aardvarkk

1

檢查(有的話),要設置表單變量爲零。這可能是它被設置爲零而沒有釋放它指向的表單,因此下次啓動代碼被調用時,它將創建表單的另一個實例。

+0

好的建議。不幸的是,我已經檢查過Launch調用只做了一次,並且該變量在創建一次後沒有被設置回'nil'。 – aardvarkk