附录A使用OPENTOOLSAPI的Delphi扩展示例.DOC

上传人:天*** 文档编号:972957 上传时间:2018-11-10 格式:DOC 页数:33 大小:222.50KB
下载 相关 举报
附录A使用OPENTOOLSAPI的Delphi扩展示例.DOC_第1页
第1页 / 共33页
附录A使用OPENTOOLSAPI的Delphi扩展示例.DOC_第2页
第2页 / 共33页
附录A使用OPENTOOLSAPI的Delphi扩展示例.DOC_第3页
第3页 / 共33页
附录A使用OPENTOOLSAPI的Delphi扩展示例.DOC_第4页
第4页 / 共33页
附录A使用OPENTOOLSAPI的Delphi扩展示例.DOC_第5页
第5页 / 共33页
点击查看更多>>
资源描述

1、附录 A 使用 OPENTOOLS API 的 Delphi 扩展示例附录 A 与第 11 章的内容前后承继。阅读第 11 章之后,您已经了解了创建定制组件的大部分知识。附录 A 也很重要,它示范了如何创建组件编辑器以及使用 OpenTools API对 Delphi 自身进行扩展。二者分属不同的主题:一个与组件相关,另一个则是要扩展Delphi。之所以将二者放到附录中,是因为它们没有其他技术那样常用。但要用到二者的时候,它们都是很有用的。定制组件编辑器可以定义设计时对话框,编辑器在 Object Inspector 不够用时,使得用户能够可视化地修改特定于该组件的每个方面。一个很好的例子就是

2、 TChart 组件,由Dave Berneda 开发。另外,在设计时您还可以从组件的上下文菜单中运行该组件所包含的代码。假定您使用 Delphi 已经有一段时间了,而您认为 Delphi 缺乏某些必要的特征。我三年前在一个工程上工作时,就发生了这样的情况。当时正在对 Rational Rose 所定义的系统结构模型进行编码,我们已经厌烦了手工定义类并编写函数体。实在是太烦了。创建一个类来读取类的声明并编写函数体,这看来是个不错的主意。使用 OpenTools API,有时候再借助一下 Ray Lischner 的书Hidden Paths of Delphi 3: Experts, Wiza

3、rds, and the Open Tools API ,我们最终向 Delphi 添加了一个能够调用类生成器的菜单项。结果终于摆脱了这本来可以自动完成的、烦人的任务(可惜的是我们没有一本语法分析方面的好书,我有点离题了) 。这准确地描述了 Inprise 公司在决定向 Delphi 专业版和企业版用户提供 OpenTools API时的想法。当需要 Delphi 具有某些功能时,添加上去就行了。Delphi 现在还具有“Complete class at cursor”的代码生成功能,因此我们可以创建一个尚不存在的专家:可以生成专家的专家。当您阅读本章后,可以了解到如何创建组件编辑器以及怎样

4、使用专家对 Delphi 进行定制。有一个工具可用于开发定制专家,这使得创建专家与创建组件一样容易。A.1 OpenTools API 介绍OpenTools API 原来定义为抽象虚类,即它使用了 Delphi 接口,而我们可以继承它以便向 Delphi 添加扩展。原来的那些单元仍然存在于你安装的 Delphi 的 SourceToolsAPI 子目录下,但在大多数情况下它们已经让位于 ToolsAPI.pas 单元中定义的 COM 接口。注意:ToolsAPI 单元与 Delphi 专业版和企业版一同发布。您也可以对 Delphi标准版进行定制,只是包含相 应接口的单元在 Delphi 标

5、准版中是没有的。如果您对 Delphi 抽象接口比较熟悉,那么比从零开始要好一些。不管怎样,您都应附录 A 使用 OPENTOOLS API 的 Delphi 扩展示例 501该学习 COM 接口,这正是我们在本章中要做的。A.1.1 OpenTools 接口大多数情况下,OpenTools 接口都是位于 SourceToolsAPIToolsAPI.pas 单元中的COM 接口。为提高后向兼容性,该目录下也定义了风格较老的 Delphi 接口。表 A.1 完整地列出了 ToolsAPI 中的所有单元。带有星号的单元包含了风格较老的 Delphi 接口,通常应该避免在较新的代码中使用。警告:很

