附錄A使用OPENTOOLSAPI的D擴展示例_第1頁
附錄A使用OPENTOOLSAPI的D擴展示例_第2頁
附錄A使用OPENTOOLSAPI的D擴展示例_第3頁
附錄A使用OPENTOOLSAPI的D擴展示例_第4頁
附錄A使用OPENTOOLSAPI的D擴展示例_第5頁
已閱讀5頁,還剩28頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、 PAGE 532Delphi 6運用開發(fā)指南.附錄A 運用OPENTOOLS API的Delphi擴展例如 PAGE 531:.;附錄A 運用OPENTOOLS API的Delphi擴展例如附錄A與第11章的內(nèi)容前后承襲。閱讀第11章之后,您曾經(jīng)了解了創(chuàng)建定制組件的大部分知識。附錄A也很重要,它示范了如何創(chuàng)建組件編輯器以及運用OpenTools API對Delphi本身進展擴展。二者分屬不同的主題:一個與組件相關(guān),另一個那么是要擴展Delphi。之所以將二者放到附錄中,是由于它們沒有其他技術(shù)那樣常用。但要用到二者的時候,它們都是很有用的。定制組件編輯器可以定義設(shè)計時對話框,編輯器在Objec

2、t Inspector不夠用時,使得用戶可以可視化地修正特定于該組件的每個方面。一個很好的例子就是TChart組件,由Dave Berneda開發(fā)。另外,在設(shè)計時您還可以從組件的上下文菜單中運轉(zhuǎn)該組件所包含的代碼。假定您運用Delphi曾經(jīng)有一段時間了,而您以為Delphi缺乏某些必要的特征。我三年前在一個工程上任務(wù)時,就發(fā)生了這樣的情況。當(dāng)時正在對Rational Rose所定義的系統(tǒng)構(gòu)造模型進展編碼,我們曾經(jīng)膩煩了手工定義類并編寫函數(shù)體。真實是太煩了。創(chuàng)建一個類來讀取類的聲明并編寫函數(shù)體,這看來是個不錯的主意。運用OpenTools API,有時候再借助一下Ray Lischner的書,我

3、們最終向Delphi添加了一個可以調(diào)用類生成器的菜單項。結(jié)果終于擺脫了這本來可以自動完成的、煩人的義務(wù)惋惜的是我們沒有一本語法分析方面的好書,我有點離題了。這準確地描畫了Inprise公司在決議向Delphi專業(yè)版和企業(yè)版用戶提供OpenTools API時的想法。當(dāng)需求Delphi具有某些功能時,添加上去就行了。Delphi如今還具有“Complete class at cursor的代碼生勝利能,因此我們可以創(chuàng)建一個尚不存在的專家:可以生成專家的專家。當(dāng)您閱讀本章后,可以了解到如何創(chuàng)建組件編輯器以及怎樣運用專家對Delphi進展定制。有一個工具可用于開發(fā)定制專家,這使得創(chuàng)建專家與創(chuàng)建組件一

4、樣容易。A.1 OpenTools API引見OpenTools API原來定義為籠統(tǒng)虛類,即它運用了Delphi接口,而我們可以承繼它以便向Delphi添加擴展。原來的那些單元依然存在于他安裝的Delphi的SourceToolsAPI子目錄下,但在大多數(shù)情況下它們曾經(jīng)讓位于ToolsAPI.pas單元中定義的COM接口。留意:ToolsAPI單元與Delphi專業(yè)版和企業(yè)版一同發(fā)布。您也可以對Delphi規(guī)范版進展定制,只是包含相應(yīng)接口的單元在Delphi規(guī)范版中是沒有的。假設(shè)您對Delphi籠統(tǒng)接口比較熟習(xí),那么比從零開場要好一些。不論怎樣,您都應(yīng)該學(xué)習(xí)COM接口,這正是我們在本章中要做

5、的。A.1.1 OpenTools接口大多數(shù)情況下,OpenTools接口都是位于SourceToolsAPIToolsAPI.pas單元中的COM接口。為提高后向兼容性,該目錄下也定義了風(fēng)格較老的Delphi接口。表A.1完好地列出了ToolsAPI中的一切單元。帶有星號的單元包含了風(fēng)格較老的Delphi接口,通常應(yīng)該防止在較新的代碼中運用。警告:很差的是,這些單元在協(xié)助 文件中并沒有很好的文檔。首先要參考單元中的代碼;代碼中的注釋很有協(xié)助 ,但默許某些知識;而經(jīng)過仔細查找,我們發(fā)現(xiàn)幾乎完全沒有集成化的協(xié)助 。這真是個不幸,假設(shè)要進展擴展,您必需閱讀許多代碼并進展實驗。表A.1 Delphi

