程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> delphi程序設計.2

delphi程序設計.2

編輯:Delphi

4.4.1.2.打開無模式窗體
要打開一個無模式窗體,可以調用Show()。無模式窗體與有模式窗體的區別是,用戶可以在無模式窗體和其他窗體之間切換。這樣,用戶就可以同時工作於一個應用程序的幾個部分。下面的代碼演示了怎樣動態創建一個無模式的窗體:

上述代碼同時演示了怎樣防止一個窗體的多個實例存在。記住,無模式的窗體允許用戶與應用程序的其他部分交互。這樣,用戶可以照常使用菜單命令,或者創建TModeless的另一個實例。因此,需要考慮這些實例的創建和刪除問題。
要特別注意窗體的實例:當通過窗體的系統菜單或者窗體上的Close按鈕關閉這個窗體時,窗體並沒有真正從內存中釋放。它仍然還在內存中,除非關閉了主窗體(即應用程序)。在上面這個程序示例中,then後面的語句只會執行一次,前提是這個窗體不是自動創建的。如果希望用戶關閉了窗體就在內存中釋放它,必須處理它的OnClose事件,並且把Action參數設為caFree,這樣,VCL就會在這個窗體關閉時釋放它。

上述代碼解決了窗體實例在內存釋放的問題。不過,還有一個問題,注意下面這行代碼:

這行代碼檢查TModeless的實例是否已經由Modeless變量引用,這實際上就是檢查Modeless是否為nil。盡管第一次進入例程的時候,Modeless可能是nil,但第二次進入這個例程的時候,它已經不是nil。這是因為VCL並沒有把Modeless變量設為nil。因此,必須手工把這個變量設為nil。
與模式窗體不同的是,無法在代碼中判斷無模式窗體什麼時候將刪除。因此,無法在創建窗體實例的例程中刪除窗體的實例。用戶有可能在應用程序正在運行的任何時候關閉無模式窗體。因此,無模式窗體本身一定要把Modeless變量設為nil,而且最好在處理窗體的OnDestroy事件的處理過程中設置這個變量:

這樣就能保證每次關閉窗體時,Modeless變量總是被設為nil,從而防止Assigned()函數失敗。記住,同一時刻只能創建TModeless的一個實例。
注意:對於無模式窗體來說,要避免出現下列有缺陷的代碼:

上述代碼會導致每次都創建窗體的實例,重復了被Form1引用的以前的實例,從而消耗了大量的內存。盡管通過Screen.Forms可以訪問這些實例,但最好還是盡量避免使用上述代碼。向構造器Create()傳遞nil造成無法在Form1實例變量被覆蓋後,無法再引用這個窗體實例指針。

4.4.1.3.管理窗體的圖標和邊框
TForm有一個BorderIcons屬性,它是一個集合,包含下列元素:biSystemMenu、biMinimize、biMaximize和biHelp。只要讓這個集合不包含其中的某個元素,就可以使窗體上不出現相應的系統菜單、最大化按鈕和最小化按鈕,但窗體上總是有關閉按鈕。
還可以通過BorderStyle屬性改變窗體的非客戶區。BorderStyle屬性的定義如下:

BorderStyle屬性可以使窗體具有下列特征:
1. bsDialog不能重設大小,只有關閉按鈕。
2. bsNone沒有邊框,不能重設大小,沒有按鈕。
3. bsSingle不能重設大小,有所有按鈕。如果biMinimize和biMaximize中只有一個按鈕被設為False,那麼窗體上有兩個按鈕。但設為False的按鈕不可用。如果二者均為False,那麼沒有按鈕在窗體上顯示。如果biSystemMenu,則沒有按鈕顯示。
4. bsSizeable有邊框,有所有按鈕,按鈕情況與bsSingle一樣。
5. bsSizeToolWin可以重設大小,只有關閉按鈕和標題欄。
6. bsToolWindow不能重設大小,只有關閉按鈕和標題欄。
注意:在設計時修改BorderIcon和BorderStyle屬性並不立即反映出來。這些變化要到運行期才能看到效果。其實,TForm的大部分屬性都是這樣的,這是因為在設計時修改窗體的外觀沒有多大意義。例如,假設把Visible屬性設為False,如果窗體不再顯示出來,那麼就無法操作窗體上的組件。
粘上標題!
你可能注意到了,上面的選項沒有一個選項能夠創建一個沒有標題但可以重設大小的窗體。要實現這種特殊窗體,需要覆蓋窗體的CreateParams()方法,然後設置相關的風格。下面的代碼演示了這一點:

