Delphi中的窗體,有模式窗體與非模式窗體兩種。兩種窗體的調用方式不同,模式窗體使用ShowModal顯示,非模式窗體使用Show顯示。當顯示模式窗體的時候你是不能操作本程序的其他窗體的,你不能把焦點從模式窗體轉到其他窗體上。而非模式窗體則沒有這種限制,你可以從一個非模式窗體切換到另外一個非模式窗體上。兩種窗體的區別僅僅在調用的方式上有區別。
窗體的創建:
當使用Delphi的IDE New一個窗體后,在Project1.dpr文件中,會出現一句Application.CreateForm(TForm2, Form2);意思是當程序啟動的時候會創建TForm2類的Form2實例,也就是窗體2。這一過程是自動的,不管你是否調用顯示Form2,Form2已經存在了,其OnCreate事件也已經觸發了。這時候,如果你想顯示Form2,那么可以顯式調用Form2的Show或ShowModal方法,以非模式或模式顯示窗體。
如果你不想隨程序啟動而創建窗體,而是動態的創建窗體,那么,你可以刪除上面的那句代碼,然后在程序中你想動態創建窗體的地方加上以下代碼:
Application.CreateForm(TForm2, Form2);或者使用Form2 := TForm2.Create(Application);兩者的主要區別在於,觸發OnCreate事件的時候,第一種方法Form2變量已經指向了新生成的實例,外第二種方法先調用TForm2的Create方法,再給Form2這個變量賦值,在OnCreate時Form2變量還是未定義的。
窗體銷毀:
有創建,就必須有銷毀,不然的話會產生內存泄漏。對於程序自動生成的窗體,在程序結束的時候會自己釋放,對於這種窗體,我不建議進行手動釋放,除非你確定釋放后絕對不會再用到這個窗體了,不然就會產生內存訪問錯誤。對於動態生成的窗體,一旦不再使用,一定要手動釋放資源,手動釋放主要有兩種方式,第一種是顯示調用Form.Free這個方法。對於上面用的例子Form2來說:
Form2.Free;
Form2 := nil;
要將變量Form2賦值為nil,是為了防止此后的代碼通過Form2變量訪問已經被釋放的TForm2實例。
另一種方法是在窗體的OnClose事件中將變量Action設置為caFree。
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree; // TCloseAction = (caNone, caHide, caFree, caMinimize);
Form2 := nil;
end;
這兩種方法沒有什么本質區別,可以根據實際情況來使用,但是一定不要忘記在釋放資源后將變量指向空,不然很容易出現非法訪問的情況。實際上在TForm2的FormClose中寫Form2 := nil 是無用的,應該寫在創建Form2的單元中,因為這兩個Form2變量是不同的,TForm2所在單元的Form2變量是一個私有變量,別人是訪問不到的,別人可以訪問到的,也就是可能觸發非法訪問的是在TForm2所在單元外的Form2變量。
注:Delphi無論釋放窗體還是其它什么變量,都是使用Free而不是Destroy方法,后者是內部調用的,在FormCreate或Free方法被調用時會自動調用到。
Delphi 單元文件結構
unit Unit1;
interface
{接口部分開始}
uses
{引用單元列表,這是可選的,如果包含必須緊跟interface關鍵字}
{接口部分聲明常量/類型/變量/過程和函數,這些聲明對引用單元就像自己的聲明一樣}
{在接口部分聲明的過程和函數,就像使用了forward關鍵字}
{接口部分結束}
implementation
{實現部分}
uses
{如果包含uses字句,必須緊跟關鍵字implementation}
{在這里實現interface中定義的過程和函數,可以任意順序的定義和調用.}
{在這里可以省略過程和函數的列表,如果包括,必須一樣.}
{可以定義單元私有的常量/類型(包括類)/變量/過程和函數,但這些對引用單元的客戶是不可見的}
{$R *.dfm}
{如果是對應窗體的單元文件,會有這句. $R 指令用於加載一個外部資源文件, 這里是指加載同名的窗體文件一起編譯.}
initialization
{初始化部分}
{程序啟動時先執行,並順序執行}
{一個單元的初始化代碼運行之前,就運行了它使用的每一個單元的初始化部分}
finalization
{結束化部分,程序結束時執行}
end.