6、 ToolsAPI單元列表。經(jīng)過實現(xiàn)ToolsAPI.pas單元中定義的COM接口,可以訪問Delphi的大部分功能單元描畫toolsapi.pas包含了新的COM接口,它交換了在其他單元中可以找到的風(fēng)格較老的接口本章中將廣泛地運用該單元的接口vcsintf.pas包含了與版本控制系統(tǒng)進展鏈接的COM接口dsgnintf.pas包含了特性編輯器、組件編輯器以及注冊過程所需的接口例如,RegisterComponentEditoreditintf.pas*風(fēng)格較老的Delphi籠統(tǒng)接口,用于訪問編輯器緩存,例如單元的文本exptintf.pas*風(fēng)格較老的單元,其中包括了用于定義專家的籠統(tǒng)虛類T

7、IExpert;新代碼應(yīng)運用ToolsAPI單元中的COM接口fileintf.pas*風(fēng)格較老的單元,其中包括了用于訪問文件系統(tǒng)功能的籠統(tǒng)虛接口istreams.pas*包含了流、內(nèi)存流、文件流的接口toolintf.pas*與Delphi菜單和ToolServices相關(guān)的接口;在新代碼中應(yīng)運用ToolsAPI單元中的BorlandIDEServices COM對象以及IOTAMenuWizardvirtinft.pas*包含了TInterface的定義,以及Delphi對根本的COM接口IUnknown的實現(xiàn)留意:本章中能夠會交替運用導(dǎo)游和專家這兩個詞。它們都是指Delphi中的專家。之

8、所以運用兩個詞,是由于Inprise也并未確定運用單個詞。注冊過程運用導(dǎo)游這個詞,而COM接口也包含了導(dǎo)游這個詞。在Delphi中進展討論時,對這兩個詞進展區(qū)分是沒有意義的。如今曾經(jīng)無需了解進一步的細節(jié)了,我們來創(chuàng)建一個Delphi專家。A.1.2 創(chuàng)建導(dǎo)游對Delphi導(dǎo)游進展擴展的最為直接的途徑就是實現(xiàn)IOTAWizard和IOTAMenuWizard接口。這兩個接口都定義在ToolsAPI單元中,而且您可以看到,它們非常容易實現(xiàn)。留意:首字母縮略詞前綴IOTA指的是Interface for OpenTools API我是這樣以為的!,它也能夠是指一幕希臘劇,意思是指非常小的數(shù)量由于只需

9、很少量的代碼需求實現(xiàn)。實現(xiàn)IOTAWizard和IOTAMenuWizard最容易實現(xiàn)的導(dǎo)游是非常根本的IOTAWizard接口,它運用IOTAMenuWizard類來實現(xiàn)。IOTAWizard接口需求實現(xiàn)四個方法,而IOTAMenuWizard那么把一個菜單項放置到Help菜單上。由于剛剛起步,我們將以導(dǎo)游的方式實現(xiàn)一個Hello World例子。為使讀者不至于絕望,將在下一節(jié)實現(xiàn)一個較為有用的導(dǎo)游。下面的代碼定義IOTAWizard和IOTAMenuWizard。實現(xiàn)根本的導(dǎo)游并顯示在Help菜單上,需求實現(xiàn)IOTAWizard接口的四個方法:GetIDString、GetName、Get

10、State和Execute。由于IOTAWizard承繼了IOTANotifier接口,您還需求實現(xiàn)IOTANotifier接口??梢赃\用TNotifierObject存根類作為IOTANotifier接口的實現(xiàn)。IOTANotifier接口引入了AfterSave、BeforeSave、Destroyed和Modified方法,以便對事件進展呼應(yīng)。對這個練習(xí)而言,該存根類就足夠了。IOTAMenuWizard承繼了IOTAWizard接口。在IOTAMenuWizard類中,獨一需求實現(xiàn)的方法是GetMenuText,該方法前往在Help菜單上顯示的文本。IOTAWizard = inter

11、face(IOTANotifier)B75C0CE0-EEA6-11D1-9504-00608CCBF153 Expert UI strings function GetIDString: string;function GetName: string;function GetState: TWizardState; Launch the AddIn procedure Execute;end;IOTAMenuWizard = interface(IOTAWizard)B75C0CE2-EEA6-11D1-9504-00608CCBF153function GetMenuText: strin