第21章"編寫自定義組件"將進一步介紹CreateParams()的用法。
清單4-2列出了怎樣在運行時修改BorderIcon和BorderStyle屬性的有關代碼:
清單4-2BorderStyle/BorderIcon項目的主窗體單元

注意:TForm的部分屬性用於設置窗體的外觀,部分屬性用於設置窗體的行為。要想進一步了解TForm的屬性,請查找Delphi5幫助系統。

4.4.1.4.窗體重用性:可視化窗體繼承
Delphi5的一個重要功能就是可視化窗體繼承。在Delphi的第一個版本中,可以創建一個窗體,然後把它保存為模板,以後可以在模板的基礎上創建新的窗體。但這並不是真正的繼承,因為無法訪問祖先窗體的組件、方法和屬性。而對於真正的繼承來說,派生的窗體與祖先窗體可以共享相同的代碼。
繼承的優勢在於,應用程序可以做得比較精巧。另外,當祖先窗體的代碼改變時,派生窗體會跟著改變。
對象庫
Delphi5提供了對象管理功能,允許程序員共享窗體、對話框、數據模塊和項目模板。這個功能稱為"對象庫(ObjectKepository)"。通過對象庫,開發者可以共享其他項目的對象。另外,通過繼承對象庫中已有的對象,可以最大程度地實現代碼重用。第4章講到了對象庫。最好要熟悉對象庫的功能。
提示:在網絡環境中,可能要與其他程序員共享窗體模板,這時需要創建一個共享的庫。在Environment|Options對話框中,可以指定共享庫的位置。每一個程序員必須把一個網絡驅動器映射到這個位置。以後當程序員使用File|New菜單命令時,Delphi就會檢查共享庫所在的目錄。
繼承另一個窗體是很簡單的,因為這已成為Delphi5環境內置的功能。要基於一個已有的窗體創建一個新的窗體,只要使用File|New菜單命令,Delphi將打開New Items對話框。這個對話框列出了對象庫中的所有對象。翻到Forms頁,這裡列出了所有已經加到對象庫中的窗體。
注意:不必在對象庫中查找就能繼承一個本項目中的窗體。使用File|New菜單命令,然後選擇Project頁。在那裡,可以選擇一個本項目中已有的窗體。顯示在Project頁中的窗體並不在對象庫中。
有一些列出的窗體就是以前加入到對象庫中的。可能注意到,有三個選項用於把窗體加到項目中:Copy、Inherit和Use。
如果選擇Copy,則意味著把所選窗體的副本加到當前項目中。如果對象庫中的窗體發生變化,不會影響到當前項目中的副本。
如果選擇Inherit,則意味著從所選窗體派生出一個新的窗體加到當前項目中。如果對象庫中的窗體發生變化,則派生的窗體也會跟著變化。
如果選擇Use,則意味著所選的窗體直接加到當前項目中,就好像這個窗體是當前項目創建的一樣。在設計時對這個窗體的任何修改都會影響以Inherit方式使用這個窗體的項目。

4.4.2TApplication類
任何基於窗體的Delphi5程序都包含一個全局變量Application,它的類型是TApplication。TApplication封裝了一些屬性和方法,使應用程序能夠正確地在Windows環境下運行。這些方法中,有的用於建立窗口類定義,有的用於創建應用程序的主窗口、激活應用程序、處理消息、添加上下文敏感的幫助以及處理VCL的異常。
注意:只有基於窗體的Delphi應用程序才有全局Application對象,而控制台程序和服務程序沒有Application對象。
一般不需要關心TApplication在背後到底做了些什麼,不過,有時需要了解TApplication的詳細情況。
由於TApplication並不在Object Inspector中出現,所以不能在設計時修改它的屬性,但可以用Project|Options菜單命令,翻到Application頁,設置一些有關TApplication的屬性。在大多數情況下,只能在運行時工作於TApplication的實例即Application。也就是說,只能在運行時設置Application的屬性、方法和事件過程。

