版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第 11 章用組件開發(fā)一致的界面什么能算是好的界面,標(biāo)準是非常主觀的。許多商業(yè)應(yīng)用程序都跟隨著WinTel 標(biāo)準:灰色的按鈕和控件,白色的背景。對商務(wù)程序來說,這可能是個不錯的主意,因為通過多年的熟悉使得這個界面在某種程度上較為舒服,但這是個好的界面嗎?AlanCooper 是Visual Basic之父,他建議“通過堅持使他們(Microsoft和 Apple )各自獨立的開發(fā)者群體遵守既定的方針,他們偷偷摸摸地阻止了來自應(yīng)用者群體的革新?!?Cooper,212 Cooper 認為,“我并不鼓吹忽略界面風(fēng)格方面的指導(dǎo),從而導(dǎo)致界面出現(xiàn)混亂。我僅僅認為應(yīng)該像參議員看待說客那樣來看待對界面風(fēng)格
2、的指導(dǎo),而絕不能像司機服從于交警那樣。立法者知道說客想要削減某項經(jīng)費,但說客并非來自于持有客觀態(tài)度的第三方?!盋ooper,212在所有的條件下都是最好的界面可能并不存在,即使在一定的條件下,界面的設(shè)計仍然是高度主觀的。如果你能開發(fā)出像圖 11.1 所示的新 RealPlayer 那樣的界面,而且符合你的目的,那就很好了。如果你不擅長創(chuàng)建獨一無二或非常有趣的圖形用戶界面,而且并沒有雇傭圖形設(shè)計者的預(yù)算, 那么可能會開發(fā)出與 WinTel 風(fēng)格類似的應(yīng)用程序。 對于商業(yè)目的而言,也許較為熟悉的風(fēng)格可以避免使用方面的障礙。圖 11.1 RealPlayer 8 使用了一些漂亮的圖形按鈕,并進行了視
3、覺人類工程學(xué)方面的嘗試。還可以選用卡通標(biāo)志和斑馬條紋等外表只有一個問題不是主觀的,它也是本章的主題,那就是界面應(yīng)該是一致、連貫、完全的。不一致、不連貫、不完全,不考慮界面的風(fēng)格對用戶來說是不可容忍的。第 11 章示范了一些技術(shù),可用于簡化開發(fā)并確保一致性,包括如何使用定制組件、組件模板和窗體繼承,以提供一致、連貫而完全的應(yīng)用程序。11.1定制組件創(chuàng)建定制組件很有趣,而且定制組件也很有用。首先,顯而易見的理由是可以重用已有的對象,并封裝新的或增強的特性;其次,它可以提供一致的效用。無須繪制組件時保證相同的尺寸、風(fēng)格、字體、顏色或措辭,可以對組件進行定制以確保這些目標(biāo)。定制組件的三個C定制組件的三
4、個 C 是一致性、連貫性和完備性。一致性意味著組件在你的應(yīng)用程序和其他地方的行為是一致的。一致性( Consistency )組件每次都表現(xiàn)出相同的行為和初始狀態(tài),才能提供一致性。對組件的行為或狀態(tài)進行一次編程,則所有的組件實例都具有一致的外觀和行為。一致性并不追求數(shù)量,注意到這一點是很重要的。定制組件無須進行大量的修改,即可提供一致性。即使組件只是重載了缺省的大小或形狀,創(chuàng)建一個定制組件也可確保一致性。有兩個直接的方法可以做到這一點。您可以子類化所有的需要微小修改的組件然后再安裝;或者快速地創(chuàng)建組件模板,這更容易一些(參考11.2 節(jié)“創(chuàng)建組件模板”)。連貫性( Coherency )一致性
5、是連貫的一個方面。如果對象不具有一致性,也會缺少連貫性。連貫性是對控制流和操作的邏輯性的度量,它要求語義上相似的操作具有一致的行為。定制控件和組件模板可用于提供更為連貫的行為流程。沒有一致性和連貫性,應(yīng)用程序不可能是完全的。完備性( Completeness)不一致、不完全的應(yīng)用程序看起來是不合邏輯且不正確的,這樣必定是不完備的。如果應(yīng)用程序不被用戶群體所接受,也不能說是完備的。完備性度量了應(yīng)用程序是否執(zhí)行了所要求的任務(wù)、結(jié)果是否正確、應(yīng)用程序是否具有合理的容錯級別。如果程序給出正確卻不合時宜的回答,也是不完備的。而迅速的提供錯誤的結(jié)果,仍然是錯誤的。如果程序的行為毫無規(guī)律、不一致、或不合邏輯
6、,那么該程序是失敗的。即使程序有相應(yīng)的用戶群體,仍然可能失敗,因為用戶群體可以拒絕使用該程序,或惡意共謀使用該程序提供錯誤的或不合適宜的結(jié)果。為什么組件幫助你走向勝利組件是對象。每個對象都屬于某個類。這意味著有一組代碼需要測試、調(diào)試和擴展。如果一個類已經(jīng)是完美的,那么每個實例都不會出錯。這樣如果類滿足了 3C 標(biāo)準,那么類的每個實例都會滿足該標(biāo)準。注意: “大而復(fù)雜的軟件系統(tǒng)需要設(shè)計師,以便開發(fā)者能夠朝著共同的目標(biāo)前進?!盝acobsen,Booch,andRumbaugh62 。設(shè)計師是這樣的人,他形成解決方案的概念并向程序員說清設(shè)計意圖。即便開始時的進度比通常慢,也要把事情做正確, 這將會
7、節(jié)省大量金錢和思考的時間,防止在最后才發(fā)現(xiàn)出軌。沒有經(jīng)驗、缺乏技術(shù)的管理者可能認為編寫組件接近于消磨時間,但這是面向?qū)ο蟮某绦蛟O(shè)計。以非面向?qū)ο蟮姆椒ㄈナ褂妹嫦驅(qū)ο蠊ぞ呤且粋€錯誤。使用Delphi 編寫結(jié)構(gòu)化程序可以很快地到達beta 版,這在短期內(nèi)常常會使管理者高興,但可能使得處于beta 版的時間較長。您的程序可能永遠都脫離不了beta 版。迅速得到錯誤的答案,仍然是錯誤的。無論是否能確認管理層會花大筆金錢來確保成功,都可以采取一些防御措施。從許多功能正確的組件來創(chuàng)建程序,可以盡可能少寫代碼而又能提高程序的正確性。重分解重分解是采取小的增量式改變的過程。組件可以一步就寫出來,創(chuàng)建全新而獨一
8、無二的東西,這樣做代價昂貴、風(fēng)險較大而且浪費時間;或者我們可以采取小的步驟,分層實現(xiàn)各種能力,這樣就不那么昂貴,風(fēng)險較低而且快速。設(shè)計師的關(guān)鍵作用之一 找到和減少冒險。如果沒有設(shè)計師,必須由程序員來完成該工作。管理者喜歡快速而廉價。那么很清楚,許多情況下最好的選擇就是對組件進行小的修改,將增量式的改變分層添加到已有的組件中。為示范進行這種小的修改所需代碼的合理數(shù)量,設(shè)計了下面的組件:unit UDBShortNavigator;/ UDBShortNavigator.pas - Toggles between short list of buttons/ and long list/ Copy
9、right (c) 2000. All Rights Reserved./ by Software Conceptions, Inc. Okemos, MI USA (800) 471-5890/ Written by Paul KimmelinterfaceusesWindows, Messages, SysUtils, Classes, Graphics, Controls,Forms, Dialogs,ExtCtrls, DBCtrls;typeTNavigatorButtonSet = ( nbsFull, nbsPartial );TDBShortNavigator = class(
10、TDBNavigator)private Private declarations FButtonSet : TNavigatorButtonSet;procedure SetButtonSet(const Value: TNavigatorButtonSet); protected Protected declarations public Public declarations published Published declarations property ButtonSet : TNavigatorButtonSet read FButtonSet write SetButtonSe
11、t;end;procedure Register;implementationprocedure Register;beginRegisterComponents(PKTools, TDBShortNavigator);end; TDBShortNavigator procedure TDBShortNavigator.SetButtonSet(const Value:TNavigatorButtonSet);constFULL_SET = nbFirst, nbPrior, nbNext, nbLast, nbInsert, nbDelete, nbEdit, nbPost, nbCance
12、l, nbRefresh;PARTIAL_SET = nbFirst, nbPrior, nbNext, nbLast;SETS : arrayTNavigatorButtonSet of TButtonSet = (FULL_SET,PARTIAL_SET);beginif( FButtonSet = Value ) then exit;FButtonSet := Value;VisibleButtons := SETSFButtonSet;end;end.TDBShortNavigator 繼承了 TDBNavigator ,添加了一個 ButtonSet 特性。將該特性在 nbsFull
13、 和 nbsPartial 之間切換,即可顯示所有的導(dǎo)航按鈕或僅僅顯示基本的四個按鈕(如圖 11.2 所示)。圖 11.2 TDBShortNavigator 可以快速地在顯示部分或全部導(dǎo)航按鈕之間切換很顯然該組件并沒有多少代碼。而這正是我們所需要的。小的改變快速、便宜而且可靠。然而,有人可能認為這是不重要或不相關(guān)的。由混沌理論可知,即使蛾的翅膀振動一下也可能影響到很遠的地方。那么我們可以考慮蛾困在Mark型計算機的中繼轉(zhuǎn)換開關(guān)中的情況。據(jù)說是COBOL 的發(fā)明者Grace Hopper 杜撰了 bug 這個詞,現(xiàn)在整個工業(yè)界都在使用它,連世界歷史上最重大的媒體事件之一Y2K 問題也是它的標(biāo)志
14、。并不是說上述的導(dǎo)航器子類在歷史上也能有這樣幸運的角色;軼事能被記錄本來就是戲劇性的。小的事件能夠發(fā)揮值得記載的作用,并具有相當(dāng)?shù)挠绊?。千里之行,始于足下,高級的系統(tǒng)正是由小塊的優(yōu)質(zhì)代碼所組成的。小的改變有什么好處除了本節(jié)開始所描述的好處之外,還包括快速、廉價、可靠等等,這些好處都是由小的、增量式的改變得到的。 TDBShortNavigator 這樣的組件有利于代碼的收斂。收斂是指所有該算法的代碼都聚集在一起;如果沒有最好的代碼,那么一個實例的代碼是次好的,代碼多于一個實例是較差的。發(fā)散是指出現(xiàn)算法的多個副本;這是最壞的情況。當(dāng)子類化TDBNavigator 這樣的組件來進行小的改變時,可以
15、促進代碼的收斂。改變可見按鈕數(shù)量的所有代碼都包含在同一個地方。因此只有一個代碼段需要測試、調(diào)試和擴展。如果要為按鈕定義三個狀態(tài),可以在同一地方快速而有效地修改代碼。注意: 您可能聽說過比其他的程序員多產(chǎn)一個數(shù)量級的程序員。也就是他個人的產(chǎn)量是其他人的十倍。這怎么可能呢?很顯然一個人不可能比程序員的平均打字速度快十倍。這是技巧與策略方面的問題。即使最好的程序員也不太可能在語法和程序編碼方面比平均程度強十倍;他只是使用了一些具有累積效應(yīng)的策略。其中必有一種策略傾向于編寫收斂的代碼。這種程序員可以比一般人快上十倍或更多,而且其代碼也可能好于平均的水平。我們提到過,修改并不重要。重要的是修改表示了什么
16、。像TDBShortNavigator這樣的組件就表明了編寫內(nèi)聚代碼的傾向。這種累積效應(yīng)往往分布在程序員的職業(yè)生涯或工程的生命周期中。采取好的策略編寫收斂的代碼,或編寫的代碼只具有算法的單一副本,這是一個策略。這可能是成為高產(chǎn)開發(fā)者的最佳途徑之一。有兩個習(xí)慣可促進采用該策略,并逐漸使之成為一種第二天性。首先:考慮多次修改你的代碼。我們知道諺語“天才是1%的靈感加99%的汗水”,這意味著當(dāng)一個人思考解決方案時,只有出現(xiàn)了非常好的機會,靈感才能發(fā)揮作用。其次:當(dāng)發(fā)現(xiàn)重復(fù)出現(xiàn)的代碼時,立即把涉及到的算法編寫為過程。隨著實踐的進行,這種迭代式的修改會變得更加自然,如果隨時進行修改,也更容易發(fā)揮作用。反
17、之,如果等到程序完成之后才進行修改工作,可能會遇到困難。管理者和其他程序員可能不想立即投入很多時間進行修改,而這時代碼已經(jīng)相互糾纏在一起以至于小的修改也可能引起代碼的混亂。組件化我們就繼續(xù)討論上一節(jié)的問題,如果你發(fā)現(xiàn)自己正在編寫處理組件內(nèi)部數(shù)據(jù)的代碼,那么最好子類化組件以封裝新的行為。 組件化的規(guī)則是: 如果代碼涉及到組件內(nèi)部的數(shù)據(jù),例如組件所擁有的對象列表,那么代碼實際上描述了組件的行為。對象的行為就是方法。通過將外部的、隱式的算法提升為方法,可以使代碼在類的層次上趨向于收斂。類不一定是組件;任何表示類行為的代碼都應(yīng)該作為方法合并到類中。有三個地方可以方便地重用代碼??梢宰宇惢ńM件在內(nèi)的
18、任何類,以重用代碼??梢远x組件模板,這是 Delphi 新近添加的功能,利用該方法可以很容易地在一個或多個組件中重用新的行為;而且能夠創(chuàng)建窗體或框架模板,這樣就可以重用整個窗體或框架及其所包含的組件。11.2創(chuàng)建組件模板首先將組件添加到數(shù)據(jù)模塊或窗體,設(shè)置它們的特性,創(chuàng)建事件處理程序,并編寫代碼。然后選定一個或多個組件,從 Component 菜單里選擇 Create Component Template 菜單項。所有被選中的組件、 事件處理程序、 以及相關(guān)的代碼, 都添加到了 VCL 面板的 Template 屬性頁上。選擇該組件模板并將其拖動到任意的窗體或數(shù)據(jù)模塊上,即可重新創(chuàng)建包括代碼
19、在內(nèi)的各個組件。將模板添加到窗體或數(shù)據(jù)模塊后,可以修改其位置、大小和特性等,就像是分別添加的一樣。當(dāng)選擇 Create Component Template 菜單項時, 會顯示 Component Template Information 對話框(見圖 11.3)。點擊 OK ,則接受缺省的組件名、面板屬性頁以及組件圖標(biāo),當(dāng)然也可以修改這些信息。 可以給模板組件命名所喜歡的名字, 將其放置在任何面板屬性頁上。如果輸入的屬性頁名字不存在, Delphi 將創(chuàng)建新的屬性頁。模板組件惟一的限制就是其圖標(biāo)必須是 24 24 像素位圖,與其他組件的圖標(biāo)類似。圖 11.3Component Templat
20、e Information 對話框定義組件模板編寫基本的組件相當(dāng)容易。創(chuàng)建組件模板甚至更容易。定義組件模板的步驟與創(chuàng)建窗體基本相同。增加組件,修改其特性,并編寫事件特性。像其他單元一樣,對窗體(或數(shù)據(jù)模塊)進行單元測試。工作完成后,就可以創(chuàng)建組件模板,選擇組件,并將其添加到組件模板。注意: Delphi 組件模板存儲在Delphi 的 Bin 目錄下的二進制文件Delphi.dct中。 Windows錯誤地把該文件和FoxProDataBaseContainer文件類型關(guān)聯(lián)在一起??紤]第 3 章的 Edit 程序中對 Edit 菜單編寫菜單。您可以花費一些時間來查找所有的 Windows Se
21、ndMessage 代碼;而下一次在另一個程序里創(chuàng)建消息,并在應(yīng)用Edit 菜單時,您還得做同樣的事情。從菜單資源模板重新創(chuàng)建菜單您可以選擇使用Insert Template 對話框中的Edit菜單,如圖11.4 所示。使用MenuDesigner 上下文菜單添加一個菜單的步驟如下:圖 11.4 Insert Template 對話框可以從存儲的資源中重新創(chuàng)建菜單。但并不包括代碼1從 VCL 的 Standard 屬性頁上選擇MainMenu 組件。2雙擊 MainMenu 圖標(biāo)向窗體添加菜單。3右擊MainMenu組件,顯示TMainMenu組件的組件編輯器菜單,并選擇MenuDesigne
22、r 菜單項(如圖11.5 所示)。這樣可以打開菜單編輯器,如圖11.4 的背景所示。4右擊鼠標(biāo),打開菜單編輯器的上下文菜單,并選擇Insert From Template 菜單項,如圖 11.6 所示。5從 Insert Template 對話框中(如圖 11.4 所示),雙擊 Edit 菜單模板,以添加編輯菜單。這就是所有的工作。上述五個步驟將把 TMenuItem 組件添加到窗體類定義的開頭。使用菜單資源模板需要對 OnClick 事件方法重新編寫代碼。更好的方法是使用組件模板,這可以包括代碼。圖 11.5點擊 TMainMenu 組件的組件編輯器菜單上的Menu Designer 菜單項
23、圖 11.6菜單設(shè)計器的上下文菜單,對于管理菜單資源模板很方便創(chuàng)建并安裝菜單組件模板組件模板是Delphi 新增的功能。使用菜單資源模板存儲菜單必須重新編寫代碼,而使用組件模板則不必如此。還使用上一節(jié)提到的 Edit 菜單,它是在第 3 章中實現(xiàn)的。我們現(xiàn)在把整個菜單和代碼都保存為組件模板。1對 Edit 菜單編寫代碼(使用第3 章的例子,或步驟后列出的代碼)使控件呈現(xiàn)正確的行為。2用代碼測試Edit 菜單后,選擇包含Edit 菜單的 TMainMenu 組件并點擊Component| Create Component Template 菜單項。procedure TForm1.Edit1Cl
24、ick(Sender: TObject);begin/ CanUndo testUndo1.Enabled := Boolean(SendMessage(EM_CANUNDO, 0, 0 );end;procedure TForm1.Copy1Click(Sender: TObject);begin/ Copy menuprocedure TForm1.Cut1Click(Sender: TObject);begin/ Cut menuprocedure TForm1.Paste1Click(Sender: TObject);begin/ Paste menuend;procedure TFo
25、rm1.SelectAll1Click(Sender: TObject);begin/ select all textend;procedure TForm1.Undo1Click(Sender: TObject);begin/ Undo menuend;該代碼與第3 章中的類似。因此我們不再對細節(jié)進行重復(fù)?,F(xiàn)在我們已經(jīng)有了Edit菜單的組件模板,每次需要菜單、相應(yīng)的菜單項和代碼時就可以使用該模板。使用組件模板菜單現(xiàn)在已經(jīng)有了Edit 菜單模板,它可以像其他的組件一樣使用。要使用組件模板,從Template 屬性頁上選擇對應(yīng)的模板,像其他菜單一樣拖動到窗體上。菜單組件及其擁有的TMenuIte
26、ms 、以前寫過的代碼都可以添加到任何窗體上,而無需測試,也不會產(chǎn)生任何混亂的情況。擴展組件模板可以把組件模板看作組件類。當(dāng)創(chuàng)建組件模板時(如本節(jié)的前半部分的Edit 菜單),不要刪除它,當(dāng)需要新的行動時,可以對該模板進行擴展。添加新的行為可以擴展已有的組件,最后我們有原來的和新的組件模板。假設(shè)現(xiàn)在有Edit 菜單,要對其定義Find 菜單項。使用組件面板的Dialogs 屬性頁上的TFindDialog 組件。按照下列步驟,即可添加Find 功能并創(chuàng)建新的組件模板。1把在本節(jié)開頭保存的模板拖動到任意的窗體上。2從 Dialogs 屬性頁上拖動TFindDialog 組件到同一個窗體。3在窗體
27、上,點擊Edit , Find 菜單項,并添加代碼FindDialogl.Execute 。4為 TFindDialog.OnFind 事件添加事件方法, 并向事件處理程序添加一些代碼以提醒用戶實現(xiàn)查找行為。5選擇TMainMenu組件和FindDialog組件并單擊Component| Create ComponentTemplate菜單項,把合并的控件和代碼添加到template屬性頁。TFindDialog組件可能的代碼如下。procedure TForm1.Find1Click(Sender: TObject);beginFindDialog1.Execute;end;procedur
28、e TForm1.FindDialog1Find(Sender: TObject);beginMessageDlg( Implement find behavior!, mtInformation, mbOK, 0 );end;警告: 當(dāng)存儲模板組件時,確保使用惟一的名字。如果你使用已有的名字,那么 Delphi將提示你是否替換已有的模板,包括代碼在內(nèi)。這就是所需要的工作。通過將代碼分層添加到模板中,可以對完整的組件群體和提供功能的代碼創(chuàng)建精致的接口。然而使用組件面板也有一些缺點。組件面板并非真正的組件;它們只是寫入到二進制文件 Delphi.dct 中的文本。它們提供了方便,但卻放棄了靈活性
29、?;貞泴?SelectAll 菜單項的前一個實現(xiàn)。第 3 章開始部分列出的代碼中顯示的 ToDo 表明,事件方法需要進行修改才能對其他類型控件做出合適的響應(yīng)。 在 SelectAll 當(dāng)前的實現(xiàn)中, 是無法響應(yīng) TComboBox 之類的控件的。不幸的是,如果你返回來完成 SelestAll 行為,可以創(chuàng)建新的模板。但這對包含菜單和 Find 對話框的復(fù)合模板沒有影響。原來模板不會有什么改變,衍生的模板將繼續(xù)使用 SelectAll 的舊版本。如果模板代碼能夠繼承,而且可以自動更新有依賴關(guān)系的面板,那就太好了,但這并不是面向?qū)ο蟮睦^承,而是一種新型的資源流化機制。如果需要繼承,那就要創(chuàng)建新的類
30、并進行子類化。但組件模板仍然是一種流行的方法,只會變得更好而已。對于可視化的建立多數(shù)或全部組件這個目標(biāo)來說,我們已經(jīng)不遠了。刪除組件模板Component Templates包含在 Delphi.dct 文件中。該文件不像其他的組件庫,它并非軟件包的庫文件。因此無法像管理其他組件一樣管理組件目標(biāo)。為刪除組件目標(biāo),需要在組件面板上找到對應(yīng)的位置,并組件面板上下文菜單中點擊Properties 菜單項。參考圖11.7,從右邊的組件列表里選取要刪除的模板組件,然后點擊Delete 按鈕。圖 11.7 Palette Properties 對話框可用于刪除組件模板或隱藏組件提示:你不會意外地從圖11.
31、7 所示的Palette Properties對話框中刪除組件。如果選定了某個組件,Add 按鈕右側(cè)將出現(xiàn)一個Hide按鈕; 而如果組件實際上是一個模板,那么同一位置就出現(xiàn)Delete 按鈕。組件模板不同于組件,使用圖 11.7 所示的 Palette Properties 對話框只能隱藏組件。如果你刪除組件模板,也會刪除所有與之相關(guān)聯(lián)的代碼。把組件模板中的代碼保存到外部文件是個好主意,以防止意外刪除。關(guān)于組件模板的最后一個問題。 組件模板方便且易于使用, 但并非實際的組件。 以 Edit 菜單為例,模板比簡單的資源菜單使用起來更加方便。雖然可以創(chuàng)建精巧的模板,但從長遠看來,將復(fù)雜的代碼和相互
32、交織的組件關(guān)系封裝到類的話將更為可取。11.3窗體模板與窗體繼承與組件模板相比,窗體模板出現(xiàn)得更早一些。我們知道窗體是由TComponent 子類化而來,但如果將窗體直接安裝到VCL 中,可能會出現(xiàn)不正確的行為;因此在Delphi的早期版本里發(fā)明了窗體模板來解決這個問題(更多的信息請參見第10 章的對話框組件部分) 。很快發(fā)現(xiàn),窗體一般帶有許多代碼,而且大多數(shù)應(yīng)用程序里會重復(fù)出現(xiàn)許多類型的窗體,很顯然的一個例子就是About對話框。 幾乎所有應(yīng)用程序都有該對話框。但只是意外DFM文件與VCL無法很好的協(xié)作,就需要開發(fā)者為每個應(yīng)用程序繪制一個About框并且添加必要的代碼來顯示該窗體嗎?答案是,
33、你不必如此。最后,我們可以把窗體添加到存儲庫中,存儲庫中的窗體可以直接使用、繼承和復(fù)制。注意: 在技術(shù)上,與窗體繼承相關(guān)的最大的困難可能就是,如何使DFM流機制正確地工作。為了深入了解DFM 流化機制, 看第 10 章的“對象流化與窗體繼承”一節(jié)。窗體繼承機制現(xiàn)在已經(jīng)工作得很好了。對于開發(fā)者來說,所有這些意味著又添加了一個強有力的方法來重用整個程序。下面的方法都可以促進代碼與界面設(shè)計的重用,包括保存菜單資源,創(chuàng)建組件模板,將窗體添加到存儲庫并重用;當(dāng)然最強大的方法是創(chuàng)建新類。創(chuàng)建窗體模板窗體模板是保存并添加到存儲庫的窗體。在上一節(jié)中,我們還記得一個包含TMainMenu 組件的窗體, 其中有編
34、輯菜單,還包括查找功能; 我們把窗體添加為組件模板。通過把窗體添加到存儲庫中,然后把組件模板放置到窗體上,即可迅速地啟動一個主窗體。向存儲庫添加窗體為實驗創(chuàng)建窗體模板的過程,我們將包含TMainMenu 和 TFindDialog 的組件模板添加到空 白窗體上(如果你在上一節(jié)中沒有創(chuàng)建組件模板而還想繼續(xù)的話,只能先把TMainMenu和 TFindDialog 組件拖動到空白窗體上)。按照下列步驟,可以將窗體添加到存儲庫(見圖11.8)。圖 11.8 MainForm 模板,其中包含 TMainMenu 和 TFindDialog 組件1右擊要添加為模板的窗體,以顯示窗體設(shè)計器上下文菜單。2選
35、擇 Add to Repository 菜單項。3填寫 Add To Repository 對話框,需要為模板窗體提供標(biāo)題和描述(見圖11.8),并選擇要加入的屬性頁,輸入作者信息和圖標(biāo)。4點擊OK按鈕。如果尚未保存文件,在添加到存儲庫之前Delphi將提示你保存文件。如果向Add To Repository對話框中的Page 組合框文本域中輸入并不存在的屬性頁名,Delphi將創(chuàng)建新的屬性頁。這是一個對窗體模板進行組織的好方法?,F(xiàn)在,無論何時需要帶有主菜單的窗體,其中包括編輯和查找功能,只需選擇New ,Other 菜單項,然后從 New Items 對話框的Forms 屬性頁上選擇對應(yīng)模板
36、(見圖File,11.9)。圖 11.9從 New Items 對話框選擇與目標(biāo)最為接近的窗體目標(biāo)存儲庫的維護大多數(shù)人都有一個用于存放物品的地方。存儲庫就是個存放物品的地方。最后您可能需要對存儲庫中的目標(biāo)重新進行組織或刪除某些模板。Tools 菜單有一個Repository 菜單項,可以打開Object Repository 對話框(見圖11.10)。對話框的左側(cè)列出了所有可以修改的 Repository 屬性頁, 包括 Forms 屬性頁, 其中有用戶定義窗體模板的。像 New 和 ActiveX等屬性頁是不可修改的。要增加、 刪除、重新命名符合條件的屬性頁,只需選擇相應(yīng)的屬性頁并點擊Add
37、 Page、Delete Page、Rename Page 中某個合適的按鈕。要從Objects 列表中編輯或刪除某個模板,在左側(cè)選擇包含該模板的頁并在右側(cè)的Objects 列表中點擊相應(yīng)的模板。例如要刪除上一節(jié)定義的 FormMain 模板,首先點擊左側(cè)Pages 列表框中的Forms 項。所有的窗體模板將在右側(cè)的 Objects 列表框中列出。找到MainForm 模板,單擊以選取它并點擊Delete Object按鈕(如圖11.10 所示,選定了Main Form 窗體)。圖 11.10Object Repository對話框NEW FORM也可以在Object Repository 中
38、選擇缺省的New Form 復(fù)選框, 用于表示在 Delphi 中點擊 File| New | Form 菜單項時將創(chuàng)建哪個窗體。缺省情況下并未選定NewForm 復(fù)選框,但很容易就可以將FormMain 作為默認的新窗體(選取窗體的指令,請參見前面的章節(jié))。選取窗體后,選定圖11.10 所示的 New Form 復(fù)選框并點擊OK 按鈕。MAIN FORM當(dāng)創(chuàng)建新的可執(zhí)行應(yīng)用程序時例如當(dāng)Delphi 啟動時缺省情況下主窗體是空白窗體。 另外,你還可以在Delphi中點擊 Tools | Repository 菜單項打開ObjectRepository 對話框。當(dāng)存儲庫被打開后, 選取所需的新窗
39、體作為主窗體并選定Main Form復(fù)選框(如圖 11.10 所示)。這樣,每次創(chuàng)建新應(yīng)用程序時,將使用該窗體作為缺省的主窗體。向存儲庫添加工程可以將整個的工程添加到存儲庫。完整的工程由工程中的DPR 文件、所有的源代碼、窗體和數(shù)據(jù)模塊組成。如果要把一個或多個窗體定義為工程模板,可以使用Project 菜單將工程添加到存儲庫。要向存儲庫添加工程,首先選擇要添加工程,然后點擊Project | Add toRepository 菜單項。這時將顯示Add to Repository 對話框,它與窗體模板的情形類似(見圖 11.8),由于將添加所有窗體,所以不需要選擇添加哪個窗體。將工程添加到存儲庫
40、后, 點擊 File | New | Other 菜單項, 然后從 New Items 對話框中選擇所需的工程,即可基于已有的工程啟動一個新的工程??捎糜诜胖霉こ棠0宓暮玫胤绞?Projects 屬性頁,盡管在添加工程時也可以創(chuàng)建新的屬性頁。提示:如果要把缺省的工程從標(biāo)準的可執(zhí)行程序改變?yōu)榇鎯熘械哪硞€工程,那么可以從Tools 菜單中打開對象存儲庫,并將相應(yīng)的工程設(shè)置為新的缺省工程。選定一個工程后,Objects 列表框下將出現(xiàn)New Project復(fù)選框。 選定該復(fù)選框,則對應(yīng)的工程將成為新的缺省工程。當(dāng)從 New Items 對話框中選擇一個工程模板時, Delphi 將提示您為該工程輸
41、入路徑,這時 Delphi 相應(yīng)創(chuàng)建該工程中所有的文件。要避免選擇創(chuàng)建工程模板時的原始路徑;如果這樣做你將覆蓋原來的存儲庫文件。也可以從Object Repository對話框中刪除工程模板。細節(jié)請參考前面,標(biāo)題為“存儲庫的維護”一節(jié)。使用模板窗體當(dāng)使用模板創(chuàng)建新窗體時,有三種選擇??梢栽贜ew Items 對話框的Forms 屬性頁上選擇 Copy 、Inherit 或 Use 三者之一。缺省情況下,將選擇Copy 。您可以得到窗體的完整副本,但不會維護模板窗體與新窗體之間的進一步的關(guān)系(如果選擇Use,那么實際上將修改存儲庫中的窗體模板;即,任何改變都會反映到窗體在存儲庫中的版本)。如果選
42、擇Inherit ,將繼承模板窗體,這里的繼承指的是面向?qū)ο蟮囊饬x。對窗體在存儲庫中版本的改變將反映到子窗體??紤]到主窗體含有Edit 菜單和 Find 對話框。 如果使用某個主窗體模板創(chuàng)建新的窗體,新窗體將子類化那個窗體。以后,再選擇該主窗體模板以及 Use 選項,添加一個Replace 對話框,則所有的子窗體在下次編譯時將自動具有Replace行為。由 DFM文件的內(nèi)容可以看出原始窗體、副本窗體、以及使用模板窗體創(chuàng)建的子窗體之間的不同。下面的片斷來自三個獨立的DFM 文件,分別演示了基于Use、Inherit 、Copy方式創(chuàng)建窗體時數(shù)據(jù)寫入DFM 文件的方式。這三個窗體都與窗體類TFor
43、mMain有關(guān)。object FormMain: TFormMainLeft = 435Top = 254Width = 418Height = 320Caption = Application Title Here上面列出的是實際的窗體。當(dāng)在 New Items 對話框的 Forms 屬性頁中選擇 Use 時,將得到模板窗體。object FormMain1: TFormMain1Left = 435Top = 254Width = 418Height = 320Caption = Application Title Here當(dāng)選擇該窗體是從Copy 時,得到的是TFormMain1 ,看上
44、去像是TFormMainTForm 子類化而來。所擁有的組件都被復(fù)制并流化到DFM的子類,但實際上文件中,但在模板和窗體副本之間不存在更進一步的關(guān)系。inherited FormMain4: TFormMain4Caption = FormMain4PixelsPerInch = 120TextHeight = 16end上面列出的DFM 文件是從TFormMain 繼承時創(chuàng)建的。與前面的兩個DFM 文件不同,第一個詞不是object,而是 inherited 。這是個約定, 用于表示應(yīng)從祖先窗體讀取額外的流化信息。當(dāng)要對所有的祖先都作出持久性的改變時,可修改原始窗體。若希望父窗體與子窗體之間
45、的改變互不影響,應(yīng)使用復(fù)制;如果要對窗體的行為與外觀在整個家族中定義并維護一個核心集合,則應(yīng)使用繼承。組件模板、窗體模板、工程模板是三種極好的方法,可用于在一組應(yīng)用程序中維護工程內(nèi)和工程間的一致性。一致性是連貫性的一個因素。即使應(yīng)用程序提供了某些前所未見的功能,如果交互界面是一致的,那么經(jīng)過適當(dāng)?shù)膶W(xué)習(xí)之后新的任務(wù)看起來也會更加連貫。在應(yīng)用程序被認為具有完備性之前,它首先必須是一致和連貫的。另外,完備性還需要程序能夠合乎用戶的需求。11.4靜態(tài)與動態(tài)的組件用法當(dāng)把窗體添加到應(yīng)用程序時,將把一行代碼加入到DPR文件(工程源文件)中,以便在程序啟動時自動創(chuàng)建窗體。Application.Create
46、Form(TForm1, Form1);對于 Visual Basic 程序員或尚未完全掌握對象及動態(tài)對象創(chuàng)建的用法的新程序員來說,這可以使得添加和使用窗體更為容易。對外行人來說, 這實際上使得Delphi 和 Visual Basic看起來很相似:創(chuàng)建窗體、運行程序、調(diào)用show 或 show modal,然后用戶就可以使用窗體了。當(dāng)在窗體上繪制組件時,也是同樣。好像是有魔力一樣,它們在運行時出現(xiàn)時,自然的就具有設(shè)計時的狀態(tài)以及任何由自己編寫的代碼所定義的行為。Delphi 與 Visual Basic 之間的相似性在這里結(jié)束了。與 Visual Basic相比,Object Pascal(
47、 Delphi 的語言) 與 C+ 更為相似。 Delphi 像 Visual Basic 一樣易于使用, 并具有 C+ 的強大功能。這意味著新的程序員也能立即開始,而經(jīng)驗豐富的老手則能夠創(chuàng)建非常復(fù)雜的應(yīng)用程序。Delphi 自動創(chuàng)建窗體或在運行時自動創(chuàng)建組件時,其行為是一致的。而且,已經(jīng)對流化機制編碼,知道如何解析組件引用、從 DFM 文件里讀出屬性、構(gòu)造對象。當(dāng) Delphi 自動創(chuàng)建窗體和組件時,與手工使用代碼來創(chuàng)建的方式是一致的。動態(tài)創(chuàng)建窗體到現(xiàn)在為止,您可能已經(jīng)熟悉如何繪制程序所擁有的窗體了。有些程序員允許自動創(chuàng)建所有的窗體,但這會使可執(zhí)行文件變得相當(dāng)大并降低程序的啟動速度。大多數(shù)用
48、戶通常只使用某些核心功能,從來或很少使用其他功能。最終結(jié)果是用戶為一些從不使用的功能付出了性能方面的代價。好一些的方法是在需要的時候才創(chuàng)建窗體、數(shù)據(jù)模塊以及加載庫。這實際上是通過推遲堆內(nèi)存的分配以及窗體流數(shù)據(jù)的讀取,以便降低程序啟動時一次性創(chuàng)建窗體的成本,該技術(shù)有個名字,可以稱之為惰性實例化(lazy instancing )。在 Project Options 對話框的Forms 屬性頁中,將窗體和數(shù)據(jù)模塊從auto create 欄移動到 available 欄,即可推遲窗體的創(chuàng)建。雖然在啟動時性能有所提高,但以后在運行時動態(tài)創(chuàng)建窗體是要付出代價的;除非該功能對時間要求非常高或經(jīng)常使用,否
49、則在需要時動態(tài)創(chuàng)建窗體比一次性創(chuàng)建所有的窗體更為可取。有兩種技術(shù)可用于創(chuàng)建惰性實例,分別討論如下。顯式構(gòu)造顯式構(gòu)造是指調(diào)用窗體構(gòu)造函數(shù)創(chuàng)建窗體,如何使用窗體,最后釋放創(chuàng)建窗體所用的內(nèi)存。Form := TForm.Create(self);tryif( Form.ShowModal = mrOK ) then/ doe herefinally Form.Free;end;如果把窗體作為模式對話框來顯示, 該技術(shù)工作得很好, 因為在調(diào)用 ShowModal 時代碼的運行是同步的。只要關(guān)閉窗體,內(nèi)存也就被釋放了。另外,您也可以顯示窗體并讓窗體在關(guān)閉時自行釋放內(nèi)存。TForm.Create(Self).Show;被創(chuàng)建的窗體需要一個 OnClose 事件處理程序,以便進行一些設(shè)置,這樣當(dāng)窗體關(guān)閉時它可以將自身從內(nèi)存中釋放出去。procedure TForm1.FormClose(Sender: TObject; var Action:TCloseAction);begi
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度模具鋼材行業(yè)聯(lián)盟共建與資源共享合同4篇
- 2025年度電商虛擬貨幣交易服務(wù)合同11篇
- 2024年度青海省公共營養(yǎng)師之三級營養(yǎng)師模考預(yù)測題庫(奪冠系列)
- 二零二五年度美食攤位租賃與品牌孵化合同4篇
- 2025年度個人出納職業(yè)擔(dān)保合同規(guī)范范本3篇
- 2025年度體育館窗簾安裝與運動安全合同4篇
- 二零二五年度彩鋼房智能安防系統(tǒng)集成合同3篇
- 二零二五年度拍賣會場地租賃合同4篇
- 二零二四年度員工宿舍物業(yè)管理與社區(qū)和諧共建合同3篇
- 2025年度電熱水器售后服務(wù)品牌形象設(shè)計與宣傳合同4篇
- 鹽酸??颂婺崤R床療效、不良反應(yīng)與藥代動力學(xué)的相關(guān)性分析的開題報告
- 消防設(shè)施安全檢查表
- 組合結(jié)構(gòu)設(shè)計原理 第2版 課件 第6、7章 鋼-混凝土組合梁、鋼-混凝土組合剪力墻
- 建筑公司資質(zhì)常識培訓(xùn)課件
- 旅居管家策劃方案
- GB/T 26316-2023市場、民意和社會調(diào)查(包括洞察與數(shù)據(jù)分析)術(shù)語和服務(wù)要求
- 春節(jié)值班安全教育培訓(xùn)
- 帶狀皰疹護理查房
- 平衡計分卡-化戰(zhàn)略為行動
- 幼兒園小班下學(xué)期期末家長會PPT模板
- 幼兒教師干預(yù)幼兒同伴沖突的行為研究 論文
評論
0/150
提交評論