標籤: 暫無標籤

Delphi是著名的Borland(現在已和Inprise合併)公司開發的可視化軟體開發工具。「真正的程序員用c,聰明的程序員用Delphi」,這句話是對Delphi最經典、最實在的描述。Delphi被稱為第四代編程語言,它具有簡單、高效、功能強大的特點。和VC相比,Delphi更簡單、更易於掌握,而在功能上卻絲毫不遜色;和VB相比,Delphi則功能更強大、更實用。可以說Delphi同時兼備了VC功能強大和VB簡單易學的特點。它一直是程序員至愛的編程工具。

1 Delphi -基本簡介

DelphiDelphi

Delphi具有以下的特性:基於窗體和面向對象的方法,高速的編譯器,強大的資料庫支持,與Windows編程緊密結合,強大而成熟的組件技術。但最重要的還是Object Pascal語言,它才是一切的根本。 Object Pascal語言是在Pascal語言的基礎上發展起來的,簡單易學。

Delphi提供了各種開發工具,包括集成環境、圖像編輯(Image Editor),以及各種開發資料庫的應用程序,如DesktopDataBase Expert等。除此之外,還允許用戶掛接其它的應用程序開發工具,如Borland公司的資源編輯器(Resourse Workshop)。

在Delphi眾多的優勢當中,它在資料庫方面的特長顯得尤為突出:適應於多種資料庫結構,從客戶機/服務機模式到多層數據結構模式;高效率的資料庫管理系統和新一代更先進的資料庫引擎;最新的數據分析手段和提供大量的企業組件。

Delphi發展從Delphi1、Delphi2到現在的Delphi5,不斷添加和改進各種特性,功能越來越強大。Delphi5添加了對IDE(集成開發環境)的很多改進新特性,擴展了資料庫支持(ADO和InterBase資料庫),帶有Internet支持的MIDAS改進版,TeamSouse版本控制工具,轉換功能,框架概念以及很多的新組件與新特性。

Delphi5功能十分完善和強大,本欄目將以它為基礎,介紹Delphi的開發環境、基本概念、控制項的使用、常用的編程方法和編程技巧。本欄目的對象為Delphi初學者,主旨是幫助初學者更快更好掌握Delphi基本的編程方法和技巧。

2 Delphi -程序之父

Anders Hejlsberg,丹麥人,曾在丹麥科技大學學習工程學。Anders Hejlsberg第一次登上軟體界歷史舞台是在80年代早期,因為他為MS-DOS和CP/M設計了一個Pascal編譯器。當時,還是一個小公司的Borland很快僱用了他,並買下了他的編譯器,改稱Turbo Pascal。在Borland,Hejlsberg繼續開發Turbo Pascal,並最終帶領他的小組設計了Turbo Pascal的替代品、開發工具史上的奇迹:Delphi語言。

3 Delphi -編程入門

DelphiDelphi

Delphi是全新的可視化編程環境,為提供了一種方便、快捷的Windows應用程序開發工具。它使用了Microsoft Windows圖形用戶界面的許多先進特性和設計思想,採用了彈性可重複利用的完整的面向對象程序語言(Object-Oriented Language)、當今世界上最快的編輯器、最為領先的資料庫技術。對於廣大的程序開發人員來講,使用Delphi開發應用軟體,無疑會大大地提高編程效率。 

Delphi實際上是Pascal語言的一種版本,但它與傳統的Pascal語言有天壤之別。一個Delphi程序首先是應用程序框架,而這一框架正是應用程序的「骨架」。在骨架上即使沒有附著任何東西,仍可以嚴格地按照設計運行。您的工作只是在「骨架」中加入您的程序。預設的應用程序是一個空白的窗體(Form),您可以運行它,結果得到一個空白的被放大縮小、移動、最大最小化等,但您卻沒有編寫一行程序。因此,可以說應用程序框架通過提供所有應用程序共有的東西,為用戶應用程序的開發打下了良好的基礎。Delphi已經為您做好了一切基礎工作——程序框架就是一個已經完成的可運行應用程序,只是不處理任何事情。您所需要做的,只是在程序中加入完成您所需功能的代碼而已。

在空白窗口的背後,應用程序的框架正在等待用戶的輸入。由於您並未告訴它接收到用戶輸入後作何反應,窗口除了響應Windows的基本操作(移動、縮放等)外,它只是接受用戶的輸入,然後再忽略。Delphi把Windows編程的回調、句柄處理等繁複過程都放在一個不可見的Romulam覆蓋物下面,這樣您可以不為它們所困擾,輕鬆從容地對可視部件進行編程。

面向對象的程序設計(Object-Oriented Programming,簡記為OOP)是Delphi誕生的基礎。OOP立意於創建軟體重用代碼,具備更好地模擬現實世界環境的能力,這使它被公認為是自上而下編程的優勝者。它通過給程序中加入擴展語句,把函數「封裝」進Windows編程所必需的「對象」中。面向對象的編程語言使得複雜的工作條理清晰、編寫容易。說它是一場革命,不是對對象本身而言,而是對它們處理工作的能力而言。對象並不與傳統程序設計和編程方法兼容,只是部分面向對象反而會使情形更糟。除非整個開發環境都是面向對象的,否則對象產生的好處還沒有帶來的麻煩多。而Delphi是完全面向對象的,這就使得Delphi成為一種觸手可及的促進軟體重用的開發工具,從而具有強大的吸引力。

一些早期的具有OOP性能的程序語言如C++,Pascal,Smalltalk等,雖然具有面向對象的特徵,但不能輕鬆地畫出可視化對象,與用戶交互能力較差,程序員仍然要編寫大量的代碼。Delphi的推出,填補了這項空白。您不必自己建立對象,只要在提供的程序框架中加入完成功能的代碼,其餘的都交給Delphi去做。欲生成漂亮的界面和結構良好的程序絲毫不必絞盡腦汁,Delphi將幫助您輕鬆地完成。它允許在一個具有真正OOP擴展的可視化編程環境中,使用它的Object Pascal語言。這種革命性的組合,使得可視化編程與面向對象的開發框架緊密地結合起來。

 在這一節中,來開發一個小程序。隨著開發的過程,逐步介紹Delphi的主要部件及其操作方法。建議讀者按照本書介紹的過程,在您的電腦上直接操作。您將對Delphi的可視化編程有一個直觀、快捷的了解,必將起到事半功倍的效果。 

4 Delphi -安裝方法

DelphiDelphi

Delphi的安裝與其它應用軟體並無不同。2.0版必須在Windows 95以上的操作系統中使用。啟動Windows 95或Windows NT后,將Delphi的光碟放入光碟機(CD-ROM)中,運行光碟上的\INSTALL\SETUP.EXE文件,它的安裝程序會提示您正確地裝入Delphi。如果您是在微軟中文Windows環境中安裝Delphi,請參照附錄A來設置您的BDE環境,以便於處理中文數據。 

為避免隱藏在Delphi后的Program Manager和曾經運行過的其它程序擾亂版面,分散您的注意力,不妨在啟動Delphi前關掉其它應用程序;啟動Delphi后,再最小化隱藏在後面的Delphi 2.0程序組。這樣屏幕上就只留下Delphi窗口可見了。

首次載入Delphi,屏幕上會出現四個窗口:

標題為「Delphi-Project1」的Delphi主窗口

Object Inspector窗口

標題為「Form1」的窗體(Form)窗口

標題為「Unit1.PAS」的代碼編輯窗口。剛啟動時這一窗口的大部分被「Form1」窗體所掩蓋。將「Form1」窗體移開,或單擊Form1窗體下方的狀態行,可以使其全部可見。在「Form1」窗體的任意可見位置單擊滑鼠,可以恢復主窗體可見。

Delphi的主窗口位於屏幕的上端,包括Menu(菜單)、Speed Bar(加速條)和Component Panel(部件選項板)。Menu是下拉式主菜單。Speed Bar位於主窗口的左下端,由兩排共14個加速按鈕組成。這些按鈕是菜單功能的快捷方式,各種圖標直觀地表示了它能執行的動作。Component Panel由一行、若干頁對象按鈕所組成,利用它來選擇需要的部件並將它放到窗體中去。 

Object Inspector窗口含有兩頁:Properties頁顯示窗體中當前被選擇部件的屬性信息,並允許改變對象的屬性;Events頁列出了當前部件可以響應的事件。按動Object Inspector下端的「Events」頁標籤,使得Events頁可見,這一定的事件後邊的空白處,可以定義對象接受到相應事件時執行的動作。首次啟動時,Object Inspector窗口顯示的是當前窗體Form1的屬性。Object Inspector根據對象屬性的多少,決定是否有滾行顯示。移動滾行條,可以查看當前對象的全部屬性。