4.4.2.1.TApplication的屬性
TApplication具有幾個屬性,可以在運行時訪問它們。下面將介紹這些屬性以及怎樣通過它們改變Application的默認行為。這些屬性在Delphi5的在線幫助中也有介紹。
(1)TApplication.ExeName屬性
ExeName屬性能夠返回應用程序的全路徑和文件名。這個屬性在運行時是只讀的,不能修改它。但是可以讀它,以使用戶知道應用程序是從哪兒運行的。例如,下面的代碼把ExeName屬性的值顯示在主窗體的標題欄上:

提示:使用ExtractFileName()函數可以從ExeName屬性中得到文件名:

使用ExtractFilePath()函數可以從ExeName屬性中得到全路徑:

使用ExtractFileExt()函數可以從ExeName屬性中得到文件擴展名:

(2)TApplication.MainForm屬性
在前面的例子中,可以看到怎樣訪問MainForm來修改它的Caption屬性以顯示應用程序的ExeName值。MainForm的類型是TForm,可以通過MainForm訪問TForm的任何屬性和方法。也可以訪問加到派生窗體的屬性,只要把MainForm強制轉換為該窗體的類型:

MainForm是一個只讀的屬性。只能在設計時通過Project Options對話框上的Forms頁把一個窗體指定為主窗體。
(3)TApplication.Handle屬性
Handle屬性是一個HWND(一個用於Win32 API的窗口句柄)。一般情況下,用不著訪問Handle屬性,除非要修改Application的默認行為,而Delphi又沒有提供相應的方法。此外,調用某些Win32 API時可能也需要用到Handle屬性,因為那些API需要傳遞應用程序的窗口句柄。後面將更詳細地討論Handle屬性。
(4)TAppllcation.Icon和TApplication.Title屬性
Icon屬性用於設置當應用程序最小化時代表應用程序的圖標。可以修改Icon屬性來改變應用程序的圖標。後面的4.6.1節"在項目中添加資源"將詳細介紹這一點。
在Windows95/98的任務欄上,顯示在圖標右邊的文字通過Title屬性設置。如果應用程序在Wndows NT下運行,則文字顯示在圖標下面。下面的代碼演示了怎樣修改Title屬性:

(5)其他屬性
Active是一個只讀的屬性,它的值表明應用程序是否激活和具有輸入焦點。
ComponentCount屬性表明應用程序所包含的組件數,如果Application.ShowHint屬性設為True的話,那麼這些組件主要是指窗體和THintWindow實例(即提示窗口)。對於那些沒有擁有者(owner)的組件來說,ComponentIndex屬性總是-l。因此,TApplication.ComponentIndex總是-1。這個屬性主要用於窗體和窗體中的組件。
Components屬性是一個數組,它的元素就是那些屬於Application的組件。Components數組的元素個數就是TApplication.ComponentCount屬性的值。下面的代碼演示了在一個列表框中列出所有組件的類名:

HelpFile屬性用於指定幫助文件的文件名。需要向TApplication的HelpContext方法以及其他類似的方法傳遞幫助文件的文件名。
TApplication.Owner屬性總是nil,因為TApplication不可能被另個組件擁有。
ShowHint屬性用於設置是否允許顯示提示條。Application.ShowHint屬性覆蓋其他組件的ShowHint值。如果Application.ShowHint屬性設為False,則所有組件的提示條都不會顯示。
如果應用程序的主窗體被關閉,或者調用了TApplication.Terminate(),則Terminated屬性為True。

4.4.2.2.TApplication的方法
應當熟悉TApplication的有些方法。下面就討論這些方法。
1.TApplication.CreateForm()方法
TApplication.CreateForm()是這樣聲明的:

這個方法用於創建一個窗體的實例,InstanceClass參數用於指定這個窗體的類,創建的實例由Reference參數返回。在項目文件中你可能看到過CreateForm的用法。例如,下面的代碼創建TForml類型的實例Form1:

