使用Delphi快速开发ActiveX控件
ActiveX 控件也就是一般所说的 OCX 控件,它是 ActiveX 技术的一部分。ActiveX 是微软公司推出的基于组件对象模型 COM 的技术,包括对 Windows 32位应用编程接口(Win32 API)和组件对象模型的一系列扩充和增强,目标是把计算机桌面环境与因特网环境集成起来,同时保护在 Windows 技术中现有的开发投资。微软的 ActiveX 技术根本上就是修改过的 OCX 技术,使它能够跨越 Internet,主要是使用 WWW 来传递控件。
ActiveX 控件可以被集成到很多支持 ActiveX 的应用当中去,或者直接用来扩展应用的功能,这些支持 ActiveX 的应用包括 C++ Builder、Delphi、Visual dBASE、 Visual Basic、Visual C++、Internet Explorer、Netscape Navigator 等。ActiveX 控件还可以使用在因特网上,在网页上使用它来发布信息、处理与用户的交互,但是需要使用支持 ActiveX 的浏览器才能阅读这些网页。目前已经开发出来的 ActiveX 控件越来越多,由于 ActiveX 控件具有很好的特性,我们可以在编程的时候选择使用合适的控件来加快自己的应用开发。可以不夸张地说,ActiveX 控件是 Windows 平台编程必不可少的法宝。
使用 ActiveX 控件是相对比较简单的。但是,开发 ActiveX 控件并不是一件简单的事情,必须要熟悉而不只是了解 ActiveX 技术才能开发出好的 ActiveX 控件。而 COM、OLE 等 ActiveX 技术对于一般的程序员来说,是比较复杂难懂的。所以,ActiveX 控件的开发者一般都是“老鸟”级别的程序员。
但是如果您有了 Inprise 公司的 Borland Delphi,那又另当别论了。Delphi 作为 Windows 平台上最优秀的程序开发工具之一,为 ActiveX 控件的开发提供了强有力的支持,让您轻松地开发 ActiveX 控件。Delphi 的开发者仅仅需要了解一些 ActiveX 控件的简单知识,就可以使用 Delphi 提供的工具来快速开发自己的 ActiveX 控件。本文详细介绍了利用 Delphi 所提供的工具来快速开发 ActiveX 控件的技巧。
一、ActiveX 控件
要开发 ActiveX 控件,我们先得简单了解一下 ActiveX 控件的一些相关知识。在 Delphi 中,一个 ActiveX 控件由如下几个部分组成:VCL(可视化构件库)控件、属性、方法、事件,以及一个或者多个相关的类型库,其中每个部分都有各自的作用。现在对每个部分介绍如下:
1、VCL 构件
在 Delphi 中,一个 ActiveX 控件是由一个或者多个 VCL 构件经过包装以后得到的。所以,要使用 Delphi 来开发 ActiveX 控件,必须先得开发出或者选择要进行包装的 VCL 构件。也正是由于这个原因,我们可以将 Delphi 里大量优秀的 VCL 构件包装成 ActiveX 控件,从而可以在别的不能够直接使用 VCL 构件的开发工具(如 Visual Basic、Visual C++)里也能够使用到这些控件啦!
但是,在 Delphi 里可以用来做 ActiveX 控件的 VCL 构件必须是 TWinControl 的后代。如果想用一个 TGraphiControl 的子类做 ActiveX 控件,在大多数情况下只需要把它的基类变为 TCustomControl 即可。有的 VCL 构件是被注册成非 ActiveX 控件的,例如 EditControl,这些控件也不能做 ActiveX 控件。
2、类型库
类型库包含了控件的类型定义信息,提供了比接口更多的详细信息,是控件向它的宿主程序提供服务信息的一种途径。类型库的目的是为其他应用和编程工具提供关于它包含的构件对象的信息。开发 ActiveX 控件时,Delphi 把类型库信息存入一个.TLB 文件中及一个对应的 Pascal 文件(.TLB 文件的 Pascal 语言版本),编译时类型库将作为资源链入 DLL 或者 EXE 中。
类型库的元素包括:(1)类型库信息:包括类型库的总体信息和特征、当前类型库引用的其他类型库;(2)构件类:代表整个 ActiveX 控件,包含了提供给客户应用的接口;(3)接口属性和方法、事件;(4)枚举类型:一种用作数据类型的相关常量,可以用在类型库的其他地方定义属性和方法。
Delphi 提供了一个类型库编辑器,用于观察或修改类型库,见图1,可以使用它来增加、修改、删除类型库的各种元素。从图1类型库的界面上可以看到,左边是一个树形结构,各种元素的成员作为子节点出现;右边是根据左边所选中的元素类型显示不同的页签,可以对该元素的一些属性进行编辑。
3、属性、方法和事件
VCL 构件的属性、方法和事件自然就变成为 ActiveX 控件的属性、方法和事件。控件的属性,例如颜色、标签等;控件的方法是请求控件执行某些动作;事件则是控件给宿主程序的一个通知,发生了一些事情。
4、属性页
ActiveX 控件所带的属性页可以让控件的使用者查看和修改控件的属性。您可以把几个属性捆绑在一个属性页上,也可以只为一个属性提供一个属性页。
二、快速开发 ActiveX 控件
下面就让我们来使用 Delphi 具体做一个 ActiveX 控件。
假设我们现在面临的问题是,在使用 Visual C++(VC)开发一个应用的时候,需要使用一个 Grid 控件来处理界面的事情,而使用 VC 所提供的 FlexGrid 控件又很麻烦,发现 Delphi 里的 TStringGrid 构件非常合适。但是 TStringGrid 是 Delphi 里的 VCL 构件,又不能直接被 VC 使用,怎么办呢?不用愁,我们只要把 TStringGrid 包装成为 VC 可以使用的 ActiveX 控件就可以解决这个问题了。
Delphi为ActiveX 控件的开发提供了两个向导:
* ActiveX 控件向导可以让你把一个 VCL 构件包装成为一个 ActiveX 控件。下面将会使用到这个向导。
* ActiveForm 向导则可以把几个 VCL 构件包装成为一个 ActiveX 控件或者开发一个完整的 ActiveX 应用。
在 Delphi 当中把 TStringGrid 包装成一个 ActiveX 控件的过程如下:
首先,要启动 ActiveX 控件向导,选择 File 菜单里的 New 命令,在弹出的对话框里选择 ActiveX 页签,然后双击 ActiveX Control 图标即可,如图2所示。向导中的第一个域要求选择一个要进行包装的 VCL 构件,点击选择 TStringGrid。其他几个域取缺省值即可,如果需要包含版本信息等其他信息,也可以选上。点击 OK 按钮,向导将生成一个 Delphi 的 ActiveX 控件开发项目 StringGridXControl1,包括以下几个的文件:
1. 一个 ActiveX 项目文件,包含了启动、初始化一个 ActiveX 控件所需要的代码。通常是不需要修改这个文件的。
2. 一个类型库文件(TLB 扩展名),定义和实现了 ActiveX 控件向外所提供的接口、属性、方法和事件。Delphi 专门为这个文件提供了一个 Pascal 版本的文件,而且自动维护这两个文件的一致性。
3. 一个 ActiveX 实现的文件,使用了 Delphi ActiveX 框架(DAX)定义和实现了这个 ActiveX 控件,具体实现类型库里定义的接口。这个文件是我们经常需要修改的。DAX 是 Delphi 对 ActiveX 控件的 COM 规约的实现方式。
4. 如果选择了包括一个“关于”对话框的话,还有一个对应的对话框实现文件。
Delphi 的 ActiveX 控件向导根据所包装的 VCL 构件的属性、方法和事件生成了 ActiveX 控件相应的属性、方法和事件。但是它没有把 VCL 构件使用非 OLE 类型(如集合、数组等)的属性、方法和事件转换过去。例如,TStringGrid 的 Options 属性是集合类型的,RowHeights 是数组类型的,在控件向导所生成的属性中就没有这些属性。但是有时候偏偏这些属性、方法和事件是很重要的,这时就需要手工添加一些属性、方法和事件!
现在为这个 ActiveX 控件添加一个 BRowSelect 属性,这个属性本来是 TStringGrid 的 Options 属性的子属性,控制 Grid 是否处于行选中状态。在 StringGridXControl1项目里打开 ActiveX 实现文件 StringGridImp1.pas,选择 Edit 菜单里的 Add To Interface 命令(注意:只有打开了实现文件,这个命令才能使用),Delphi 将弹出增加接口对话框,如图3所示。在对话框里的 Interface 项选择 Properties/Methods-IStringGridX,然后在 Declaration 里写入 BRowSelect 属性的声明(如果你选中了对话框里的 Syntax Helper 选项,Delphi 将随时提示你应该输入的内容):
Property BRowSelect:WordBool;
点击 OK 后,这个属性的相关信息将自动加入到控件的实现文件、类型库文件和对应的 Pascal 文件中。因为控件的接口是双向的,所以在 Pascal 文件里使用了读和写两个方法来实现控件的属性。
Delphi 自动在类型库里加入了以下声明:
property BRowSelect: WordBool read Get_BRowSelect write Set_BRowSelect;
这说明了:对于 BRowSelect 这个属性,有一个读方法 Get_BRowSelect,一个写方法 Set_BRowSelect。
Delphi 自动在控件的实现文件里加入了对 BRowSelect 属性的读和写访问方法的声明和实现:
function Get_BRowSelect: WordBool; safecall;
procedure Set_BRowSelect(Value: WordBool); safecall;
这时候这两个方法的实现体是空的,必须得自己填入具体实现的代码:
function TStringGridX.Get_BRowSelect: WordBool;
begin
//以下代码由自己根据需要编写
//获得现在是否处于行选中状态
with FDelphiControl do
Result:=goRowSelect in Options ;
end;
procedure TStringGridX.Set_BRowSelect(Value: WordBool);
begin
//以下代码由自己根据需要编写
//设置行选中状态
with FDelphiControl do
begin
if Value then Options:=Options+[goRowSelect]
else Options:=Options-[goRowSelect];
end;
end;
这时候,使用类型库编辑器来查看类型库,可以看到新增加的 BRowSelect 属性。类似的,我们还可以往 ActiveX 控件里加入更多的属性。
还可以往 ActiveX 控件加入新的方法、事件,加入的方法与加入属性类似。而且加入以后,Delphi 也会自动往相应的文件中加入对应方法和事件的声明和实现,具体的实现体还得自己编写,这里不再多说。
我们可以注意到,Delphi 自动生成了把 VCL 构件包装成 ActiveX 控件所需的包装代码。我们为 ActiveX 控件增加新的属性、方法和事件的时候,只需要在接口方法的实现里把 ActiveX 控件的数据与 VCL 构件的数据联系起来,或者使用 VCL 构件的方法来完成 ActiveX 控件的行为,而基本上不需要关心编写一个 ActiveX 控件的具体细节,例如 COM 规约等。
前面提到,还可以为 ActiveX 控件添加定制的属性页。这里不必专门添加新的属性页,因为大多数支持 ActiveX 的 IDE 编程环境已经缺省为每个 ActiveX 控件提供了一个包含所有属性的属性页了,我们使用这个缺省的属性页即可。
好了,做好了前面这些工作以后,选择 Project 菜单的 Build StringGridXControl1命令即可生成我们所需要的 ActiveX 控件。在项目的目录下,我们可以找到 StringGridXControl1.ocx 这个文件,这个就是我们的 ActiveX 控件啦!把它拷贝到 Windows 9x 的 System 目录或者 Windows NT/2000的 System32目录里面,然后使用命令 regsvr32 StringGridXControl1.ocx 在系统中注册这个 StringGridX 控件,就可以在 VC 编程中使用了。
三、小结
由于有了 Delphi 对开发 ActiveX 控件强有力的支持,我们基本不费什么功夫就很快得到了一个新的 ActiveX 控件。Delphi 让使用它来开发 ActiveX 控件的开发人员把注意力集中到了作为 ActiveX 控件基础的 VCL 构件上,而不必过多地关心 ActiveX 控件的细节,所以让对 ActiveX 技术不是太熟悉的开发者也能够享受到开发 ActiveX 控件的乐趣,而且也大大丰富了在 VC、VB 里开发能够利用的控件。