6、差的是,这些单元在帮助文件中并没有很好的文档。首先要参考单元中的代码;代码中的注释很有帮助,但默 认某些知识;而 经过仔细查找,我们发现几乎完全没有集成化的帮助。这真是个不幸,如果要进行扩展,您必须阅读许多代码并进行实验。表 A.1 Delphi ToolsAPI 单元列表。通过实现 ToolsAPI.pas 单元中定义的 COM 接口,可以访问 Delphi 的大部分功能单元 描述toolsapi.pas 包含了新的 COM 接口,它替换了在其他单元中可以找到的风格较老的接口(本章中将广泛地使用该单元的接口)vcsintf.pas 包含了与版本控制系统进行链接的 COM 接口dsgnintf

7、.pas 包含了特性编辑器、组件编辑器以及注册过程所需的接口(例如,RegisterComponentEditor)editintf.pas* 风格较老的 Delphi 抽象接口,用于访问编辑器缓存,例如单元的文本exptintf.pas* 风格较老的单元,其中包括了用于定义专家的抽象虚类 TIExpert;新代码应使用ToolsAPI 单元中的 COM 接口fileintf.pas* 风格较老的单元,其中包括了用于访问文件系统功能的抽象虚接口istreams.pas* 包含了流、内存流、文件流的接口toolintf.pas* 与 Delphi 菜单和 ToolServices 相关的接口;在

8、新代码中应使用 ToolsAPI 单元中的BorlandIDEServices COM 对象以及 IOTAMenuWizardvirtinft.pas* 包含了 TInterface 的定义,以及 Delphi 对基本的 COM 接口 IUnknown 的实现注意:本章中可能会交替使用向导和专家这两个词。它 们 都是指 Delphi 中的专家。之所以使用两个词,是因为 Inprise 也并未确定使用单个词。注册过程使用向导这个词,而 COM 接口也包含了向 导这个词。在 Delphi 中进行讨论时,对这两个词进行区分是没有意 义的。现在已经无需了解进一步的细节了,我们来创建一个 Delphi

9、专家。A.1.2 创建向导对 Delphi 向导进行扩展的最为直接的途径就是实现 IOTAWizard 和 IOTAMenuWizard接口。这两个接口都定义在 ToolsAPI 单元中,而且您可以看到,它们非常容易实现。注意:首字母缩略词前缀 IOTA 指的是 Interface for OpenTools API(我是这502 Delphi 6 应用开发指南样认为的!),它也可能是指一幕希腊剧,意思是指非常小的数量(因为只有很少量的代码需要实现)。实现 IOTAWizard 和 IOTAMenuWizard最容易实现的向导是非常基本的 IOTAWizard 接口,它使用 IOTAMenuW

10、izard 类来实现。IOTAWizard 接口需要实现四个方法,而 IOTAMenuWizard 则把一个菜单项放置到Help 菜单上。由于刚刚起步,我们将以向导的形式实现一个 Hello World 例子。为使读者不至于失望,将在下一节实现一个较为有用的向导。下面的代码定义 IOTAWizard 和 IOTAMenuWizard。实现基本的向导并显示在 Help菜单上,需要实现 IOTAWizard 接口的四个方法:GetIDString 、GetName、GetState 和Execute。由于 IOTAWizard 继承了 IOTANotifier 接口,您还需要实现 IOTANoti

11、fier 接口。可以使用 TNotifierObject 存根类作为 IOTANotifier 接口的实现。 IOTANotifier 接口引入了AfterSave、BeforeSave、Destroyed 和 Modified 方法,以便对事件进行响应。对这个练习而言,该存根类就足够了。IOTAMenuWizard 继承了 IOTAWizard 接口。在IOTAMenuWizard 类中,惟一需要实现的方法是 GetMenuText,该方法返回在 Help 菜单上显示的文本。IOTAWizard = interface(IOTANotifier)B75C0CE0-EEA6-11D1-9504

12、-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: string;end;这个没有实际功能的向导定义为 TDummyWizard 类,该类是TN

13、otifierObject、IOTAWizard 以及 IOTAMenuWizard 的子类。它实现了上面代码所列出的接口中的五个方法。完整的实现代码如下。unit UDummyWizard;/ UDummyWizard.pas - Demonstrates basic wizard interface/ Copyright (c) 2000. All Rights Reserved./ By Software Conceptions, Inc. http:/ Written by Paul Kimmel. Okemos, MI USAinterfaceusesWindows, ToolsAP