此外,Object Inspector上還有Object Selector(對象選擇器),位於Object Inspector上方的下拉式菜單中。它顯示了窗體上所有部件的名稱和類型,也包含窗體本身。您可以用Object Selector很容易地在窗體的各個部件之間切換,也可以快速地回到窗體本身。當窗體中含有較多的對象時,您會發現這是切換對象尤其是回到窗體的最快捷途徑。

想使Object Inspector一直可見,可將滑鼠移到Object Inspector上,按動右鍵,以啟動Object Inspector的彈出式菜單,將其設置為Stay On Top。這對初學者常是一個很重要的設置方式。 

5 Delphi -窗體窗口

DelphiDelphi

Forms窗口是開展大部分設計的工作區域。首次啟動Delphi 2.0時顯示的是窗體Form1。可以把部件放在窗體中,通過移動位置、改變尺寸等操作隨心所欲地安排它們,以此來開發應用程序的用戶界面。您可以把窗體想象成一個可以放置其它部件的容器。窗體上有柵格(Grids),供放置部件時對齊位置用,在程序運行時Grids是不可見的。

一個真正的應用程序可能有不止一個窗口,您可以選用不同的窗體進行設計。其它窗體可以是對話框(Dialog Box)、數據錄入框等。 

代碼窗口一開始處於窗體窗口之下。因為在Delphi中,設計用戶界面直接在窗體中進行,運行結果和設計樣板完全一致。當部件被放到窗體上時,Delphi會自動生成大部分的用戶界面代碼。您所應做的只是在它為您生成的框架中加入完成所需功能的程序段而已。點動Form1的狀態行使代碼窗口可見。 

這個窗口中是代碼編輯器。可以在其中書寫Delphi應用程序的源代碼。當程序中含有不止一個窗口時,會有幾個庫單元的源程序出現在代碼編輯器中。代碼編輯器的標題條中顯示了當前正在編輯的庫單元文件名。要查看某一特定程序的源代碼,只需用滑鼠點動寫有該庫單元文件名的頁標籤,就可以對該庫單元進行編輯了。

6 Delphi -用戶界面

DelphiDelphi

從空白窗體開始工作。將設計一個簡單的程序:在屏幕上開一個窗口,窗口中有一個圖框,用三個按鈕來改變圖框的形狀;再用一個圖標按鈕來進行圖框的顏色設置,通過顏色編輯對話框來選擇變成哪一種顏色。 在菜單上選用File|New Application菜單項來生成新的工程文件。這時,屏幕上出現窗體。 

部件(Component)是建立Delphi應用程序的要素。Delphi為用戶提供了豐富的部件庫,既有可視的部件(如編輯框、按鈕)等,也有不可視的部件(如系統定時器、數據表等)。它們按照功能分別排列在Component Panel的各頁上。

移動滑鼠到Component Panel上,在部件按鈕上「猶豫」一、兩秒鐘,一個黃色小提示框就會彈出,寫有該部件的名稱,稱之為提示(Hint)。在要選擇的部件上單擊左鍵,則該部件按鈕被按下,表示部件已被當前選擇。然後,將滑鼠移動到窗體上,按下左鍵,該部件被放到窗體中。部件的輪廓線上會顯現八個被稱為尺寸調整器(Sizing Handles)的黑色小方塊。它除了供用戶調整尺寸使用之外,還可以表示該對象處於當前編輯狀態。此時,按「Delete」鍵可以將該部件刪除。

在Component Panel上,點動寫有「Additional」的頁標籤,切換到Additional頁,再移動滑鼠,逐個用觀看Hint的辦法查看部件的名稱,找到「Shape」部件(其圖標為圓、方形、三角形三個幾何體),將其放到窗體的左方。再按動「Standard」頁標籤,找到「Button」部件(圖標上畫有OK按鈕)。Delphi允許在添加多個同類型的部件時,不必每次到部件選項板上選取。按住「Shift」鍵,同時在「Button」部件上單擊滑鼠左鍵,這時「Button」部件處於按下狀態,並有藍色邊框,表示已經被選擇固定。依次在窗體右方的三個位置單擊左鍵,則會放置三個相同的Button部件。把滑鼠游標移到部件選項板左側的箭頭圖標處,這是「取消選擇」按鈕,它沒有提示。按動它,會發現「Button」部件按鈕恢復彈起狀態。否則,每次「Form1」上的滑鼠單擊左鍵動作,都會導致增加一個按鈕部件。

再次進入「Additional」部件頁,選擇一個「BitBtn」按鈕(圖標是有綠色對號的OK按鈕),把它放到其它三個按鈕部件的下面。

點動「Dialog」頁標籤,選擇以16色網格做圖標的ColorDialog部件並把它放到窗體的任意位置。因為這一部件是不可視部件,所以它的位置並不影響大局。 

7 Delphi -部件調整

DelphiDelphi

一般來講,此時放置到窗體的部件是分散排列的,而且其大小不是真正需要的尺寸。除了不可視的ColorDialog部件外,其它的部件都需要進行位置、大小和顯示字樣的調整。Delphi提供的對齊工具和窗口柵格為這些調整提供了方便。

移動部件:只需把滑鼠落到想移動的部件上,按住左鍵並移動游標,到合適的位置再釋放左鍵,整個部件即被移到新位置。

調整尺寸:先把滑鼠游標移動到要改變尺寸的部件上,單擊左鍵,選中該部件,尺寸調整器會出現,把滑鼠移動到其中的一個小黑色方塊上,當滑鼠變成拖動方向指示時,按下並拖動滑鼠左鍵,可以放大或縮小部件。上下左右的小方塊用來移動對應的各邊,四個角的方塊可以移動相連的兩條邊。如果要精確地表述部件的尺寸,可以在Object Inspector上,改變Left(表示部件左邊緣到窗體左邊框的象素點數)、Top(表示窗體上邊框到部件上邊緣的象素點數)、 Width(部件本身的寬度)、Height(部件本身的高度)等屬性。關於改變部件的屬性,下文還將仔細講解。

使得一組部件對齊:用調整位置的方法可以對齊部件,但操作步驟複雜。Delphi提供的對齊工具可以使多個部件的對齊極為迅速方便。下面來使四個按鈕對齊。先將四個按鈕選為一組:按住並向右下方拖動滑鼠左鍵,在窗體上畫出圍繞四個按鈕的矩形,釋放左鍵后,被選中的按鈕周邊會出現暗灰色的邊框。選用Edit|Align命令,或使用彈出式菜單(在被固定的部件上單擊滑鼠右鍵激活),可以顯示圖1.4所示的對話框。

要使按鈕沿左邊對齊並使它們在垂直方向上均勻分佈,先在Alignment對話框的Horizontal欄內選擇「Left sides」,在「Vertical」欄內選擇「Space equally」,按動OK按鈕,Delphi就會自動將它們對齊。然後,您可以將它們四個作為一組來移動。在四個按鈕以外的窗體上按動滑鼠左鍵,就釋放了組中的部件,使它們成為分立的部件。

利用對齊模板來對齊部件也是很方便的。首先要將要對齊的部件選成一組,選擇View|Alignment Palette顯示對齊模板。按照所示的方式選擇即可達到對齊的目的

8 Delphi -鎖定部件

DelphiDelphi

如果部件已經對齊,為防止不小心移動部件,可以將部件位置鎖定。選擇主菜單上的Edit|Lock Controls選項,使得部件不能進行移動操作。解鎖只需再次選擇此項即可。

調整「Shape」部件的大小,使之與右邊的按鈕組相匹配。再改變窗體的大小,按住並拖動窗體右下方使之剛好包容窗體上的全部部件。這樣,您的用戶界面就會比較美觀。及時地保存所做的工作至關重要。對設計者來講,有兩個文件需要保存:庫單元文件(以.PAS為後綴)和工程文件(以.dpr為後綴)。從主菜單上選擇File|Save Project As...項,Delphi會顯示標題為「Save Unit1 As」的文件保存對話框,Delphi 2.0 允許用戶更改存儲路徑,您可以在下拉式列表框中選擇。最好將您的文件保存在自己的目錄中。在編輯框中鍵入demoform.pas以保存庫單元文件;然後顯示標題為「Save Project As」的另一個文件保存對話框,鍵入sample.dpr。Delphi保存這兩個文件並返回窗體窗口。不要把庫單元和工程存成一樣的文件名,Delphi要求兩者不同。

第一次保存后,以後可以隨時通過Speed Bar中的「Save All」和「Save file」來保存工程文件和庫單元文件。一般來講,當確認文件的改變后,要同時存儲這兩個文件。 