12、g;end;這個沒有實踐功能的導(dǎo)游定義為TDummyWizard類,該類是TNotifierObject、IOTAWizard以及IOTAMenuWizard的子類。它實現(xiàn)了上面代碼所列出的接口中的五個方法。完好的實現(xiàn)代碼如下。unit UDummyWizard;/ UDummyWizard.pas - Demonstrates basic wizard interface/ Copyright (c) 2000. All Rights Reserved./ By Software Conceptions, Inc. softconcepts/ Written by Paul Kimmel.

13、Okemos, MI USAinterfaceusesWindows, ToolsAPI;typeTDummyWizard = class(TNotifierObject, IOTAWizard,IOTAMenuWizard)publicfunction GetIDString : String;function GetName : String;function GetState : TWizardState;procedure Execute;function GetMenuText : String;end;procedure Register;implementationusesDia

14、logs;procedure Register;beginRegisterPackageWizard(TDummyWizard.Create);end; TDummyWizard procedure TDummyWizard.Execute;beginMessageDlg( Building Delphi 6 Applications, mtInformation,mbOk, 0 );end;function TDummyWizard.GetIDString: String;beginresult := SoftConcepts.DummyWizard;end;function TDummyW

15、izard.GetMenuText: String;beginresult := Dummy Wizard;end;function TDummyWizard.GetName: String;beginresult := Dummy Wizard;end;function TDummyWizard.GetState: TWizardState;beginresult := wsEnabled;end;end.Register過程以TDummyWizard的一個實例為參數(shù)調(diào)用了RegisterPackageWizard。您可以像安裝組件一樣把專家安裝到包中,如上例。實踐上,進展安裝最容易的方法就

16、是運用Delphi中的Component | Install Component菜單項。當(dāng)用戶單擊添加的菜單項時,即可調(diào)用這個非常根本的導(dǎo)游。當(dāng)單擊菜單項時,將調(diào)用導(dǎo)游實現(xiàn)的Execute方法來呼應(yīng)。TDummyWizard在一個TMessageDlg對話框中顯示本書的標題。當(dāng)然,假設(shè)您確定的話,可以在Execute方法中參與幾乎任何級別的復(fù)雜行為。GetIDString方法前往導(dǎo)游的字符串標識符。按照慣例,該ID的前綴是您公司的名字,這里運用了Software Concepts, Inc公司的注冊商標SoftConcepts,并將其經(jīng)過圓點銜接到導(dǎo)游的名字。GetMenuText的實現(xiàn)代碼中

17、包含了顯示在協(xié)助 菜單上的菜單項文本。當(dāng)每次單擊Delphi的Help菜單上相應(yīng)菜單項時,都會調(diào)用該方法。GetName方法前往導(dǎo)游的名字,而GetState方法那么前往TWizardState類型值。該類型定義如下:TWizardState = set of wsEnabled, wsChecked;wsEnable表示該導(dǎo)游能否是活動的,而wsChecked值那么在菜單項上放置一個檢查標志。從代碼可以看到,根本的Help菜單導(dǎo)游所需的代碼非常少。當(dāng)安裝導(dǎo)游后,Delphi的協(xié)助 菜單上出現(xiàn)了一個新的菜單項Dummy Wizard。當(dāng)用戶單擊導(dǎo)游時,將調(diào)用Execute方法,從而在TMess

18、ageDlg對話框上顯示文本“Building Delphi 6 Applications。關(guān)于相應(yīng)的菜單項和單擊后的反響,可以參見圖A.1和A.2。圖A.1 Dummy Wizard添加到Delphi的Help菜單圖A.2 當(dāng)單擊Dummy Wizard菜單項時,將顯示TMessageDlg對話框,其代碼可以參見Execute方法注冊導(dǎo)游把導(dǎo)游添加到包,并像組件一樣對其進展安裝,即可擴展Delphi。當(dāng)把包編譯為BPL庫之后,將調(diào)用上一節(jié)的Register過程來進展安裝。如上一小節(jié)的代碼所示,RegisterPackageWizard需求導(dǎo)游的一個實例作為參數(shù)。RegisterPackage

19、Wizard定義在ToolsAPI.pas單元中,其參數(shù)為IOTAWizard類型的常量援用,該過程聲明如下:procedure RegisterPackageWizard(const Wizard: IOTAWizard);要安裝導(dǎo)游,可以按照以下步驟進展。在Delphi中,單擊Component | Install Component菜單項。在Install Component對話框中,假設(shè)單元尚未顯示在Unit file name域中,那么單擊Browse按鈕找到相應(yīng)的單元。假設(shè)要在當(dāng)前包中安裝專家,單擊OK。否那么單擊Into new package屬性頁見圖A.3,并給出包的名字及描