14、I;附录 A 使用 OPENTOOLS API 的 Delphi 扩展示例 503typeTDummyWizard = class(TNotifierObject, IOTAWizard,IOTAMenuWizard)publicfunction GetIDString : String;function GetName : String;function GetState : TWizardState;procedure Execute;function GetMenuText : String;end;procedure Register;implementationusesDialogs

15、;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 TDummyWizar

16、d.GetMenuText: String;beginresult := Dummy Wizard;end;function TDummyWizard.GetName: String;beginresult := Dummy Wizard;end;function TDummyWizard.GetState: TWizardState;504 Delphi 6 应用开发指南beginresult := wsEnabled;end;end.Register 过程以 TDummyWizard 的一个实例为参数调用了 RegisterPackageWizard。您可以像安装组件一样把专家安装到包中,

17、如上例。实际上,进行安装最容易的方法就是使用 Delphi 中的 Component | Install Component 菜单项。当用户单击添加的菜单项时,即可调用这个非常基本的向导。当单击菜单项时,将调用向导实现的 Execute 方法来响应。TDummyWizard 在一个 TMessageDlg 对话框中显示本书的标题。当然,如果您确定的话,可以在 Execute 方法中加入几乎任何级别的复杂行为。GetIDString 方法返回向导的字符串标识符。按照惯例,该 ID 的前缀是您公司的名字,这里使用了 Software Concepts, Inc 公司的注册商标 SoftConcep

18、ts,并将其通过圆点连接到向导的名字。GetMenuText 的实现代码中包含了显示在帮助菜单上的菜单项文本。当每次单击Delphi 的 Help 菜单上相应菜单项时,都会调用该方法。GetName 方法返回向导的名字,而 GetState 方法则返回 TWizardState 类型值。该类型定义如下:TWizardState = set of wsEnabled, wsChecked;wsEnable 表示该向导是否是活动的,而 wsChecked 值则在菜单项上放置一个检查标记。从代码可以看到,基本的 Help 菜单向导所需的代码非常少。当安装向导后,Delphi的帮助菜单上出现了一个新的

19、菜单项 Dummy Wizard。当用户单击向导时,将调用Execute 方法,从而在 TMessageDlg 对话框上显示文本“Building Delphi 6 Applications”。关于相应的菜单项和单击后的反应,可以参见图 A.1 和 A.2。图 A.1 Dummy Wizard 添加到 Delphi 的 Help 菜单附录 A 使用 OPENTOOLS API 的 Delphi 扩展示例 505图 A.2 当单击 Dummy Wizard 菜单项时,将显示 TMessageDlg对话框,其代码可以参见 Execute 方法注册向导把向导添加到包,并像组件一样对其进行安装,即可扩

20、展 Delphi。当把包编译为 BPL库之后,将调用上一节的 Register 过程来进行安装。如上一小节的代码所示,RegisterPackageWizard 需要向导的一个实例作为参数。RegisterPackageWizard 定义在ToolsAPI.pas 单元中,其参数为 IOTAWizard 类型的常量引用,该过程声明如下:procedure RegisterPackageWizard(const Wizard: IOTAWizard);要安装向导,可以按照下列步骤进行。1. 在 Delphi 中,单击 Component | Install Component 菜单项。2. 在

21、Install Component 对话框中,如果单元尚未显示在 Unit file name 域中,则单击Browse 按钮找到相应的单元。3. 如果要在当前包中安装专家,单击 OK。否则单击 Into new package 属性页(见图A.3) ,并给出包的名字及描述。图 A.3 图中为 Install Component 向导,用于将向导安装到包。所需步骤与安装组件时相同4. 当单击 OK 后,给出的包将在包编辑器中打开(见图 A.4) 。单击 Compile 按钮(见图 A.4) 。5. 对包进行编译之后,Install 已经可用,单击该按钮。要记住,包在本质上是动态链接库,也是一种

22、应用程序。因此,可以而且应该像其他程序一样对选项进行设置。要加入路径和版本消息,并记得设置对所处的开发阶段可用的编译器选项。可以参考前面的第 18 章,在测试时使用运行时错误和调试选项,而在测试结束后、应用程序打包之前去掉这些选项。506 Delphi 6 应用开发指南图 A.4 包编辑器用于编译并安装包A.2 创建定制向导像 New Component Wizard 这样有用的向导,可以减少编写代码的数量,使得不必手工编写一些可以自动完成的代码;而且有助于开发者在越过障碍之后发现 Delphi 的一些新的功能。为保持向导的这种功能,本节给出了一个 New Expert 专家;正如同 New