運行工程:操作使您有了一個自己的應用程序界面。在速度條中按動「Run」按鈕(繪有綠色三角圖標),您可以看到,所生成的界面與您設計的界面是完全一致的。 

改變對象的屬性:上述的工程雖能夠運行,但它對您的按動按鈕操作是沒有什麼反應的,而且,所有部件上還寫著不需要的字樣。雙擊窗口的關閉按鈕結束運行,回到設計界面。下面,將仔細講述如何在Object Inspector中改變部件的各種屬性。 

用Properties頁改變部件的屬性值:首先要改變各種部件的標題。先給窗口命名為「Demo」。按動Object Inspector上端的Object Selector的題條或者其右端的下拉標誌,找到Form1項,並點動左鍵,窗體被選中。在Object Inspector的Properties頁中,找到Caption屬性並用左鍵選中,將其右端的Form1改為Demo,同時,您會發現窗體的標題已經相應地做了改變。

用滑鼠點中窗體中的Shape部件,Object Inspector列出了它的屬性。選中Shape屬性,您會發現右端出現了下拉標誌。點動這一標誌,可以查看對象的Shape屬性可選值。它的形狀可以是矩形、圓形、圓角矩形、方形等幾種。這是設計後續功能的基礎。

選中Button1按鈕,此時Object Inspector已經顯示出此按鈕的一應屬性。將它的Caption屬性改為「&Rectangle」,「&」號使得Delphi特殊處理它後面的字元,在這裡,按鈕中的R字母被做了下劃線處理,運行時,可以用「Alt-R」熱鍵來按動這一按鈕。同樣,您可以將其它的兩個按鈕Button2和Button3的Caption屬性改成需要的形狀指示,譬如「&RoundRec」、「&Ellipse」。可以把某個按鈕作為窗口上的預設按鈕,Delphi會為按鈕加上有黑色的邊緣。運行時,回車即相當於被按下。只需將此按鈕的Default屬性從False改成True,即將它設為窗體的預設按鈕。點動Default屬性,在右端的值後面雙擊左鍵,或從下拉菜單中選取True,即可改變這一屬性。Delphi中有許多只有True、False兩個屬性的部件,雙擊左鍵可以在這兩個值之間切換。

漢化界面及字體選取 

如果您的Windows95系統中安裝了中文系統,對界面做漢化是極其方便的。例如,您可以將Button1的Caption屬性改成「&R矩形」,同樣地可改變其它部件的屬性,將窗體做成中文的操作界面。

若對中、西文字體不滿意,則可以調整Font屬性以滿足您的要求。Font屬性的前面,有一個小小的「+」號,這說明它表徵的是集屬性,也即屬性不再是一個單值,而是一個屬性的集合。雙擊Font,ObjectInspector將在下面擴充顯示它的其它屬性。Color用來表示文本的顏色,Name定義了字體名,如System,MsSerif,Arial,宋體,黑體等。Style下又擁有四個屬性:fsBold,fsItalic,fsUnderline和fsTrikeOut。如果想讓字體有其中的某種風格,可把相應的屬性值設成True。

Font對話框可以更為直接地設定以上屬性。Font屬性右側值段有帶省略號的按鈕,單擊它可以激活Font對話框,如圖1.7所示:

這一對話框中包含了上述的全部屬性,使得調整字形更為直接方便。但要申明的是,對於窗體Form來講,Font屬性改變的是窗體中其它部件的顯示字形,它本身的標題字體是預設的System字體,不能通過屬性來改變。

使用圖形編輯對話框 

最後,用圖標按鈕BitBtn1來控制Shape部件的顏色。選中圖標按鈕,將它的Caption屬性改為「&Color」(或「&C顏色」)。可以在按鈕中加入一個圖標來形象地表述它的功能。選用ObjectInspector中的Glyph屬性,點動值段的三點按鈕,彈出圖形編輯對話框。

您可以通過圖形編輯對話框裝入圖標,在本常式中,按動Load按鈕,選擇\Delphi2.0\Images\Buttons\Brush.bmp文件裝入,Bitbtn1就成為一個圖標按鈕。另外,Delphi還為您提供了豐富的Windows標準圖標按鈕。想運用它們,改變BitBtn的Kind屬性。用戶不妨嘗試一下,選擇其它值可以生成漂亮的標準按鈕,如OK,Cancel等等。這會使您在以後的程序開發中受益匪淺。

至此,界面的設計工作就已完成了。運行一下觀察效果,別忘記保存您的庫單元文件、工程文件。 

編寫事件處理過程 

完成用戶界面,只是建立了一個「骨架」,下面要做的便是給程序加入「靈魂」,也即,使它能夠完成所要求的功能。 

為用戶操作建立「事件」

單擊窗體上的「Rectangle」按鈕,在ObjectInspector中,點動「Events」頁標籤,出現事件窗口。在本常式中,只關心OnClick事件,即按鈕接收到左鍵單擊時應用程序所作出的反應。在ObjectInspector窗口中雙擊OnClick事件右端的值段,會使得Delphi激活庫代碼編輯器,並將游標停在該按鈕所對應的過程的begin...end之間。「Rectangle」按鈕的功能是使Shape部件的形狀為矩形。聯繫前文查看過的Shape部件的「Shape」屬性,現在,要做的是在程序中控制部件的屬性。

在游標處鍵入以下的程序段: 

Shape1.Shape:=stRectangle; 

用同樣的方法,在Button2和Button3的OnClick事件響應內複製以上語句,並分別將賦值號后的屬性值改為stRoundRect和stEllipse。為防止輸入錯誤導致程序運行出錯,建議您使Shape1部件的ObjectInspector可見,檢視屬性Shape的各個值並對應輸入。

在代碼編輯器中,Delphi自動建立的過程以關鍵字Procedure開頭,用戶可以在begin…end之間加入自己的程序,也可以定義變數。這個程序塊對用戶的外部事件(此例中是按動按鈕)進行響應。稱之為事件處理過程。 

使用顏色編輯對話框 

圖標按鈕「Color」要控制部件Shape1的顏色,可以調入顏色編輯對話框,用以選擇要變成的顏色。這時就要用到運行時不可視的部件ColorDialog了。同樣地使圖標按鈕BitBtn1響應OnClick事件,在它的過程中加入以下的語句:

ColorDialog1.Execute;

Shape1.Brush.Color:=ColorDialog1.Color; 

這樣,圖標按鈕的功能也就完成了。

初學者可能對這樣的程序段不能理解。其實也是十分簡單的。查看ColorDialog的Brush屬性,就會發現它是個集屬性,在其下還有一個Color選項,正是想改變的屬性。既然想將圖形的顏色變得更加豐富多彩,它本身提供的幾種顏色就已不能滿足要求了。用顏色編輯器可以得到更多的色彩。程序的第一句用Execute方法,使得ColorDialog運行它本身。當用戶在對話框中進行操作,選定了一種顏色時,即使得TColorDialog對象的一個屬性Color置為選定顏色的值。將此值賦給Shape1的Brush屬性的子屬性Color,就將選定的顏色加到了圖形上。

讀者的要求可能會是,怎樣儘快的了解這些這些方法、屬性和域呢?下文對使用聯機幫助的簡單介紹可能會對您有所裨益。 

使用聯機幫助Help 

事實上,使用聯機幫助是您全面地了解可用的方法、對象的域、??的常式。較為簡單有效的方法是使用Help中的搜索功能。如果您對一個對象知之甚少,選用主菜單中的Help|HelpTopics項,在彈出的幫助對話框,選用Indexes(「索引」)頁,Delphi2.0會提示您輸入要檢索的主題。以您想用的部件的對象名作為檢索主題詞,可以參閱很多基本的信息。例如,上文的常式中,在編輯框中鍵入對象的名稱TColorDialog,在詞條中就會出現該主題,按動Display按鈕顯示出TColorDialog的幫助信息。查看method,可以找到能應用在CclorDialog1上的方法Execute;仔細閱讀它的功能,上述的編程便不難理解了。Properties中提供了部件的所有屬性,在關鍵屬性KeyProperties前加上了「金鑰匙」,提供了詳盡的說明。在Task中您可以查閱該對象的其它相關主題,還可以參閱Example中的應用常式。

9 Delphi -編程方法

DelphiDelphi

Delphi的編程語言是以Pascal為基礎的。Pascal語言具有可讀性好、編寫容易的特點,這使得它很適合作為基礎的開發語言。同時,使用編譯器創建的應用程序只生成單個可執行文件(.EXE),正是這種結合,使得Pascal成為Delphi這種先進開發環境的編程語言。

