在Delphi 中用程式實現自定義窗體的建立和顯示順序(2) (轉)
在 中用實現自定義窗體的建立和顯示順序(2)
以上方法雖然可以實現動態的有選擇地建立和顯示窗體,但是有一個致命的弱點,就是程式關閉的轉移,不能保留Form1的程式關閉許可權。怎樣真正實現有選擇的建立和顯示窗體,並且能保持Form1為主窗體呢?方法如下::namespace prefix = o ns = "urn:schemas--com::office" />
把3個窗體都放置在Auto-create forms裡面,即3個窗體都自動建立。
在Form1中設定一個全域性變數
var
flag:Integer;
然後把上面Form1那段程式碼改成如下所示:
procedure TForm1.FormCreate(Sender: T);
var
rannum:Integer;
begin
flag:=0;
Label1.Caption:='Form1 Create Complete!';
Randomize;
randomnum:=Random(10);
if (randomnum>0)and (randomnum<=4) then
flag:=2
else if (randomnum>4)and (randomnum<=8) then
flag:=3
else
flag:=1;
end;
(程式碼6)
然後,在Form2的OnCreate() 事件中加入以下程式碼:
procedure TForm2.FormCreate(Sender: TObject);
begin
Label1.Caption:='Form2 Create Completed!';
end;
在Form3的OnCreate() 事件中加入以下程式碼:
procedure TForm3.FormCreate(Sender: TObject);
begin
Label1.Caption:='Form3 Create Complete! (' +IntToStr(flag)+') ';
Form3.H;
if flag=3 then
Begin
Form3.Visible:=True;
End
else if flag=2 then
Begin
Form2.Visible:=true;
End
else if flag=1 then
Begin
Form1.Show;
end;
(程式碼7)
還要記得把Form2和Form3的FormStyle屬性改成fsStayOnTop,把Form1的FormStyle屬性設成fsNormal,否則無法在螢幕的最前端顯示所需要的窗體。把Form2和 Form3的Visible屬性設成False,否則程式將無法正確地Focus(聚焦)於所需窗體。經過這樣的修改之後就能根據隨機結果選擇最終要顯示的窗體。
分析一下上面的過程可知道,窗體1,2,3是按順序建立的,但是在Form1的建立過程中設定了一個全域性變數作為記錄的標記,記錄應該顯示的是哪個窗體,Form2的建立過程沒有做任何動作,只是簡單的一個顯示資訊,而在Form3的建立過程中則判斷標誌flag的值,由此決定究竟應該顯示哪個窗體。
注意到主窗體是一定會顯示出來的,這也是Form1的Visible沒有設定成 False的原因,因為即使設定成False,也是會顯示出來的。
以上所說的方法,其中的3個窗體都是已經被完全建立的,只是其中一個或兩個沒顯示出來而已(設定成Visible為False),如果現在開啟Spy++,可以清楚地看到3個視窗都在。但是我們的目的不僅僅如此,我們還要實現窗體建立的動態性和選擇性。
前面說過使用Appliation.CreateForm()的方法來動態建立窗體有它的侷限性,就是所謂的許可權的轉移。實際上我們可以改變這種情形,方法如下:
在Project1.dpr中只建立Form1
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
在Form1的OnCreate()中的程式碼和程式碼5一樣。Form2,Form3的OnCreate()不需要任何程式碼, 這時程式的關閉許可權還是沒有回到Form1的手裡,其實我們只要在Form1的OnClose()中加入一句就行了:
Application.Tenate;
如果不加入這一句,則關閉Form1是不會關閉整個應用程式的,必須關閉Form2或Form3才行。 有些人可能會問,為什麼不是Free而是Terminate呢?查一下Delphi的幫助關於Free的描述,其中有一個注意事項如下所述:
Warning: Never explicitly free a component within one of its own event handlers or the event handler of a component it owns or contains. For example, don’t free a button, or the fothat owns the button, in its OnClick event handler.
可以看到,在Delphi中不能在一個它自己的事件處理中明確地釋放這個元件。這就是為什麼不能用Application.Free的原因。必須用Application.Terminate這一句來釋放窗體建立的資源,否則將出現資源沒有釋放的錯誤。如何知道資源沒有釋放呢?在Delphi則體現為Project在Running狀態,並且需要透過Run->Program Reset來結束程式;另外,如果把程式Build了之後,脫離Delphi編譯器直接執行程式,然後關閉Form1,這時候開啟的工作管理員,在程式一頁將顯示Project仍然在,佔用著和,需要透過結束程式來去掉它。
關於Application.Terminate,Delphi的幫助檔案有這樣的描述:
Call Terminate to end the application programmatically. By calling Terminate rather than freeing the application object, you allow the application to shut down in an orderly fashion.
這裡,Delphi很明確的告訴我們,Terminate而不是Free,可以讓應用程式以整齊的方式關閉。
到這裡我們的任務還沒結束,我們只是讓Form1 和Form2或者是Form3有同等的關閉程式的許可權,我們還要剝奪Form2或是Form3的程式關閉權,方法是在Form2和Form3的OnClose()事件中加入一句Application.Run,這樣按Form2和Fomr3的關閉按鈕都不會有什麼反應了,當然也就不會關閉程式了。我們再新增一個按鈕用來“關閉”窗體,在其Onclik事件中加入一句
Form2.Visible:=False;
所謂的關閉其實是把顯示關閉,而不是把窗體關閉,窗體的資源是沒有釋放的。Delphi的幫助檔案中關於Application.Run的描述不鼓勵我們使用Run,但是從實際使用情況來看,並沒有什麼壞處,只是窗體的關閉按鈕的功能被遮蔽掉了,但是我們有替代的辦法,把窗體的BorderStyle屬性設定成bsNone就可以把窗體的Title標題欄取掉,用其他按鈕或者其他,代替標題欄上的最小化,最大化,關閉按鈕。
到此為止,我們可以說是基本解決了本文開始提出的問題,但是還有一個重要問題我們忽略了,Fom1總是會出現,聰明的你可能想到了在Project.dpr中編寫一些程式碼來處理,對極了,請看下面程式碼:
program Project1;
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,
Unit1 in 'Unit1.pas' {Form1},
Unit2 in 'Unit2.pas' {Form2},
Unit3 in 'Unit3.pas' {Form3};
{$R *.res}
var
randomnum:Integer;
begin
Application.Initialize;
Randomize;//設定隨機器
randomnum:=Random(10);//在0到10之間取隨機值
if (randomnum>0)and (randomnum<=4)then//如果隨機值在0到4之間
Begin
Application.CreateForm(TForm2, Form2);
End
else if (randomnum>4)and (randomnum<=8)then//如果隨機數在4到8之間
Begin
Application.CreateForm(TForm3, Form3);
End
Else //如果隨機數在8到10之間
Begin
Application.CreateForm(TForm1, Form1);
End;
Application.Run;
end.
實現以上程式碼後,Form1,Form2,Form3不用寫任何處理程式碼,不用修改任何屬性,就能解決我們的問題,我們可能要慨嘆了,為什麼一開始沒想到這樣做。
三. 總結
使用Appliation.CreateForm()的方法來動態建立窗體有它的侷限性,本文介紹了一個簡單而實用的方法用來動態顯示窗體,這種方法的關鍵是設定一個標誌,根據實際情況給標誌賦值,等到全部窗體建立完畢後,根據所設標誌決定需要顯示的窗體。但是這種方法的缺點是所有的窗體都將被建立。本文介紹了另外一種方法,這種方法能真正實現動態選擇建立窗體,但是同樣存在缺點,就是程式關閉許可權被平均化了,但是我們有相應的解決辦法。這兩種方法各有其優缺點,為此我們用到第三種方法,在Project.dpr中編寫程式碼實現窗體的動態選擇建立,到此則完滿地解決了本文開始提出的問題。
如果讀者有更好的建議或解決辦法,歡迎指教,我的E是.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-960878/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Django Admin自定義app中模型顯示順序DjangoAPP模型
- 在Delphi中實現任意形狀的窗體 (轉)
- [安卓] 16、ListView和GridView結合顯示單元實現自定義列表顯示效果安卓View
- 在VB中用API實現多媒體 (轉)API
- 小程式自定義modal彈窗封裝實現封裝
- mysql自定義排序順序語句MySql排序
- java使用sshd 實現sftp 自定義顯示目錄JavaFTP
- 列定義的順序和列儲存的順序
- avalonia實現自定義小彈窗
- Qt 把窗體顯示在螢幕的中心QT
- MySQL自定義變數執行順序MySql變數
- Excel--使用VBA Code 動態建立、修改和刪除自定義窗體程式碼摘抄Excel
- 程式介面多模式顯示的實現 (轉)模式
- Jquery實現自定義訊息彈窗jQuery
- 自定義來電顯示
- 顯示驅動程式和硬體 (轉)
- 在執行時顯示或隱藏窗體的標題欄 (轉)
- 順序表的實現
- 順序跳躍顯示陣列中的值陣列
- django自定義構建模板,透過bootstrap實現選單隱藏和顯示Djangoboot
- 資料結構實驗一:順序表的建立與操作實現、順序表實現約瑟夫環問題資料結構
- 在Delphi中開發使用多顯示器的應用程式
- 在VB中實現窗體的動態效果 (轉)
- 自定義xunit測試用例的執行順序
- Qt程式設計技巧 窗體居中顯示QT程式設計
- 自定義SeekBar顯示進度
- MUI DtPicker 顯示自定義日期UI
- 在 Avalonia 程式中新增自定義字型,並最佳化字型顯示效果自定義字型
- CAD中的物件顯示順序如何設定物件
- FrameLayout裡有CardView造成的顯示順序問題View
- 順序棧的實現方式
- 讓 排序 按照 in 列表的的顯示順序排序輸出。排序
- 如何在一個自定義視窗中顯示(文字區域)顯示在DOS下執行JAVAC\JAVA時所觸發的異常?Java
- 使用自定義任務審批欄位建立 SharePoint 順序工作流
- 安卓自定義View實現圖片上傳進度顯示(仿QQ)安卓View
- 如何自定義終端顯示配置
- Java實現順序表Java
- Delphi在dbgrideh中新增Img顯示blobIDE