23、Component 对话框跳过了开始组件单元的步骤一样,New Expert 的作用也是类似的。A.2.1 定义 New Expert WizardNew Expert 的功能是,它可以生成一些与本章开头的 Dummy Wizard 类似的专家。而New Expert 本身将安装在 Component 菜单上 New Component 菜单项之后。要建立该向导并将其安装到 Component 菜单上,我们需要实现 IOTACreator 和 IOTAModuleCreate,而且还需要查询 BorlandIDEServices 以获得 INTAServices40。INTAServices4

24、0 对象定义了向特定的 Delphi 菜单添加菜单项的行为。向导的类是 TNewExpertWizard。当单击 Component | New Expert 菜单项(见图 A.5)时,它生成一个与 TDummyWizard 几乎相同的类。将特定的行为添加到生成的 Execute 方法,然后就可以了。完整的代码列表如下,对相关部分的描述分为小节,以便使您能够清楚地了解其作用。图 A.5 将 New Expert 向导添加到 INTAServices40 对象之后附录 A 使用 OPENTOOLS API 的 Delphi 扩展示例 507unit UNewExpertWizard;/ UNew

25、ExpertWizard.pas - An example of a wizard that generatesthe code for a wizard/ Copyright (c) 2000. All Rights Reserved./ By Software Conceptions, Inc. http:/ Written by Paul Kimmel. Okemos, MI USAinterfaceusesWindows, Controls, ToolsAPI, Forms, Menus, Classes, SysUtils;typeTNewExpertWizard = class(T

26、NotifierObject, IOTAWizard,IOTACreator,IOTAModuleCreator)privateFNewClassName : string;FMenuText : string;FExpertIDString : string;FExpertName : string;FUnitName : String;FWizardState : TWizardState;FMenuItem : TMenuItem;procedure AddMenuItem;procedure OnClick( Sender : TObject );procedure GenerateC

27、ode;publicconstructor Create; virtual;destructor Destroy; override; IOTAWizard function GetIDString : String;function GetName : String;function GetState : TWizardState;procedure Execute; IOTACreator function GetCreatorType : string;function GetExisting : Boolean;function GetFileSystem : string;funct

28、ion GetOwner : IOTAModule;function GetUnnamed : Boolean; IOTAModuleCreator function GetAncestorName : string;function GetImplFileName : string;function GetIntfFileName : string;function GetFormName : string;508 Delphi 6 应用开发指南function GetMainForm : Boolean;function GetShowForm : Boolean;function Get

29、ShowSource : Boolean;function NewFormFile( const FormIdent, AncestorIdent : string) : IOTAFile;function NewImplSource( const ModuleIdent, FormIdent,AncestorIdent : string ) : IOTAFile;function NewIntfSource( const ModuleIDent, FormIdent,AncestorIdent : string ) : IOTAFile;procedure FormCreated( cons

30、t FormEditor : IOTAFormEditor );end;procedure Register;implementationuses UFormMain, Dialogs, UExpertUnit;$R *.RESprocedure Register;beginRegisterPackageWizard(TNewExpertWizard.Create);end; TNewExpertWizard constructor TNewExpertWizard.Create;begininherited;AddMenuItem;end;destructor TNewExpertWizar

31、d.Destroy;beginif( Assigned(FMenuItem) thenFMenuItem.Free;inherited;end;procedure TNewExpertWizard.OnClick( Sender : TObject );beginExecute;end;procedure TNewExpertWizard.AddMenuItem;varNTAServices40 : INTAServices40;ComponentMenuItem : TMenuItem;附录 A 使用 OPENTOOLS API 的 Delphi 扩展示例 509beginNTAServic

32、es40 := BorlandIDEServices As INTAServices40;if( Not Assigned(NTAServices40) then exit;ComponentMenuItem :=NTAServices40.MainMenu.Items.Find(if( Not Assigned( ComponentMenuItem) then Exit;FMenuItem := TMenuItem.Create( ComponentMenuItem );tryFMenuItem.Caption := New FMenuItem.OnClick := OnClick;Comp

33、onentMenuItem.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 := 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;

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 重点行业资料库 > 1

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。