本章中,將討論ObjectPascal的主要特點,並講解如何在事件處理過程和其他應用程序中,使用它來編製程序代碼。本章將講解Delphi應用程序中最常用的ObjectPascal語法,而不是Pascal語言的一切細節。如果您完全不熟悉Pascal編程,請參閱一些基礎的Pascal教程。如果您具有編程經驗,並能熟練地使用其他流行程序語言,您將在本章的ObjectPascal中發現一些相同的概念。如果您已經熟悉了BorlandPascal,就可以快速瀏覽或跳過本章。 

編寫ObjectPascal程序代碼 

在前邊的章節中,通過常式,已經編寫了幾行簡單的代碼。在本章中,將從熟悉Pascal編程的角度,配合實例,講解ObjectPascal編程的基本方法。

在編寫自己的ObjectPascal程序時,要注意程序的可讀性。Pascal語言是英式結構語言,在程序中選擇合適的縮排、大小寫風格,並在需要時將程序代碼分行,會使得程序代碼能夠很容易地被自己和他人讀懂。一般的程序員都有這樣的體驗:如果不給程序加上適當的註解,一段時間后,自己也難以理清程序的流程。給程序及時地加上註釋是良好的編程習慣。Delphi的註釋需要加註在{}之間,編輯器會把它們處理成為空白。Delphi保留了BorlandPascal編輯器的風格,關鍵字採用黑體字,被註釋的部分會變暗,這使得編程風格良好,易讀易寫。 

10 Delphi -賦值語句 

DelphiDelphi

在事件處理過程中,最常用到的工作就是把一個新值賦給一個屬性或變數。在設計用戶界面時,可以使用ObjectInspector(ObjectInspector)來改變其屬性;但有時需要在程序執行時改變屬性的值,而且有些屬性只能在執行時改變,這些屬性在Delphi的在線幫助的「Proprety」主題中被標為執行期屬性。進行這種改變,就必須使用賦值語句。

下文的賦值語句表徵一個OnClick事件。當按鈕按動后,將編輯框部件Edit1的Color屬性置為clRed:

procedureTForm1.Button1Click(Sender:TObject);

begin

Edit1.Color:=clRed;

end; 

當按動按鈕后賦值語句被執行,編輯框變成紅色。

在語句中,部件的名稱在屬性前,中間用「.」表示屬性的所屬關係。這樣就準確地指定了要將clRed值賦給哪一部件的哪一屬性。賦值號為「:=」,不論給屬性還是給變數賦值,都是將右邊的值賦給左邊的屬性或變數。

當將一個屬性值、變數、常量或文本數據賦給屬性或變數時,所賦值的類型和接受此值的屬性或變數的類型應相同或兼容。一個屬性或變數的類型定義了此屬性或變數的可能值集合,也定義了程序代碼可以執行的運算。在前邊的常式中,編輯框部件的Color屬性和clRed的類型都是TColor。可以在在線幫助中找到一個屬性的類型;另外一種方法是在ObjectInspector中選定該屬性值段,並按下F1鍵,則類型將在屬性說明的結尾處列出,例如Color屬性列出下邊的語句: 

PropertyColor:TColor; 

有些屬性是只讀(ReadOnly)的,它們只能被讀取,不能被改變。請查閱在線幫助,在Delphi中這些只讀屬性都有註解。 

標識符的說明與使用 

標識符是Delphi應用程序中一些量的名稱,這些量包括變數(var)、常量(const)、類型(type)、過程(procedure)、方法(Method)及其他,ObjectPascal在應用標識符時,必須首先說明它們。ObjectPascal是強類型語言,它的編譯器可以檢查確保賦給變數或屬性的值是正確的類型,以便於您改正錯誤。因為ObjectPascal是編譯語言,所以Delphi的執行速度要比使用解釋語言快得多。在使用標識符前說明它們,可以減少程序錯誤並增加代碼的效率。 

變數

變數是程序代碼中代表一個內存地址的標識符,而此地址的內存內容在程序代碼執行時可以被改變。在使用變數前必須對它進行說明,即對它進行命名,並說明它的類型。在所有變數說明以前加上保留字var。變數說明左邊是變數的名稱,右邊則是該變數的類型,中間用(:)隔開。 

var

Value,Sum:Integer;

Line:String; 

在窗體中加入一個名稱為Edit1的編輯框,再加入一個名稱(屬性Name)為Add的按鈕部件,並建立如下的事件處理過程:

procedureTForm1.addClick(Sender:TObject);

var

X,Y:Integer;

begin

X:=100;

Y:=20;

Edit1.Text:=IntToStr(X+Y);

end; 

在本例中,當按動ADD按鈕時,編輯框中顯示值120。在ObjectPascal中,必須確保變數或屬性被賦予類型相同或兼容的值。您可以嘗試將賦給X的值改為100.0,或去掉IntToStr函數,在編譯時會出現類型不匹配的錯誤,這也說明了ObjectPascal強類型語言的特點。 

11 Delphi -預定義類型

DelphiDelphi

ObjectPascal有多個預定義的數據類型,您可以說明任何這些類型的變數:

整形:Integer的範圍是-32768到32767,佔2位元組的內存;Shortint從-128到127,佔1位元組內存;Longint從-2147443648到2147483647佔4位元組內存;Byte從0到255,佔1位元組;Word從0到65535,佔2位元組內存。它們都是沒有小數部分的數字。

實型:Single可以包含7到8位有效小數部分,佔用4位元組的內存;Double類可以包含15到16位有效小數部分,佔用8位元組的內存;Extended類型包含19到20位有效小數部分,佔用10位元組內存;Comp可以包含19到20位有效小數部分,佔用8位元組內存。以上實數類型只有在8087/80287選項[N+]打開才可以使用。Real可以包含11到12位有效小數部分,佔用6位元組內存。它只有在和以前BorlandPascal兼容的情況下才使用,否則應使用Double或Extended。

布爾型:Boolean,只包含true或False兩個值,佔用1位元組內存。

字元型:Char,一個ASCII字元;字元串類型String一串最長可達255個ASCII字元。

指針型:Pointer,可以指向任何特定類型。

字元串型:PChar,是一個指向以零結尾的字元串的指針。

除了預定義類型外,Delphi還有自行定義的類型。上述常式的TColor就是這種類型。此外,用戶還可以定義自己的數據類型,這部分內容將在下文中詳細講述。

整型類別和實型類別都各有五種類型,同一類別中,所有的類型與其他同類別的都相容,您可以將一種類型的值賦給相同類別中不同類型的變數或屬性,而只需要這個值的範圍在被賦值的變數或屬性的可能值範圍內。例如,對於一個Shortint型的變數,可以接受在-128到127範圍內的任意整數,例如Shortint類型的7;您不能將300賦給它,因為300已經超出了Shortint的範圍了。將範圍檢查功能打開(選用Options|Project,並在CompilerOptionsPage中選擇RangeChecking),將會檢查出一個範圍錯誤;如果RangeChecking沒有被打開,那麼程序代碼將可以執行,但被賦值的值將不是您期望的值。

在一些情況下,您可以進行不同類型的變數或屬性的賦值。一般來說,可以將一個較小範圍的值賦給一個較大範圍的值。例如,您可以將整型值10賦給一個接受實型值的Double屬性而使得值成為10.0,但如果將一個Double類型的值賦給整形變數,則會出現類型錯誤。如果您不清楚類型的兼容性,可以參閱Delphi的在線幫助中「TypeCompatibilityandAssignmentCompatibility」主題。 

常量 

常量在說明時就被賦予了一個值,在程序執行過程中是不可改變的。下面的例子說明了三個常量: 

const

Pi=3.14159;

Answer=342;

ProductName="Delphi"; 

象變數一樣,常量也有類型。不同的是,常量假設其類型就是常量說明中其所代表的值的類型。上文的三個常量的類型分別是real型、整形、字元串型。常量用「="表示兩邊的值是相等的。 

12 Delphi -過程函數

DelphiDelphi

過程與函數是程序中執行特定工作的模塊化部分。Delphi的運行庫包含許多過程與函數以供您的應用程序調用。您不必了解過程與函數的邏輯,但要知道過程與函數的用途。在對象中說明的過程和函數稱為方法(Method)。所有的事件處理過程都是過程,以保留字procedure開頭。每一個事件處理過程只包含了當這一事件發生時需要執行的程序代碼。在事件處理過程中使用Delphi已經存在的過程與函數,只需在程序代碼中調用它們即可。 

一個調用Delphi方法的簡單常式 