如果Form1出現在Project|Options對話框的Auto-Create列表中,Delphi5會自動生成上面這一行代碼。不過,對於那些沒有出現在Auto-Create列表中的Form,可以在程序的任何一個地方調用CreateForm()來創建它的實例。其實,CreateForm()相當於窗體本身的Create(),但TApplication.CreateForm()會檢查MainForm屬性是否為nil。如果是的話,CreateForm()會把新創建的窗體作為主窗體。一般情況下,不要調用CreateForm(),而要調用窗體本身的Create()。
2.TApplication.HandleException()方法
HandleExcePtion()用於顯示項目中出現的異常的有關信息。信息將顯示在一個由VCL定義的標准的異常信息框中。如果希望用自己的方式來顯示異常信息,可以響應Application.OnException事件。後面的4.6.5節"覆蓋應用程序的異常處理"將詳細介紹。
3.TApplication的HelpCommand()、HelpContext()和HelpJump()方法
HelpCommand()、HelpContext()和HelpJump()分別提供了一種讓應用程序與WINHELP.EXE程序提供的幫助系統交互的方式。其中,HelpCommand()用於執行一條WinHelp宏命令和幫助文件中定義的宏;HelpContext()用於打開一個幫助主題,主題的編號由Context參數傳遞;HelpJump()類似於HelpContext(),但它的JumpID參數需要傳遞一個字符串。
4.TApplication.ProcessMessages()方法
ProcessMessages()用於從Windows消息隊列中檢索任何等待處理的消息並進行處理。如果程序正在執行一個很長的循環而又不希望中斷其他代碼的執行(諸如響應"放棄"按鈕),這時候就要用到ProcessMessages()。相反,TApplication.HandleMessages()如果發現沒有消息,它就使應用程序處於空閒狀態,而ProcessMessages()則不會使應用程序處於空閒狀態。在第10章中將用到ProcessMessages()方法。
5.TApplication.Run()方法
Delphi5會自動把Run()放到項目文件的主代碼塊中。不要自己去調用這個方法,但需要知道這個方法到底干了些什麼。首先,TApplication.Run()建立一個退出過程,以保證當應用程序退出運行時所有的組件都會得到釋放。然後,它就建立一個循環來處理消息,直到應用程序終止。
6.TApplication.ShowException()方法
ShowException()需要傳遞一個異常類作為參數,它將顯示有關該異常的信息的消息框。後面的4.6.5節"覆蓋應用程序的異常處理"將詳細介紹ShowException()。
7.其他方法
TApplication.Create()用於創建TApplication的實例。不過,這個方法是Delphi5內部調用的,應用程序本身不應調用它。
TApplication.Destroy()用於刪除TApplication的實例。不過,這個方法是Delphi5內部調用的,應用程序本身不應調用它。
TApplication.MessageBox()用於打開一個Windows消息框。不過,這個方法不需要像Windows的MessageBox()函數那樣傳遞窗口句柄。
TApplication.Minimize()用於把應用程序的主窗口最小化。
TApplication.Restore()用於把應用程序的主窗口恢復為最大化或最小化之前的大小。
TApplication.Terminate()用於終止應用程序的執行。與Halt()不同的是,Terminate()會隱含調用PostQuitMessage()看看還有什麼消息要處理。
注意:調用TApplication.Terminate()可以終止應用程序。Terminate()會調用Windows的PostQuitMessage()函數向應用程序的消息隊列中發一個消息。VCL據此釋放應用程序創建的所有對象。要說明的是,並不是一調用Terminate()就馬上使應用程序終止,而是當應用程序檢索到WM_QUIT消息時才會真正終止。而Halt()立即終止應用程序的執行,但不釋放先前創建的對象,也不會返回到調用Halt()的地方。

4.4.2.3.TApplication的事件
TApplication有一些事件,可以建立處理這些事件的處理方法。在舊版本Delphi中,TApplication的事件在Object Inspector上是找不到的(例如針對組件面板上的組件和窗體的事件)。要建立處理一個事件的處理方法,必須先聲明一個作為處理方法的方法,然後在運行期動態地把此方法賦給某個事件屬性。後面將以OnException事件為例說明怎樣建立處理TApplication事件的處理方法。表4-2列出了TApplication的所有事件。表4-2 TApplication和TApplicationEvents的事件

本章的後續內容以及其他章節還將使用TApplication。
注意:TApplication.OnIdle事件適合於做一些不需要用戶交互的動作,例如,在應用程序空閒的時候根據應用程序的狀態更新菜單欄和工具欄。

4.4.3TScreen類
TScreen類封裝了有關應用程序運行於的屏幕的狀態信息。TScreen既不能作為組件加到窗體上,也不能在運行時動態地創建它。Delphi5會自動創建一個TScreen類型的全局變量叫Screen。TScreen的有些屬性是很有用的,這些屬性如表4-3所列。表4-3 TScreen的屬性

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved