Delphi Open Tools Api 主要接口概述
OTA接口
Creator 是定义和实现了IOTACreator接口或一个它的派生接口的类,Delphi 调用Creator 对象来生成新的文件和项目。
IOTAFile 接口
要为一个新文件提供源代码,必须定义一个实现了IOTAFile接口的类。
IOTACreator 接口
全部Creator基类,如果你想使用一个缺省的Creator,比如一个缺省的窗体或项目,那么返回一个合适的字符串作为CreatorType参数,要想创建一个定制的对象,只要返回一个空的字符串就可以了。
IOTAModuleCreator 接口
主要被用来创建一个单元、窗体或其他文件。可以创建一个缺省的单元、窗体或文本文件,并通过返回CreatorType 为sUnit、sForm、sText或nil来创建对应的源码文件、窗体文件等。不像老版本的模块创建器,新的API不返回空的字符串作为缺省的文件名,我们必须返回完整的模块信息,窗体返回一个IOTAFile接口对应于一个DFM文件,其中要包括DFM文件签名。
IOTAProjectCreator 接口
用来创建一个新的包、库或应用程序。可以通过返回CreatorType为sPackage、sLibrary或sApplication来做到,或者直接返回nil来创建新的项目源码。
写一个用户定制的窗体类的关键是定义Contructor部分。要考虑几种不同的情况,第一是否需要加载一个DFM,或者只需要从预定义的类中继承。如果需要加载一个DFM,那么只需要调用继承的Constructor,Constructor 可以做这部分事情。如果不需要加载DFM,那么需要重载Create方法来调用继承的CreateNew,而不是直接调用继承的Create方法。我们还需要调用InitInheritedComponent方法来为预定义类或衍生类加载DFM。下面就是一个如何定义Constructor函数来加载一个用户定制的窗体类。代码如下:
constructor TMyForm.Create(Owner: TComponent);
begin
inherited CreateNew(Component);
// 其他初始化工作
GlobalNameSpace.BeginWriting;
try
if (ClassType <> TMyForm) and
not (csDesigning in ComponentState) then
begin
if not InitInheritedComponent(Self, TMyForm) then
raise Exception.Create('错误:无法初始化MyForm');
if OldCreateOrder and Assigned(OnCreate) then
OnCreate(Self);
end;
finally
GlobalNameSpace.EndWriting;
end;
end;
我们可以定义一个窗体类并公开某些属性到Object Inspecotr(属性编辑器),这就称为一个定制的窗体。定制窗体同编写组件有点不同,定制窗体是一个4步的过程:
写一个继承于TForm、TCustomForm、TdataModule、或者任何从TwinControl继承的窗口类。这部分的关键在于Constructor部分。
写一个定制的模块类来添加菜单项到Delphi的窗体编辑器中,这部分不是一定要实现的。我们也可以直接用TCustomModule (在DsgnIntf 单元中)。同时定制的模块可以控制允许何种控件可以被放到窗体上。
写一个窗体向导,用来在设计时创建一个定制的窗体的实例。注意要设定父类名作为设定的窗体类名,同时在单元的源码文件中正确引用单元名。
把定制的窗体类放到一个运行时包中,把窗体向导和定制模块放到设计时包中。调用RegisterCustomModule函数来注册定制窗体类,并在Delphi中安装设计时包。
调试器接口是一个新引入的接口。但它在Delphi 4下根本无法正常工作,特别是调试器的Notifier(消息通知器)接口不能工作,没有了这个接口,其他剩余的调试器接口显得没什么用处了。不过幸运的是,Borland在Delphi 5中已经正确地实现了它。
编辑器接口同老版本的API工作方式非常接近。
1. IOTAEditor
编辑器的基本接口,这个接口定义了编辑器的基本功能,比如文件名、对模块接口的引用参考等。
2. IOTASourceEditor
这个是同源码文件相关联的编辑器接口。Edit readers、Edit writers以及编辑视图功能和用法同老式的API基本相同。
3. IOTAProjectResource
同项目中的资源文件相关联的接口,除了是使用COM接口的形式外,同老式API差不多。
4. IOTAFormEditor
与窗体编辑器相关的接口,通过这个接口可以获得窗体上每个控件的IOTAComponent 接口。
5. IOTAComponent
控件接口,通过它可以修改任意控件的属性。
6. INTAComponent
把IOTAComponent接口映射为INTAComponent的接口,通过INTAComponent可以直接同控件的实例交互。一旦得到了控件实例的引用参考,就可以做差不多所有的事情。
小知识:需要指出的是老式的API同新的基于接口的新API的工作方式非常接近,所以看以前的例子还是很有帮助的,比如Micro Cantu的那本《Delphi高级编程指南》和李维的那本《Delphi 3从入门到精通》就是两本很好的书。
消息接口也是个新接口,在Delphi 3中并没有类似的接口。使用消息服务可以在Delphi的消息视图中显示用户定制的信息。可以以字符串的形式显示信息,也可以通过完全控制消息的显示来实现彩色的不同字体的定制显示。还可以在源码文件的特定地点显示信息,当用户双击信息时,Delphi会在源码编辑器中打开文件并把光标定位在特定的行和列。
IOTAMessageServices接口方法说明
1. AddCustomMessage
用来显示一条定制的消息,必须定义一个类来实现IOTACustomMessage接口,必要的话还需要实现IOTACustomDrawMessage接口。
2. AddTitleMessage
用来显示一条简单的粗体文本信息。
3. AddToolMessage
用来显示同源码文件相关联的文本信息,Delphi按如下形式显示信息:
[前缀] 文件(行号):信息
4. ClearAllMessages
这个方法清除全部以前添加的信息。
5. ClearCompilerMessages
清除编译信息。
6. ClearSearchMessages
清除查找信息。
7. ClearToolMessages
清除我们定制的信息,但不清除通过AddToolMessage方法添加的信息。当向导被卸载时必须调用ClearToolMessages或者ClearAllMessages方法来清除先前添加的信息,否则 Delphi的消息视图会显示一些麻点。
8. IOTACustomMessage
实现这个接口可以定制消息,仔细查看ToolsAPI.pas文件就可以搞清楚它的工作方式,不过要注意的是,Delphi的IDE并不会像对Tools Message那样对它格式化文件名和行号。所以,必须自己添加前缀、文件名和行号到LineText。
9. IOTACustomDrawMessage
通过这个接口向导可以对消息的显示进行完全控制,比如修改字体大小、颜色等。下面介绍IOTACustomDrawMessage接口的方法。
Draw
当IDE需要画消息时会调用这个方法,如果比较费时的话,可以先用位图来缓冲显示,最后画到Canvas(画布)上去,以免闪烁。关于Wrap好像没什么用,Rect参数定义了当前消息视图的宽度和每行文本的高度。
CalcRect
Delphi会不定时地调用这个方法,然后忽略它返回的矩形区域。MaxWidth代表屏幕宽度。
Notifier(消息通知器)通知向导IDE中发生的令人感兴趣的事件。通过创建继承了特定的Notifier接口的类,并注册类的实例,就可以使用Notifier了。所有的Notifier必须实现IOTANotifier接口,虽然IDE根本不调用它的方法。
IOTAEditorNotifier
完全没用,IDE根本不调用它的方法,必须使用老式的模块Notifier来代替。
IOTAFormNotifier
在Delphi4中FormActivated和FormSaving 方法不被IDE调用,在Delphi5中已经有效了。只有当用户添加、删除和改名控件时,Delphi才会调用ComponentRenamed方法。
IOTABreakpointNotifier
断点Notifier,理论上当用户修改一个断点,Delphi释放一个老的断点或创建一个新断点时会被调用。但是因为调试器Notifier根本无法正常工作,所以向导也无法获得信息。只能获得断点被删除时的销毁信息通知。
IOTAThreadNotifier
每一个进程至少拥有一个线程,线程Notifier不会报告线程中的错误或异常,但它能够报告程序在断点处挂起的信息(好像没什么用)。注意IOTAThreadNotifier错误的拼写了 evaluate。应该实现的是EvaluteComplete方法。
IOTAProcessModNotifier
这个接口唯一被调用的是Modified方法,当Delphi已经加载或卸载模块的符号时会被调用。一个典型的进程会加载很多的模块 (DLL),但只有其中的几个包含符号。
IOTAProcessNotifier
这个接口通知向导IDE创建或销毁一个线程,及加载或卸载一个模块的消息。
IOTADebuggerNotifier
调试器接口。
IOTAIDENotifier
这个接口确实是有效的,但要注意的是当Code Insight解析源码文件时,Delphi会调用编译事件,这意味着这个事件在你编辑文件时就会被调用很多次。
新的OTA还提供了检查和修改项目选项和环境选项的功能。每个选项是通过名字来定位的,同时每个选项都有一个类型和值。类型通常是整数、枚举或字符串。每个项目都有同样的选项列表,包括C++ 项目、包、应用程序和库等。
获得选项编辑接口很简单,先调用CreateModule方法,然后从IOTAModul接口中获得IOTAProject接口,在通过调用ProjectOptions方法可以获得选项编辑接口 IOTAProjectOptions。要想获得环境选项编辑接口,使用IOTAServices,然后调用GetEnvironmentOptions方法即可。项目和环境接口的使用方法是类似的。
IOTAOptions
调用选项接口的GetOptionNames方法可以获得一系列的选项名。每个选项名都有一个TtypeKind类型值,使用选项名索引的Values属性可以获得和设定选项值,它是一个Variant类型,所以不用考虑类型匹配,只要指定正确的值和类型就可以了,比如字符串或整数。如果设定一个错误的类型,Delphi会产生一个异常,如果指定了一个无效的选项,Delphi会忽略它而不会报警。
下面是一个例子,如果你想写一个项目向导来创建一个包,同时这个包只能是设计时的,可以像下面这样来实现:
procedure TMyPackageWizard.Execute;
var
Project: IOTAProject;
Options: IOTAProjectOptions;
begin
with BorlandIDEServices as IOTAModuleServices do
Project := CreateModule(TMyCreator.Create)
as IOTAProject;
Options := Project.ProjectOptions;
Options.Values['DesigntimeOnly'] := True;
Options.Values['RuntimeOnly'] := False;
end;
最核心的接口是声明在ToolsAPI单元中的BorlandIDEServices,这个对象等效于老式API中的ToolServices对象。新旧API的区别在于老API有一个单独的对象ToolServices,这个对象有大量的方法。新的API通过一个单一对象实现了很多不同的COM接口,每一个接口定义了特定的功能方法。
可以通过BorlandIDEServices映射对应的接口来获得服务。
比如:(BorlandIDEServices as IOTAPackageServices).PackageCount
下面是服务的列表及其描述:
IOTAActionServices
执行文件操作,比如打开、关闭、保存文件等功能,Delphi 5中的\Demos\ToolsAPI\目录下有很好的例子。
IOTAMessageServices
在Delphi的消息视图中显示简单信息或提供自绘画的消息显示功能。
IOTAPackageServices
获得被加载的包和已安装的控件的列表。
IOTADebuggerServices
Delphi调试器的接口,当前还没有完全实现。
IOTAModuleServices
获得当前打开的文件的模块接口。提供安装文件系统、注册模块Notifier、创建新文件等功能。而且通过模块接口可以获得编辑器接口、项目选项接口等。
IOTAWizardServices
提供注册和注销向导的功能。如果想实现一个DLL型的新OTA向导必须使用它来注册。
IOTAServices
提供多项服务,比如注册IDE Notifier,获得产品名称(Delphi 或C++ Builder)等。还可以获得环境选项编辑接口。
INTAServices
提供多项服务,如添加菜单项等,替代了老API的TIMenuItemIntf的功能。