下文將通過對一個Memo部件的文本進行剪切、拷貝、粘貼、清除等編輯的應用程序編製,介紹使用Delphi過程和函數的調用方法。

Memo(備註)部件有一個CutToClipboard方法,實現將用戶在memo中選擇的文本移到剪貼板上去。由於這個功能已經被建立在此方法中了,所以您只需知道這個方法做什麼以及如何使用它即可。

下面的語句表明如何調用一個名為Memo1的memo部件的CutToClipboard方法: 

Memo1.CutToClipboard; 

通過指定Memo1的名稱,說明調用哪一個部件的CutToClipboard方法。如果不指明對象名稱,Delphi會顯示Unknownidentifier錯誤。當該事件處理過程被觸發,程序會執行CutToclipboard中的語句,將Memo1中的文本剪貼到剪貼板上去。

下文的常式展示了如何調用Delphi的方法,實現將備註部件的文本信息剪切、拷貝到剪貼板上;將剪貼板上的標記文本粘貼到備註中,清除備註部件中的全部文本等四個功能。

打開一個新的空窗體,加入一個memo部件和四個按鈕,並排列整齊。改變按鈕部件的Name屬性,分別命名為Cut,Copy,Paste,Clear。您會發現,當Name屬性發生改變時,Caption屬性將發生相應的變化。在Caption屬性前加標「&」號設立加速鍵

將memo部件的ScrollBars屬性設為ScVertical,以便加上滾行條。將WordWrap屬性設置為True,這樣當用戶輸入文本到達Memo部件的右邊緣時會自動回行。將Line屬性第一行的Memo1文本刪除,使得memo部件在初始顯示時為空的。

為每一個按鈕建立如下的事件處理過程: 

procedureTForm1.CutClick(Sender:TObject);

begin

Memo1.CutToClipboard;

end; 

procedureTForm1.CopyClick(Sender:TObject);

begin

Memo1.CopyToClipboard;

end; 

procedureTForm1.PasteClick(Sender:TObject);

begin

Memo1.PasteFromClipboard;

end; 

procedureTForm1.ClearClick(Sender:TObject);

begin

Memo1.clear;

end; 

執行此程序。您可以在備註部件中輸入文本,在進行了文本的標記后,可以任意地進行剪切、拷貝、粘貼和清除。當按鈕被按動時,就調用相應的過程進行處理。用戶可以通過查閱在線幫助進行Memo部件的TopicSearch,在MemoComponent項中查閱Method,會得到以上過程的詳細說明。 

調用Delphi的含參過程 

有些過程要求用戶指明參數。被調用的過程會在執行時使用傳入的參數值,這些值在過程中被認為是已經被說明的變數。例如,LoadFromFile方法在TString對象中被說明為: 

ProcedureLoadFromFile(constFileName:String); 

在調用這一過程時,應指明FileName參數是要裝入的文件名稱。下面的程序將先打開Open對話框,當您選擇了一個文件后,Delphi將把該文件讀入一個Memo部件: 

begin

OpenDialog.Execute;

Memo1.lines.LoadFromFile(OpenDialog.FileName);

end; 

13 Delphi -函數使用

與過程一樣,函數的程序代碼也執行特定的工作。它和過程的差別為:函數執行時會返回一個值,而過程則沒有返回值。函數可以用來賦給一個屬性或變數;也可以使用返回值來決定程序的流程。

前文中實際上已經接觸過了函數。在講述變數時,曾用到過下面的程序段:Edit1.Text:=IntToStr(X+Y);其中,IntToStr(Value)把一個LongInt類型的數值轉化為字元串的值,Value是IntToStr唯一的參數,它可以是一個整形的值、變數、屬性或產生整形值的表達式。調用函數,必須把返回值賦給和此返回值類型兼容的變數或屬性。

有些函數返回一個True或False的布爾量,用戶的程序可以根據返回值來決定跳轉。下文的常式講述了函數返回值為Boolean的判斷用法:

在窗體中加入一個ColorDialog對象和一個Name屬性為ChangeColor的按鈕。為按鈕的OnClick事件建立事件處理過程如下: 

procedureTForm1.ChangeColorClick(Sender:TObject);

begin

ifColorDialog1.Executethen

Form1.Color:=ColorDialog1.Color

else

Form1.Color:=clRed;

end; 

此事件處理過程使用一個返回Boolean值的Execute方法。按動按鈕,並在顏色對話框中選擇一個顏色。如果按動OK按鈕,ColorDialog.Execute方法將返回True,則Form1.Color將被賦值為ColorDialog1.Color,窗體顯現您選用的顏色;如果按動顏色對話框的Cancel按鈕,方法將返回False值,窗體將變為紅色。

跳轉語句 

ObjectPascal的跳轉語句有if和case兩個。 

if語句 

if語句會計算一個表達式,並根據計算結果決定程序流程。在上文的常式中,根據ColorDialog.Execute的返回值,決定窗體的背景顏色。if保留字後跟隨一個生成Boolean值True或False的表達式。一般用「=」作為關係運算符,比較產生一個布爾型值。當表達式為True時,執行then后的語句。否則執行else后的代碼,if語句也可以不含else部分,表達式為False時自動跳到下一行程序。

if語句可以嵌套,當使用複合語句表達時,複合語句前後需加上begin…end。else保留字前不能加「;」,而且,編譯器會將else語句視為屬於最靠近的if語句。必要時,須使用begin…end保留字來強迫else部分屬於某一級的if語句。 

14 Delphi -case語句

case語句適用於被判斷的變數或屬性是整形、字元型、枚舉型或子界型時(LongInt除外)。用case語句進行邏輯跳轉比編寫複雜的if語句容易閱讀,而且程序代碼整形較快。

下面的常式顯示一個使用case語句的窗體:

建立如下的事件處理過程: 

procedureTForm1.Button1Click(Sender:TObject);

var

Number:Integer;

begin

Number:=StrToInt(Edit1.Text);

caseNumberof

1,3,5,7,9:Label2.Caption:='奇數';

0,2,4,6,8:Label2.Caption:='偶數';

10..100:

begin

Label2.Caption:='在10到100之間';

Form1.Color:=clBlue;

end;

else

Label2.Caption:='大於100或為負數';

end;

end; 

執行程序,當Edit1部件接受到一個值,並按動「OK」按鈕觸發程序后,Number便被賦值為用戶輸入的數值。case語句根據Number的值判斷該執行哪一條語句。象if語句一樣。case語句也有可選擇的else部分。case語句以end結尾。 

15 Delphi -循環語句 

ObjectPascal的循環語句有三種:repeat、while和for語句。 

repeat語句 

repeat語句會重複執行一行或一段語句直到某一狀態為真。語句以repeat開始,以until結束,其後跟隨被判斷的布爾表達式。參閱以下的常式: 

i:=0;

repeat

i:=i+1;

Writen(i);

untili=10; 

當此語句被執行時,窗體的下方會出現1到10的數字。布爾表達式i=10(注意,與其他語言不同的是,「=」是關係運算符,而不能進行賦值操作)直到repeat..until程序段的結尾才會被計算,這意味著repeat語句至少會被執行一次。 

16 Delphi -while語句

while語句和repeat語句的不同之處是,它的布爾表達式在循環的開頭進行判斷。while保留字後面必須跟一個布爾表達式。如果該表達式的結果為真,循環被執行,否則會退出循環,執行while語句後面的程序。

下面的常式達到和上面的repeat常式達到同樣的效果: 

i:=0;

whilei0then

test2(A);{經前置說明,調用未執行的過程Test2}

writeln(A);

end;

procedureTest2(varA:Integer);{經前置說明的Test2的執行部分}

begin

A:=Adiv2;

ifA>0rhen

test1(A);{在Test2中調用已執行的過程Test1}

end; 

procedureTForm1.Button1Click(Sender:TObject);

begin

Alpha:=15;{給Alpha賦初值}

Test1(Alpha);{第一次調用Test1,遞歸開始}

end; 

按鈕的OnClick事件處理過程給Alpha賦初值,並實現先減1再除2的循環遞歸調用,直到Alpha小於0為止。 

17 Delphi -程序函數

程序代碼在調用一個過程或函數時,通常用參數傳遞數據到被調用的過程或函數中。最常用的參數有數值參數、變數參數和常量參數三種。

由被調用過程或函數定義的參數為形參,而由調用過程或函數指明的參數叫實參。在NoValue函數中,說明函數體中的AnEditBox是形參,而調用時在ifNoValue(Edit1)…中,Edit1是實參。

數值參數在運行過程中只改變其形參的值,不改變其實參的值,即參數的值不能傳遞到過程的外面。試看下面的常式: 

procedureCalculate(CalNo:Integer);