20、畫。圖A.3 圖中為Install Component導(dǎo)游,用于將向 導(dǎo)安裝到包。所需步驟與安裝組件時一樣當(dāng)單擊OK后,給出的包將在包編輯器中翻開見圖A.4。單擊Compile按鈕見圖A.4。對包進展編譯之后,Install曾經(jīng)可用,單擊該按鈕。要記住,包在本質(zhì)上是動態(tài)鏈接庫,也是一種運用程序。因此,可以而且應(yīng)該像其他程序一樣對選項進展設(shè)置。要參與途徑和版本音訊,并記得設(shè)置對所處的開發(fā)階段可用的編譯器選項??梢詤⒖记懊娴牡?8章,在測試時運用運轉(zhuǎn)時錯誤和調(diào)試選項,而在測試終了后、運用程序打包之前去掉這些選項。圖A.4 包編輯器用于編譯并安裝包A.2 創(chuàng)建定制導(dǎo)游像New Component W

21、izard這樣有用的導(dǎo)游,可以減少編寫代碼的數(shù)量,使得不用手工編寫一些可以自動完成的代碼;而且有助于開發(fā)者在越過妨礙之后發(fā)現(xiàn)Delphi的一些新的功能。為堅持導(dǎo)游的這種功能,本節(jié)給出了一個New Expert專家;正好像New Component對話框跳過了開場組件單元的步驟一樣,New Expert的作用也是類似的。A.2.1 定義New Expert WizardNew Expert的功能是,它可以生成一些與本章開頭的Dummy Wizard類似的專家。而New Expert本身將安裝在Component菜單上New Component菜單項之后。要建立該導(dǎo)游并將其安裝到Component

22、菜單上,我們需求實現(xiàn)IOTACreator和IOTAModuleCreate,而且還需求查詢BorlandIDEServices以獲得INTAServices40。INTAServices40對象定義了向特定的Delphi菜單添加菜單項的行為。導(dǎo)游的類是TNewExpertWizard。當(dāng)單擊Component | New Expert菜單項見圖A.5時,它生成一個與TDummyWizard幾乎一樣的類。將特定的行為添加到生成的Execute方法,然后就可以了。完好的代碼列表如下,對相關(guān)部分的描畫分為小節(jié),以便使您可以清楚地了解其作用。圖A.5 將New Expert導(dǎo)游添加到INTAServ

23、ices40對象之后unit UNewExpertWizard;/ UNewExpertWizard.pas - An example of a wizard that generatesthe code for a wizard/ Copyright (c) 2000. All Rights Reserved./ By Software Conceptions, Inc. softconcepts/ Written by Paul Kimmel. Okemos, MI USAinterfaceusesWindows, Controls, ToolsAPI, Forms, Menus, Cla

24、sses, SysUtils;typeTNewExpertWizard = class(TNotifierObject, IOTAWizard,IOTACreator,IOTAModuleCreator)privateFNewClassName : string;FMenuText : string;FExpertIDString : string;FExpertName : string;FUnitName : String;FWizardState : TWizardState;FMenuItem : TMenuItem;procedure AddMenuItem;procedure On

25、Click( Sender : TObject );procedure GenerateCode;publicconstructor Create; virtual;destructor Destroy; override; IOTAWizard function GetIDString : String;function GetName : String;function GetState : TWizardState;procedure Execute; IOTACreator function GetCreatorType : string;function GetExisting :

26、Boolean;function GetFileSystem : string;function GetOwner : IOTAModule;function GetUnnamed : Boolean; IOTAModuleCreator function GetAncestorName : string;function GetImplFileName : string;function GetIntfFileName : string;function GetFormName : string;function GetMainForm : Boolean;function GetShowF

27、orm : Boolean;function GetShowSource : Boolean;function NewFormFile( const FormIdent, AncestorIdent : string) : IOTAFile;function NewImplSource( const ModuleIdent, FormIdent,AncestorIdent : string ) : IOTAFile;function NewIntfSource( const ModuleIDent, FormIdent,AncestorIdent : string ) : IOTAFile;p

28、rocedure FormCreated( const FormEditor : IOTAFormEditor );end;procedure Register;implementationuses UFormMain, Dialogs, UExpertUnit;$R *.RESprocedure Register;beginRegisterPackageWizard(TNewExpertWizard.Create);end; TNewExpertWizard constructor TNewExpertWizard.Create;begininherited;AddMenuItem;end;