begin

CalNo:=CalNo*10;

end; 

用以下常式調用Calculate函數:

Number:=StrToInt(Edit1.Text);

Calculate(Number);

Edit2.Text:=IntToStr(Number);

Number接受由編輯框1輸入的數值,經Calculate過程運算。它是一個數值型實參。在進入Calculate函數后,會把Number實參拷貝給形參CalNo,在過程中CalNo增大十倍,但並未傳遞出來,因此Number值並未改變,在編輯框2中顯示仍然是編輯框1中的輸入值。形參和實參佔用不同的內存地址,在過程或函數被調用時,將實參的值複製到形參佔用的內存中。因此出了過程或函數后,形參和實參的數值是不同的,但實參的值並不發生變化。如果您想改變傳入的參數值,就需要使用變數參數,即在被調用程序的參數表中的形參前加上保留字var。例如:procedureCalculate(varCalNo:Integer); 

則CalNo並不在內存中佔據一個位置,而是指向實參Number。當一個變參被傳遞時,任何對形參所作的改變會反映到實參中。這是因為兩個參數指向同一個地址。將上一個常式中過程頭的形參CalNo前面加上var,再以同樣的程序調用它,則在第二個編輯框中會顯示計算的結果,把第一個編輯框中的數值放大十倍。這時形參CalNo和實參Number的值都是Nnmber初始值的10倍。

如果當過程或函數執行是要求不改變形參的值,最保險的辦法是使用常量參數。在參數表的參數名稱前加上保留字const可以使一個形參成為常量參數。使用常量參數代替數值參數可以保護您的參數,使您在不想改變參數值時不會意外地將新的值賦給這個參數。

定義新的數據類型 

ObjectPascal有一些系統預定義的數據類型,在2.1.2中已經對它們作了介紹。您可以利用這些數據類型以建立新的數據類型來滿足程序的特定需要。下面簡單地敘述了您能建立的主要數據類型,如枚舉型、子界型、數組型、集合型、記錄型、對象型等。 

18 Delphi -枚舉類型 

一個枚舉型的說明列出了所有這種類型可以包括的值: 

type

Tdays=(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday); 

可以定義上述枚舉類型的變數:

var

DayOfWeek:TDays; 

在枚舉型中,括弧中的每一個值都有一個由說明它的位置決定的整形值。例如Sunday有整形值0,Monday有整形值1等。您可以把DayOfWeek說明為一個整形變數,並將一星期的每一天賦一個整形值以達到相同的效果,但用枚舉型會使得程序可讀性好,編寫容易。當您在枚舉型中列出值時,您同時說明了這個值是一個標識符。例如您的程序中如果已經含有TDays類型且說明了DayOfWeeks變數,則程序中便不能使用Monday變數,因為它已經被說明為標識符了。 

19 Delphi -子界類型

子界型是下列這些類型中某範圍內的值:整形、布爾量、字元型或枚舉型。在您想限制一個變數的取值範圍時,子界型是非常有用的。 

type

Thours=0..23;

TValidLetter='A'..'F';

TDays=(Sunday,Monday,Tuesday,Wednesday,Thursday,

Friday,Saturday);{枚舉型}

TWorkDay=Monday..Friday;{一個TDays型的子界} 

子界型限定了變數的可能取值範圍。當範圍檢查打開時,(在庫單元的Implementation後面有{$R*.DFM}字樣表示範圍檢查打開,否則您可以在Options|Project|ComplierOptions中選擇RangeCheking來打開範圍檢查),如果變數取到子界以外的值,會出現一個範圍檢查錯誤。 

20 Delphi -數組類型

數組是某種數據類型的有序組合,其中每一個元素的值由其相對位置來指定,您可以在數組的某個位置上放置數據,並在需要時使用這些數據。下面的類型說明了一個Double型的數組變數:

var

Check:array[1..10]ofDouble; 

它表示Check指向一個含有10個Double型元素的數據串列,代表每一個元素的是1到10之間的數字,稱為索引。數組的每一項由數組名稱加上[]中的索引來表示。Check包含10個變數,Check[1]表示第一個變數。您也可以把數組定義成類型:

type

TCheck=array[1..10]ofDouble;

則變數說明改為:

var

Check:TCheck; 

您可以通過給數組賦值等方法來使用數組。下面的語句將0.0賦給Check數組中的所有元素: 

forJ:=1to10do

Check[J]:=0.0;,

數組也可以是多維的,下面的類型定義了一個20行、20列的數組。

type

Ttable=array[1..20,1..20]ofDouble;

var

table1:TTable; 

,;,;想將這一表格的所有數據初始化為0.0,您可以使用for循環: 

var

Col,Row:Integer;

forCol:=1to20do

forRow:=1to20do

Table1[Col,Row]:=0.0; 

21 Delphi -字元串類型

字元串類型事實上是一個一維的字元數組。當您說明一個字元串型的變數時,您應當指明這個字元串的大小,下面是說明字元串類型的例子:

type

MyString:string[15];

var

Myname:MyString; 

則變數MyName被說明成為最多可以包含15個字元。如果您沒有說明字元串的大小,Delphi會認為字元串包含最大值255個字元。給字元串賦值可以直接使用單引號括起的字串賦值: 

MyName:='Frank.Smith';

或MyName:='張明'; 

因為MyName是一個可以包含15個字元的MyString型變數,上文的兩個的變數都是有效的,一個漢字可以視作兩個字元。當您給字元串型變數賦的值多於定義數值時,例如將MyName賦為『FrankSmith.Franklin』,則Delphi只會接受前15個字元『FrankSmith.Fran』。在內存中,字元串通常佔用比所說明的大小多一個位元組的空間,因為第一個位置是一個包含這個數組大小的位元組。您可以使用索引值來訪問字元串的字元,MyName[1]可以得到MyName的第一個字元'F'。

可以使用Delphi豐富的運算符、過程和函數來處理字元串型的變數和屬性。下面介紹幾個常用的運算符和Delphi過程或函數:

concat和(+)功能相同,都可以將多個字元串組合在一起,建立一個較大的字元串;Copy會返回一個字元串中的子字元串;Delete在一個字元串中從一個指定位置起刪除一定數目的字元;Insert在一個字元串中插入一個字元串;Length返回字元串的長度;Pos返回一個子字元串在一個字元串中的位置,即索引值。 

22 Delphi -集合類型

集合類型是一群相同類型元素的組合,這些類型必須是有限類型如整形、布爾型、字元型、枚舉型和子界型。在檢查一個值是否屬於一個特定集合時,集合類型非常有用。下面的常式可以說明集合類型的用法:

在窗體上加入一個編輯框和一個按鈕,清除編輯框中的文字,在其上加上Caption為「輸入母音」的標籤Label,並在編輯框的下方加入一個空的標籤,將按鈕的Default屬性改為True,建立按鈕的事件處理過程如下: 

procedureTForm1.Button1Click(Sender:TObject);

type

Tvowels=setofChar;

var

Vowels:TVowels;

begin

Vowels:=['a','e','i','o','u'];

ifEdit1.Text[1]inVowelsthen

Lable2.Caption:='是母音';

else

Lable2.Caption:='請再試';

end; 

執行這個程序,在編輯框中輸入字母,表達式Edit1.Text[1]inVowels的結果是布爾型的,in是運算符,用來判斷字母是否存在於集合中。輸入的判別結果會顯示在編輯框的下方。以上就用到了集合類型TVowels。 

23 Delphi -記錄類型

記錄是您的程序可以成組訪問的一群數據的集合。下面的常式說明了一個記錄類型的用法: 

type

TEmployee=record

Name:string[20];

YearHired:1990..2000;

Salsry:Double;

Position:string[20];

end; 

記錄包含可以保存數據的域,每一個域有一個數據類型。上文的記錄TEmployee類型就含有四個域。您可以用以下的方式說明記錄型的變數: 

var

NewEmployee,PromotedEmployee:TEmployee;

用如下的方法可以訪問記錄的單域:

NewEmployee.Salary:=1000;

編寫如下的語句可以給整個記錄賦值: 

withPromotedEmployeedo

begin

Name:='';

YearHired:=1993;

Salary:=2000.00

Position:='editor';

end; 

您的程序可以將記錄當成單一實體來操作: 

PromptEmployee:=NewEmployee;

以上介紹了用戶常用的自定義類型。在Delphi的編程中,對象是非常重要的用戶自定義數據類型。象記錄一樣,對象是結構化的數據類型,它包含數據的域(Field),也包含作為方法的過程和函數。在Delphi中,當您向窗體中加入一個部件,也就是向窗體對象中加入了一個域;每一個部件也是對象,每當您建立一個事件處理過程使得部件可以響應一個事件時,您即自動地在窗體中加入了一個方法。在本章第2節中,將詳細講述Delphi面向對象編程的方法和技巧。 

ObjectPascal的庫單元Unit 

Units是常量、變數、數據類型、過程和函數的集合,而且能夠被多個應用程序所共享。Delphi已經擁有許多預定義的程序庫單元可供您建立您的程序庫單元使用。Delphi的VisualComponentLibrary由多個程序庫單元組成,它們說明了對象、部件以供您的應用程序用來設計用戶界面。例如,當您在窗體中加入一個CheckBox時,Delphi自動在您的程序庫單元中加入了Stdctrls庫單元,因為TCheckBox部件是在StdCtrls庫單元中說明的。

當您設計您的窗體時,Delphi自動建立一個和您的窗體有關的庫單元。您的庫單元不必都和窗體有關,也可以使用預定義的只包含數學運算函數的庫單元,或是自行編寫數學函數庫單元。在一個庫單元中所有的說明都相互有關係,例如,CDialogs程序庫單元包含了在您的應用程序中使用的普通對話框的所有說明。 

ObjectPascal程序庫單元的結構 

不管一個庫單元是否和一個窗體有關,庫單元的結構都是相同的。其結構如下: 

unit 

interface 

uses

{公有說明} 

implementation 

uses

{私有說明}

{過程和函數的執行部分}

initialization{選擇性的}

{選擇性的初始化程序}

end. 

程序庫單元的介面部分 

interface是庫單元的介面部分,它決定了本庫單元對其他任何庫單元或程序的可見(可訪問)部分。您可以在介面部分說明變數、常量、數據類型、過程和函數等等。Delphi在您設計窗體的庫單元中,將窗體數據類型、窗體變數和事件處理過程都說明在這一部分。

interface標誌庫單元介面部分的開始。在interface中的說明對要使用這些說明的其他庫單元或應用程序是可見的。一個庫單元可以使用其他Unit的說明,只需要在uses子句中指明那些庫單元即可。例如,您在庫單元A中編寫程序代碼,且您想調用UnitB於interface部分說明的程序。您可以把庫單元B的名稱加入到A的interface部分的uses子句中,則任何A中的程序都可以調用B中說明的程序。而且,如果B中interface部分的uses子句中出現C庫單元,儘管A中未曾出現C,A同樣可以調用B、C庫單元在interface中說明的程序。但如果B出現在A的interface部分的uses子句中,那麼庫單元A便不能出現在B的interface的uses子句中。因為這樣會產生對庫單元的循環訪問。當試圖編譯時,會產生出現錯誤信息。 

程序庫單元的實現部分 

實現部分implementation中包含interface中說明的過程、函數、事件處理過程的具體實現程序代碼。這一部分可以有自己的額外說明,但這些說明是私有的,外部程序不能調用這些說明。在interface中說明的函數實體必須在implementation部分出現,可以使用標題簡寫:只輸入procedure或function保留字,後面跟過程或函數的名稱即可,其後則是程序的實現部分了。如果您在implementation部分說明任何常式,其標題並未出現在interface部分,則必須寫全其標題部分。

在implementation部分的uses子句中指定的庫單元,只供給本庫單元的程序使用其interface中說明的程序。其他使用本庫單元的庫單元,不能訪問這些在implementation的udes子句中庫單元的說明,因為在implementation後進行的庫單元包含是私有的。所以上例中,如果C出現在B的implementation部分,則A不能使用C的公有部分,除非C出現在A的uses子句中。在implementation中出現的循環訪問是Delphi所允許的,如果A的implemetation的uses子句中出現B,則B的implementation部分也可以出現A。 

程序庫單元的初始化部分 

初始化當前庫單元所使用的數據,或是通過interface部分將數據提供給其他應用程序、庫單元使用時,您可以在庫單元中加入一個initialization部分,在庫單元的end前加上您的初始化語句。當一個應用程序使用一個庫單元時,在庫單元中的initialization部分會先於其他的代碼執行。如果一個應用程序使用了多個庫單元,則每一個庫單元的初始化部分都會在所有的程序代碼前執行。 

使用Delphi的可視化部件及其庫單元 

當您在窗體中加入可視化部件時,如果該部件在可視化部件庫中,Delphi會在您的庫單元的interface部分的uses子句中自動加上需要使用的庫單元名稱。但有些對象在Delphi的環境中並沒有可視化部件存在,例如,您想在庫單元中加入一個預定義的信息框,則您必須把MsgDlg庫單元加入您的uses子句中。如果您要使用TPrinter對象的話,必須將Printer庫單元加入uses子句中。在在線幫助中可以查到對象所屬的預定義庫單元。

要使用在??一庫單元的名稱,並用『.』號隔開。例如,要在Unit2中使用Unit1中說明的Calculate函數,應使用下面的方法:

Number:=Unit1.Calculate(10);

您可以在任何標識符如屬性、常量、變數、數據類型、函數等之前加上庫單元的名稱。您可以在自由地在任何Delphi庫單元中加入程序代碼,但不要改變由Delphi生成的程序。 

建立與窗體無關的新庫單元 

如果您想在工程中建立一個和任何窗體無關的新庫單元,可以現選用File|NewUnit。這時一個新的庫單元加入了工程,新庫單元的代碼如下: 

unitUnit2;

interface

implementation

end. 

Delphi將根據您的工程中的文件數目為您的庫單元選擇名稱,您可以在程序骨架間加入您的程序代碼。

當編譯您的工程時,這個新加入的庫單元會被編譯為一個具有.DCU後綴的文件。這個新生成的文件是鏈接到工程的可執行文件上的機器代碼。

將庫單元加入工程 

將庫單元加入工程是比較簡單的。無論是您自己建立的庫單元還是Delphi建立的與窗體有關的庫單元,如果已經完成,則先打開您想加入庫單元的工程(可以用OpenProject打開工程);再選用File|OpenFile,然後選擇您想加入的源程序(.PAS文件),並選擇OK即可。則庫單元被加入到應用程序中。 

24 Delphi -對象編程

Delphi是基於面向對象編程的先進開發環境。面向對象的程序設計(OOP)是結構化語言的自然延伸。OOP的先進編程方法,會產生一個清晰而又容易擴展及維護的程序。一旦您為您的程序建立了一個對象,您和其他的程序員可以在其他的程序中使用這個對象,完全不必重新編製繁複的代碼。對象的重複使用可以大大地節省開發時間,切實地提高您和其他人的工作效率。 

什麼是對象 

一個對象是一個數據類型。對象就象記錄一樣,是一種數據結構。按最簡單的理解,可以將對象理解成一個記錄。但實際上,對象是一種定義不確切的術語,它常用來定義抽象的事務,是構成應用程序的項目,其內涵遠比記錄要豐富。在本書中,對象可被理解為可視化部件如按鈕、標籤、表等。

了解對象,最關鍵的是掌握對象的特性。一個對象,其最突出的特徵有三個:封裝性、繼承性、多態性。 

對象的封裝性 

對對象最基本的理解是把數據和代碼組合在同一個結構中,這就是對象的封裝特性。將對象的數據域封閉在對象的內部,使得外部程序必需而且只能使用正確的方法才能對要讀寫的數據域進行訪問。封裝性意味著數據和代碼一起出現在同一結構中,如果需要的話,可以在數據周圍砌上「圍牆」,只有用對象類的方法才能在「圍牆」上打開缺口。 

對象的繼承性 

繼承性的含義直接而且顯然。它是指把一個新的對象定義成為已存在對象的後代;新對象繼承了舊類的一切東西。在往新對象中添加任何新內容以前,父類的每一個欄位和方法都已存在於子類中,父類是創建子類的基石。 

對象的多態性 

多態性是在對象體系中把設想和實現分開的手段。如果說繼承性是系統的布局手段,多態性就是其功能實現的方法。多態性意味著某種概括的動作可以由特定的方式來實現,這取決於執行該動作的對象。多態性允許以類似的方式處理類體系中類似的對象。根據特定的任務,一個應用程序被分解成許多對象,多態性把高級設計處理的設想如新對象的創建、對象在屏幕上的重顯、程序運行的其它抽象描述等,留給知道該如何完美的處理它們的對象去實現。 

通過Delphi實例了解對象 

讓結合Delphi的實例討論對象的概念:

當您要建立一個新工程時,Delphi將顯示一個窗體作為設計的基礎。在程序編輯器中,Delphi將這個窗體說明為一個新的對象類型,並同時在與窗體相關聯的庫單元中生成了創建這個新窗體對象的程序代碼。 