29、destructor TNewExpertWizard.Destroy;beginif( Assigned(FMenuItem) thenFMenuItem.Free;inherited;end;procedure TNewExpertWizard.OnClick( Sender : TObject );beginExecute;end;procedure TNewExpertWizard.AddMenuItem;varNTAServices40 : INTAServices40;ComponentMenuItem : TMenuItem;beginNTAServices40 := Borla

30、ndIDEServices As INTAServices40;if( Not Assigned(NTAServices40) then exit;ComponentMenuItem :=NTAServices40.MainMenu.Items.Find(&Component);if( Not Assigned( ComponentMenuItem) then Exit;FMenuItem := TMenuItem.Create( ComponentMenuItem );tryFMenuItem.Caption := New &Expert.;FMenuItem.OnClick := OnCl

31、ick;ComponentMenuItem.Insert( 1, FMenuItem );exceptFreeAndNil(FMenuItem);end;end;procedure TNewExpertWizard.Execute;varForm : TFormMain;beginForm := TFormMain.Create(Application);tryif( Form.ShowModal = mrOK ) thenbeginFNewClassName := Form.NewClassName;FMenuText := Form.MenuText;FExpertIDString :=

32、Form.ExpertIDString;FExpertName := Form.ExpertName;FUnitName := Form.UnitName;FWizardState := Form.WizardState;GenerateCode;end;finallyForm.Free;end;end;function TNewExpertWizard.GetIDString: String;beginresult := SoftConcepts.NewExpertWizard;end;function TNewExpertWizard.GetName: String;beginresult

33、 := Expert;end;function TNewExpertWizard.GetState: TWizardState;beginresult := wsEnabled;end;function TNewExpertWizard.NewImplSource(const ModuleIdent,FormIdent,AncestorIdent: string): IOTAFile;beginresult := TExpertUnit.Create( FNewClassName, FMenuText,FExpertIDString,FExpertName, FUnitName, FWizar

34、dState );end;procedure TNewExpertWizard.GenerateCode;begin(BorlandIDEServices as IOTAModuleServices).CreateModule(Self);end;procedure TNewExpertWizard.FormCreated(const FormEditor:IOTAFormEditor);begin/ Intentionally left blankend;function TNewExpertWizard.GetAncestorName: string;beginresult := ;end

35、;function TNewExpertWizard.GetFormName: string;beginresult := ;end;function TNewExpertWizard.GetImplFileName: string;beginresult := FUnitName;end;function TNewExpertWizard.GetIntfFileName: string;beginresult := ;end;function TNewExpertWizard.GetMainForm: Boolean;beginresult := False;end;function TNe

36、wExpertWizard.GetShowForm: Boolean;beginresult := False;end;function TNewExpertWizard.GetShowSource: Boolean;beginresult := True;end;function TNewExpertWizard.NewFormFile(const FormIdent,AncestorIdent: string): IOTAFile;beginresult := Nil;end;function TNewExpertWizard.NewIntfSource(const ModuleIDent

37、,FormIdent,AncestorIdent: string): IOTAFile;beginresult := Nil;end;function TNewExpertWizard.GetCreatorType: string;beginresult := sUnit;end;function TNewExpertWizard.GetExisting: Boolean;beginresult := False;end;function TNewExpertWizard.GetFileSystem: string;beginresult := ;end;function TNewExpert

38、Wizard.GetOwner: IOTAModule;beginresult := nil;end;function TNewExpertWizard.GetUnnamed: Boolean;beginresult := False;end;end.New Expert的類定義TNewExpertWizard類承繼了TNotifierObject存根類,以及IOTAWizard、IOTACreator和IOTAModuleCreator接口。IOTAWizard是根本的導(dǎo)游接口,而TNotifierObject那么對該接口中某些根本的事件處置程序?qū)崿F(xiàn)了一個存根。要創(chuàng)建一個根本的導(dǎo)游,您得實現(xiàn)

39、IOTAWizard接口。IOTACreator和IOTAModuleCreator用于與Delphi的文件視圖協(xié)同任務(wù),它們也包含了創(chuàng)建窗體和單元的才干。過一會兒我們繼續(xù)討論各個接口的實現(xiàn)。導(dǎo)游類的私有部分包含了幾個字段,用于正確地創(chuàng)建單元。FNewClassName存儲將要生成的導(dǎo)游的類名。而FMenuText那么存儲要生成的導(dǎo)游的菜單文本。FExpertIDString包含了專家的ID字符串。FExpertName字段包含了專家名。FUnitName是生成的.PAS單元的名字,而FWizardState包含了wsEnabled和wsChecked值。上述的每個特性都用于生成對接口的IOT

40、AWizard部分的根本呼應(yīng)。例如,IOTAMenuWizard需求用所顯示的菜單文本來呼應(yīng)。代碼生成器將從IOTAMenuWizard.GetMenuText得到FMenuText的值。私有部分還有FMenuItem,該字段用于維護對導(dǎo)游所添加菜單的援用。菜單項是經(jīng)過構(gòu)造函數(shù)中調(diào)用的AddMenuItem過程添加到Delphi的。OnClick事件處置程序包含了當(dāng)用戶單擊New Expert菜單項時見圖A.6的呼應(yīng)代碼。當(dāng)用戶填寫好如圖A.6所示的New Expert對話框之后,將調(diào)用私有方法GenerateCode。對話框中訊問了一些用于完成專家的必要的問題。專家類的名字是什么?用于觸發(fā)E

41、xecute方法的菜單項的文本是什么?創(chuàng)建的ID字符串是什么?專家的名字是什么?專家所對應(yīng)的單元名是什么?Wizard State中的復(fù)選框用于生成GetState的實現(xiàn)代碼。類的公有部分包括一些方法的聲明,這些方法是必需實現(xiàn)的,以履行接口承繼所構(gòu)成的契約。另外,除了從接口承繼的方法之外,還包括構(gòu)造函數(shù)和析構(gòu)函數(shù)。構(gòu)造函數(shù)將New Expert菜單項添加到Delphi,而析構(gòu)函數(shù)擔(dān)任釋放相應(yīng)的內(nèi)存。圖A.6 用于生成Delphi專家的New Expert對話框?qū)崿F(xiàn)IOTAWizard IOTAWizard接口需求實現(xiàn)GetIDString、GetName、GetState以及Execute方法

42、。GetIDString方法前往SoftConcepts.NewExpertWizard。按照慣例,ID字符串包括公司名和導(dǎo)游名,用圓點銜接。GetName前往Expert,這是該導(dǎo)游所顯示的名字。GetState前往包含wsEnabled的TWizardState集合,確保Component菜單上的導(dǎo)游是可用的。IOTAWizard接口中獨一較為困難的方法是Execute。當(dāng)單擊New Expert菜單項時見圖A.5,將調(diào)用Execute方法。Execute方法顯示一個對話框,如圖A.6所示。填寫New Expert對話框的一切域,然后單擊OK。由New Expert對話框得到的數(shù)據(jù)存儲在相

43、關(guān)的私有字段中,然后調(diào)用GenerateCode方法。GenerateCode調(diào)用IOTAModuleServices.CreateModule方法。由于TNewExpertWizard承繼了IOTACreator,因此它可用作CreateModule的參數(shù)。接著,CreateModule調(diào)用IOTAModuleCreator的方法,包括用于生成代碼的NewImplSource方法參考“向Delphi的菜單添加菜單項一節(jié),那里提供了關(guān)于如何從COM對象BorlandIDEServices查詢ToolsAPI效力的簡要討論。實現(xiàn)IOTACreator IOTACreator定義了用于與Delph

44、i的文件系統(tǒng)視圖協(xié)同任務(wù)的接口。IOTACreator用于為生成代碼提供方便。對于IOTACreator,我們實現(xiàn)了GetCreatorType、GetExisting、GetFileSystem、GetOwner以及GetUnnamed方法。從本節(jié)開頭列出的代碼可用看出,這些方法相對較為直觀。GetCreatorType前往ToolsAPI.pas中定義的sUnit。常量sUnit包含了值Unit,表示將創(chuàng)建單元。GetExisting前往False,由于我們正在創(chuàng)建新的單元;假設(shè)援用已有的單元,那么該方法將前往True。GetFileSystem前往TFileSystem對象的ID字符串,

45、導(dǎo)游將運用該對象來讀寫文件。它并不是必需的,因此該方法前往了空字符串。GetOwner前往對擁有模塊的援用。例如要將該模塊添加到一個已有的工程,我們需求查詢BorlandIDEServices以獲得已有的工程或包。我們將運用包編輯器來將新的專家添加到某個特定的包。GetOwner方法可以前往Nil。最后是GetUnnamed方法,假設(shè)我們前往未命名的單元,該方法將前往True。假設(shè)GetUnnamed前往True,Delphi將在第一次保管單元時提示用戶輸入文件名。如圖A.6的New Expert對話框所示,我們曾經(jīng)提供了單元名。要自動生成模塊并添加到翻開的包,您可以修正GetOwner方法,

46、查找活開工程組并將其作為GetOwner的結(jié)果前往。下面的代碼就足夠了。function TNewExpertWizard.GetOwner: IOTAModule;varModuleServices : IOTAModuleServices;ProjectGroup : IOTAProjectGroup;I : Integer;beginresult := Nil;ModuleServices := BorlandIDEServices As IOTAModuleServices;for I := 0 to ModuleServices.ModuleCount - 1 dobeginwith

47、 ModuleServices.ModulesI doif( Pos( .bpg, FileName ) 0 ) thenif( QueryInterface( IOTAProjectGroup, ProjectGroup ) =S_OK )thenbeginresult := ProjectGroup.GetActiveProject;exit;end;end;end;ModuleServices對象是由BorlandIDEServices對象前往的。將查找一切的模塊,以找到包含.bpg包擴展名的模塊。當(dāng)找到一個包以后,QueryInterface會測試該模塊能否實現(xiàn)了IOTAProject

48、Group接口。假設(shè)曾經(jīng)實現(xiàn)了該接口,那么將把ActiveProject作為函數(shù)結(jié)果前往。實現(xiàn)IOTAModuleCreator 在這個練習(xí)中,IOTAModuleCreator包含的方法數(shù)目是最多的。為與IOTA前綴的來源相一致,這些方法也都相對直觀而易于實現(xiàn)。表A.2包含了用于實現(xiàn)IOTAMoudleCreator接口的方法。雖然該表較小,但也夠用了,由于描畫都相對較短。表A.2 為IOTAModuleCreator接口所實現(xiàn)的方法。對New Expert導(dǎo)游最重要的是NewImplSource方法,該方法前往生成的源代碼接口方法描畫GetAncestorName前往模塊所承繼的祖先名;我

49、們運用了空字符串GetFormName該函數(shù)前往窗體名;由于并不生成窗體,所以我們也前往空字符串GetImplFileName前往由New Expert對話框讀取的、存儲在FUnitName中的單元名續(xù)表接口方法描畫GetIntfFileNameCPP頭文件名,這里前往空字符串,要記得Delphi與C+ Builder共享VCL代碼GetMainForm由于本模塊并非主窗體,所以GetMainForm前往FalseGetShowForm由于該導(dǎo)游并不與窗體相關(guān)聯(lián),所以依然前往FalseGetShowSource由于我們需求完成生成的專家導(dǎo)游中的Execute行為,因此前往True以顯示新的單元

50、NewFormFile前往IOTAFile對象,表示窗體文件的實例;假設(shè)生成的專家不需求窗體,那么前往NilNewImplSource這是個關(guān)鍵性的方法:該方法前往IOTAFile的子類,包含了生成的專家的源代碼。從代碼可以看到,該方法前往了TExpertUnit類的實例在“建立代碼生成器一節(jié)中,我們將繼續(xù)討論TExpertUnit單元NewIntFSource該方法前往C+頭文件的源代碼;它與我們的目的是不相關(guān)的FormCreatedFormCreated是有窗體創(chuàng)建時所調(diào)用的事件方法;由于New Expert導(dǎo)游沒有窗體,因此該事件處置程序是空白的如今我們曾經(jīng)實現(xiàn)了導(dǎo)游,并涵蓋了一切用于定

51、義導(dǎo)游的接口,接下來我們需求討論運用BorlandIDEServices對象添加菜單項。最后我們將實現(xiàn)生成代碼的IOTAFile部分以及IOTARepository接口,并終了本節(jié)。存儲庫接口將把我們創(chuàng)建的導(dǎo)游放置到New Items對話框中,這樣可以使得它與New Component功能相一致。A.2.2 向Delphi的菜單添加菜單項BorlandIDEServices全局變量定義在ToolsAPI.pas單元中。當(dāng)對COM對象運用as操作符時,它與向一個對象查詢能否支持某接口是等效的。例如,假設(shè)BorlandIDEServices實現(xiàn)了IOTAModuleServices接口,Borla

52、ndIDEServices as IOTAModuleServices將前往IOTAModuleServices的實例??梢赃\用BorlandIDEServices對象來訪問一切與ToolsAPI相關(guān)的COM對象,名字形如somenameservices。下面的代碼片斷摘自定義New Expert導(dǎo)游一節(jié)。procedure TNewExpertWizard.AddMenuItem;varNTAServices40 : INTAServices40;ComponentMenuItem : TMenuItem;beginNTAServices40 := BorlandIDEServices As

53、 INTAServices40;if( Not Assigned(NTAServices40) then exit;ComponentMenuItem :=NTAServices40.MainMenu.Items.Find(&Component);if( Not Assigned( ComponentMenuItem) then Exit;FMenuItem := TMenuItem.Create( ComponentMenuItem );tryFMenuItem.Caption := New &Expert.;FMenuItem.OnClick := OnClick;ComponentMen

54、uItem.Insert( 1, FMenuItem );exceptFreeAndNil(FMenuItem);end;end;我們首先需求經(jīng)過BorlandIDEServices獲取對INTAServices40接口的訪問權(quán)限。INTAServices40可以訪問Delphi的主菜單。TMainMenu.Items.Find方法可用于獲取Items集合中Component菜單的援用。加速鍵字符&會被忽略,運用與否都是可以的。兩種情況下find都能正確任務(wù)。假設(shè)找到了Component菜單,將創(chuàng)建一個新的菜單項并將其賦值給FMenuItem字段變量。再初始化菜單項的Caption和OnCli

55、ck特性,然后插入菜單項。當(dāng)以索引位置1插入菜單項時,該菜單項將出如今New Component菜單項之后。最后,假設(shè)發(fā)生異常,將釋放FMenuItem對象。假定其他的開發(fā)者經(jīng)常添加專家如今他們曾經(jīng)創(chuàng)建了New Expert專家,這是能夠的。為確保您的專家總是放在正確的位置上,您可以運用一點搜索邏輯來查找相對于另一菜單的正確位置。下面的修正確保了New Expert總是出如今New Component菜單項之后原來的代碼是ComponentMenuItem.Insert( 1, FMenuItem);。varI : Integer; / added an integer variableNew

56、ComponentMenuItem : TMenuItem;/ original variablesbegin/ original codeNewComponentMenuItem := ComponentMenuItem.Find(New Component);I := ComponentMenuItem.IndexOf( NewComponentMenuItem );ComponentMenuItem.Insert( I + 1, FMenuItem );修正后的版本交換掉了原來對Insert的單獨一行的調(diào)用。ComponentMenuItem.Insert(ComponentMenuIt

57、em.IndexOf(ComponentMenuItem.Find(Install Component.) + 1,FMenuItem );當(dāng)然,假設(shè)運用原來的版本,可以添加一個注釋,而且不需求額外的部分變量I和NewComponentMenuItem。A.2.3 建立代碼生成器在很大程度上,每個導(dǎo)游都包含了一些一樣的根本代碼。新的導(dǎo)游需求一個單元,其中包括單元名、接口和實現(xiàn)部分、援用ToolsAPI單元的uses子句、注冊過程、以及對IOTAWizard和IOTAMenuWizard接口的實現(xiàn)。有個方便的方法可以定義要生成的代碼,即使用源代碼的參數(shù)化的字符串,并將其放置在資源文件中。當(dāng)經(jīng)過I

58、OTAModuleCreator.CreateModule方法創(chuàng)建IOTAFile的后代類的實例時,該實例可讀出資源字符串并對參數(shù)化的空白部分進展填充。TExpertUnit類就是這樣實現(xiàn)的。我們首先看一下資源文件的定義。定義代碼資源文件可以將源代碼定義為常量,但運用資源文件更為可取。定義源代碼的過程可分為四步。第一步,我們從DemosExperts目錄下的例子中找一些源代碼,然后創(chuàng)建名為codegen.txt的文本文件,其中包括參數(shù)化的源代碼。經(jīng)過運用參數(shù),可以用Delphi的format函數(shù)插入實踐的值。第二步:創(chuàng)建資源代碼文件,資源編譯器將運用該文件生成codegen.res,這就是要鏈

59、接到New Expert 導(dǎo)游的資源文件。第三步:運用Brcc32.exe資源編譯器編譯資源文件。第四步:運用$R CODEGEN.RES編譯指令,以確保將codegen.res鏈接到程序中。A.3 CODEGEN.TXT下面列出了參數(shù)化的源代碼。仔細察看,可以留意到該文本與TDummyWizard非常類似。實踐上,它就是從TDummyWizard導(dǎo)游復(fù)制過來的,一些因?qū)в味惖年P(guān)鍵值運用參數(shù)進展了交換。例如,單元名交換為%0:s。因此,假設(shè)對資源字符串運用Format函數(shù),那么運用%0:s之處將交換為Format調(diào)用中的第一個字符串參數(shù),如此等等。unit %0:s;/ %0:s.pas -

60、 Raison d etre/ Copyright (c) 2000. All Rights Reserved./ By Your Company Name Here, Inc. yourwebsite/ Written by Your Name Here. City, State USAinterfaceusesWindows, Messages, SysUtils, Classes, Graphics, Controls, Forms,Dialogs,ToolsAPI;type%1:s = class(TNotifierObject, IOTAWizard, IOTAMenuWizard)

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論