unitUnit1; 

interface 

usesSysUtils,Windows,Messages,Classes,Graphics,Controls,Forms,Dialogs; 

type

TForm1=class(TForm){窗體的類型說明開始}

private

{Privatedeclarations}

public

{Publicdeclarations}

end;{窗體的類型說明結束} 

var

Form1:TForm1;{說明一個窗體變數} 

implementation 

{$R*.DFM} 

end. 

新的窗體類型是TForm1,它是從TForm繼承下來的一個對象。它具有對象的特徵:含有域或方法。由於您未給窗體加入任何部件,所以它只有從TForm類中繼承的域和方法,在窗體對象的類型說明中,您是看不到任何域、方法的說明的。Form1稱為TForm1類型的實例(instance)。您可以說明多個對象類型的實例,例如在多文檔界面(MDI)中管理多個子窗口時就要進行這樣的說明。每一個實例都有自己的說明,但所有的實例卻共用相同的代碼。

假設您向窗體中加入了一個按鈕部件,並對這個按鈕建立了一個OnClick事件處理過程。再查看Unit1的源程序,會發現TForm1的類型說明部分如下:

type

TForm1=class(TForm)

Button1:TButton;

procedureButton1Click(Sender:TObject);

private

{Privatedeclarations}

public

{Publicdeclarations}

end; 

現在TForm1對象有了一個名為Button1的域:它是您在窗體中加入的按鈕。TButton是一個對象類型,Button1是Tbutton的一個實例。它被TForm1對象所包含,作為它的數據域。每當您在窗體中加入一個部件時,部件的名稱就會作為TFom1的域加入到類型說明中來。在Delphi中,您所編寫的事件處理過程都是窗體對象的方法。每當您建立一個事件處理過程,就會在窗體的對象類型中說明一個方法。

當您使用ObjectInspector來改變對象(部件)的名稱時,這個名稱的改變會反映到程序中。例如,在ObjectInspector中將Form1的Name屬性命名為ColorBox,您會發現在類型說明部分,會將前文的TForm1改為: 

TColorBox=class(TForm); 

並且在變數說明部分,會說明ColorBox為TColorBox類型的變數,由Delphi自動產生的事件處理過程名稱會自動改為TColorBox.Button1Click;但您自行編寫的實現部分的代碼卻不會被自動修改。因此,如果您在改變Name屬性前編寫了程序,則您必須將事件處理過程中的對象名稱進行改變。所以,原先的Form1.Color要改為ColorBox.Color。 

25 Delphi -數據繼承 

前面的TForm1類型是很簡單的,因為它只含有域Button1和方法Button1Click。但是在這個窗體上,您可以改變窗體的大小、加入或刪除窗體的最大最小化按鈕,或設置這個窗體為MDI界面。對於一個只包含一個域和方法的對象來講,您並沒有看到顯式的支持程序。在窗體上單擊滑鼠或用ObjectInspector的上端的ObjectSelector選中Form1對象,按動F1查閱它的在線幫助,您會在Properties和Method中找到它的繼承到的全部屬性和方法。這些是在TForm類型中說明的,TForm1是TForm的子類,直接繼承了它所有的域、方法、屬性和事件。例如窗體的顏色屬性Color就是在TForm中說明的。當您在工程中加入一個新窗體時,就等於加入了一個基本模型。通過不斷地在窗體中加入部件,您就自行定義了一個新的窗體。要自定義任何對象,您都將從已經存在的對象中繼承域和方法,建立一個該種對象的子類。例如對象TForm1就被說明為對象TForm的子類,擁有一個窗體部件的基本屬性或方法。只有當您在窗體中加入了部件或編寫了事件處理過程時,Form1才成為您自己的類型。

一個比較特殊的對象是從一個範圍較廣或較一般的對象中繼承下來的,它是這個特別對象的祖先,這個對象則稱為祖先的後代。一個對象只能有一個直接的祖先,但是它可以有許多後代。TForm是TForm1類型的祖先,所有的窗體對象都是TForm的後代。

用F1查閱窗體的在線幫助時,您會發現TForm被稱為component(部件)。這是因為所有的部件都是對象。

在這個結構中所有的部件都是對象。部件類型TComponent從TObject類型中繼承數據和程序代碼,並具有額外的可以用作特殊用途的屬性、方法、事件,所以部件可以直接和用戶打交道,記錄它的狀態並存貯到文件中等等。控制類型TControl從TComponent中繼承而來,又增加了新的功能,如它可以顯示一個對象。在上圖中,雖然TCheckBox不是直接由TObject繼承來的,但是它仍然有任何對象所擁有的屬性,因為在VCL結構中,TCheckBox終究還是從TObject中繼承了所有功能的特殊對象,但它還有些自行定義的獨到的功能,如可以選擇記錄狀態等。 

26 Delphi -對象範圍 

一個對象的範圍決定了它的數據域、屬性值、方法的活動範圍和訪問範圍。在一個對象的說明部分說明的數據域、屬性值、方法都只是在這個對象的範圍中,而且只有這個對象和它的後代才能擁有它們。雖然這些方法的實際程序代碼可能是在這個對象之外的程序庫單元中,但這些方法仍然在這個對象的範圍內,因為它們是在這個對象的說明部分中說明的。

當您在一個對象的事件處理過程中編寫程序代碼來訪問這個對象的屬性值、方法或域時,您不需要在這些標識符之前加上這個對象變數的名稱。例如,如果您在一個新窗體上加入一個按鈕和一個編輯框,並為這個按鈕編寫OnClick事件處理過程: 

procedureTForm1.Button1Click(Sender:Tobject);

begin

Color:=clFuchsia;

Edit1.Color:=clLime;

end; 

其中的第一行語句是為整個窗體Form1著色。可以編寫如下:

Form1.Color:=clFuchsia; 

但您可以不必加上Form1.,因為Button1Click方法是在TForm1對象的範圍里。當您在一個對象的範圍中時,您可以省略所有這個對象中的屬性值、方法、域之前的對象標識符。但是當您編寫第二個語句改變編輯框的底色時,因為此時您想訪問的是TEdit1對象的Color屬性,而不是TForm1類型的,所以您需要通過在屬性前面加?指明,Delphi會象第一個語句一樣,將窗體的顏色變成綠色。因為Edit1部件是在窗體中的,它是窗體的一個數據域,所以您同樣不必指明其從屬關係。

如果Edit1是在其他窗體中,那麼您需要在編輯框之前加上這個船體對象的名稱了。例如,如果Edit1是在Form2之中,那它是Form2說明的一個數據域,並位於Form2的範圍中,那麼您需要將第二句改為: 

Form2.Edit1.Color:=clLime; 

而且需要把Unit2加入Unit1的uses子句中。

一個對象的範圍擴展到這個對象的所有後代。TForm的所有屬性值、方法和事件都在TForm1的範圍中,因為TForm1是TForm的後代。您的應用程序不能說明和祖先的數據域重名的類型、變數等。如果Delphi顯示了一個標識符被重複定義的信息,就有可能是一個數據域和其祖先對象(例如TForm)的一個數據域有了相同的名稱。可以嘗試改變這個標識符的名稱。 

重載一個方法 

您可以重載(Override)一個方法。通過在後代對象中說明一個與祖先對象重名的方法,就可以重載一個方法。如果想使這個方法在後代對象中作和祖先對象中一樣的工作但是使用不同的方式時,您就可以重載這個方法。Delphi不推薦您經常重載方法,除非您想建立一個新的部件。重載一個方法,Delphi編譯器不會給出錯誤或警告提示信息。

對象公有域和私有域的說明 

當使用Delphi的環境來建立應用程序時,您可以在一個TForm的後代對象中加入數據域和方法,也可以通過直接修改對象類型說明的方法來為一個對象加上域和方法,而不是把一個部件加入窗體或事件處理過程中。

您可以在對象的Public或Private部分加入新的數據域和方法。Public和Private是ObjectPascal的保留字。當您在工程中加入新的窗體時,Delphi開始建立這個新窗體對象。每一個新的對象都包含public和private指示,以便您在代碼中加入數據域和方法。在public部分中說明其它庫單元中對象的方法也可以訪問的數據域或方法。在private部分的說明有訪問的限制。如果您在private中說明域和方法,那麼它在說明這個對象的庫單元外是不透明的,而且不能被訪問。private中可以說明只能被本庫單元方法訪問的數據域和本庫單元對象訪問的方法。過程或函數的程序代碼可以放在庫單元的implementation部分。 

上一篇[光學變焦倍數]    下一篇 [塞普勒斯鎊]

相關評論

同義詞:暫無同義詞