分享

Delphi笔记-ActiveX控件

 quasiceo 2012-12-08

Delphi笔记-ActiveX控件  

2007-12-08 21:02:58|  分类: Delphi学习笔记 |字号 订阅

在发布使用ActiveX控件的应用程序时,应该附带使用到的ActiveX控件的OCX文件或DLL文件,并且在运行应用程序之前,必须先在系统注册表中注册ActiveX控件。注意:有些ActiveX控件会使用到其它的DLL文件,这时也要提供这些文件。可以通过RegSvr32.exe来注册ActiveX控件,这个程序在Windows系统中可以找到。也可以使用Delphi开发环境目录中的bin目录中的TRegSvr.exe来注册。另一种方法是将ActiveX控件的注册代码集成到应用程序中,Delphi已提供了TRegSvr.exe的源代码,并演示了如何注册ActiveX控件。

ActiveX控件向导(ActiveX Control Wizard)
  这个向导允许把一个VCL控件转换成一个ActiveX控件,能被转换成ActiveX控件的VCL控件要满足下面三个准则:
. VCL控件必须在当前安装的设计包中(它必须在组件面板中)。
. VCL控件必须是TWinControl的派生类,当前非窗口控件不能转换为ActiveX控件。
. VCL控件必须是还没有被RegisterNonActiveX()过程列出来的
许多标准的VCL控件无法转换为ActiveX控件,是因为其中有些转换成ActiveX控件没有意义,或者是因为转
换需要大量的工作,超出了向导能提供的功能。
注意:虽然ActiveX向导不能把一个非窗口的控件转换成ActiveX控件,但能通过Delphi ActiveX(DAX)框架
来手工编写这样的控件。

ActiveX控件的选项(ActiveX Control Options):
. Make Control Licensed,选中这个选项,一个许可证文件(LIC)就会产生,这是为了使其他开发者在不同
的开发环境能用这个Activex控件。
  为了能使用这个控件除了ActiveX控件的ocx文件,还需要许可证文件。DAX需要把一个许可文件和ActiveX
控件的OCX文件一起发布到用户的机器上。许可字符串是ActiveX控件类工厂构造器的一个参数。若在向导中
选中了Make Control Licensed,这个选项将生成一个GUID字符串,并把这个字符串插到类工厂构造器的调
用中和LIC文件中。如果这个ActiveX控件要用在开发工具中,DAX就会把类工厂的许可字符串与LIC文件中许
可字符串进行比较,如果匹配的话,才能创建这个控件的实例。当编译使用这个ActiveX控件的应用程序时,
许可字符串会嵌入到应用程序中,但运行这个应用程序不再需要LIC文件。
. Include Version Information,选中这个选项,一个VersionInfo资源将连到OCX文件中,在它的字符串
文件信息中有一个称为OleSelfRegister的变量,它的值为1,这个变量是为了兼容老的ActiveX控件的宿主,
例如Visual Basic 4.0,在Project Options对话框的VersionInfo页中能编辑这个变量。
. Include About Box,选中这个选项是为了把“About”对话框连到ActiveX控件中,在ActiveX容器应用程
序中在ActiveX控件上单击右键出现的菜单中能激活这个对话框,这个About对话框是一个普通的Delphi窗体。

下面简要描述ActiveX控件向导把一个VCL控件转换成ActiveX控件要经历的步骤:
1) 向导决定是哪个单元包含了选中的VCL控件,然后经编译器处理,由编译器生成与VCL控件的属性、方法和事件相对应的特殊符号信息。
2) 为这个项目创建一个类型库,其中包括一个具有属性和方法的接口、一个事件调度接口和一个表示ActiveX控件的控件类。
3) 向导遍历VCL控件的所有符号信息,把其中的属性和方法加到接口中,把事件加到调度接口中。
注意:只有那些属性、方法的参数和返回值、事件的类型与自动化兼容的才能被加到类型库中,与自动化兼
容的数据类型有:Byte、SamllInt、Integer、Single、Double、Currency、TDataTime、WideString、
WordBool、PSafeArray、TDecimal、OleVariant、IUnknown和IDispatch。不过,这个规则也有例外,如果参
数的类型是TStrings、TPicture和TFont,也是允许的。对于这些类型,向导用特殊的适配器对象将其封装为
兼容的类型。这三个类型对应的自动化接口分别为:IStrings、IPicture和IFont。
4) 一旦所有的属性、方法和事件加到类型库中后,类型库编辑器就产生一个包含类型库内容的Object Pascal译本。
5) 向导生成ActiveX控件的实现文件,这个文件中有一个TActiveXControl对象,它实现了在类型库中描述的接口,并自动实现原来在VCL中的属性、方法和事件。
注意:在类型库的单元文件中有一个类似于TMemoX的类这是从TOleControl继承下来的,这样就可以把这个
ActiveX控件加到组件面板中,只要把XXX_TLB单元加到设计期包中。

Delphi的ActiveX框架(简称DAX)在单元AxCtrls中。一个ActiveX控件可以看成是一个自动化对象,因为它需要实现IDispatch接口及其他接口。TActiveXControl是TAutoObject的派生类,它能实现一个ActiveX控件所需的接口。DAX框架是一个双向的框架,在ActiveX中的TActiveXControl部分能和在VCL控件中的TWinControl进行通信。就像所有的COM对象一样,ActiveX控件由类工厂创建, DAX中的TActiveXControlFactory就是TActiveXControl对象的类工厂。而类工厂的实例是在控件实现单元的initialization部分创建的,这个类的构造器声明如下:
constructor TAcitveXControlFactory.Create(ComServer:TComServerObject;ActiveXControlClass:
  TActiveXControlClass;WinControlClass:TWinControlClass;const ClassID:TGUID;ToolboxBitmapID:
  Integer;const LicStr:String;MiscStatus:Integer;  ThreadingModel:TThreadingModel=tmSingle);
ComServer用于指定一个TComServer的实例,它通常是ComServ单元中的全局变量ComServer。
ActiveXControlClass用于指定TActiveXControl的派生类的名字,它定义在实现文件中。
WinControlClass指定了VCL TWinControl派生类的名字,ActiveX控件就是从它转换来的。
ClassID指定了ActiveX控件的类标识符(CLSID),它被列在类型库编辑器中。
ToolboxBitmapID指定了一个位图的资源标识符,这个位图作为ActiveX控件在组件面板中的图标。
LicStr用于指定AtiveX控件的许可字符串,如果这个字符串设为空,表示不许可。
MiscStatus用于指定Activex控件的OLEMISC_XXX状态标志。这些标志决定了一个ActiveX控件怎样在窗口画
出,是否能包含其他控件。关于这些标志的含义,请查阅Microsoft Develpoer’s Network中OLEMISC主题。
ThreadingModel用于指定ActiveX控件的线程模式,特别要注意,这个参数仅用来对ActiveX控件指定一种线
程模式,但不能保证在这个线程模式下ActiveX控件就能安全工作,它只是决定了ActiveX控件是怎样注册的。
线程安全需要由程序员编程实现。

OLEMISC_XXX参数的其中一个值为OLEMISC_SIMPLEFRAME ,当VCL控件的ControlStyle属性中有
csAcceptsControls时,这个值被自动加到ActiveX控件中。这意味着,ActiveX控件就能成为其他ActiveX控
件的容器。在TActiveXControl类中有能使控件正确工作的消息处理结构,以处理子控件的消息。通常这个
值通过向导自动设定。如果不希望这样,就应当在调用类工厂构造器的代码中把这个标志手工地去掉。

某些ActiveX控件要有消息才能正确工作。因此,DAX将创建一个反射器窗口,它的任务是接收消息,并把它
们传递给VCL控件。凡是需要反射器窗口的VCL控件在ControlStryle属性中有csReflector标志。如果有一个
要处理通知消息的自定义的TWinControl控件,必须保证在控件构造器的ControlStyle集合中有这个标志值。

VCL提供一种简单的方法来判断一个控件当前是处在设计期还是在运行期,只要检查在ComponentState属性中
是否有csDesigning标志。虽然对ActiveX控件也能进行类似的判断,但它实现起来不那么简单,它需要获得
容器的IAmbientDispatch调度接口的指针并检查这个调度接口的UserMode属性。可以用下列代码来完成:
function IsControlRunning(Control:IUnknown):Boolean;
var
  OleObj:IOleObject;
  Site:IOleClientSite;
begin
  Result:=true;
  //得到控件的IOleObject指针,通过它得到容器的IOleClientSite,再得到IAmbientDispatch
  if (Control.QueryInterface(IOleObject,OleObj)=S_OK) and
     (OleObj.GetClientSite(Site)=S_OK) and (Site<>nil) then
    Result:=(Site as IAmbientDispatch).UserMode;
end;

LIC文件并不是唯一的许可策略。例如,有些开发者认为附加一个文件很麻烦,他们更愿意在注册表中注册
一个许可字符串。DAX用一种简单的方法来实现了这个目标,在TActiveXControlFactory中有一个方法叫
HasMachineLicense。默认的情况下,这个方法在LIC文件中查找许可字符串,但可以让这个方法在注册表中
查找许可字符串。例如,下面代码显示了一个TActiveXControlFactory的派生类如何在注册表中查找许可字
符串。
type
  TRegLicActiveXControlFactory=class(TActiveXControlFactory)
  protected
    function HasMachineLicense:Boolean;override;
  end;

function TRegLicActiveXControlFactory.HasMachineLicense:Boolean;
var Reg:TRegistry;
begin
  Result:=true;
  if not SupportsLicensing then Exit;
  Reg:=TRegistry.Create;
  try
    Reg.RootKey:=HKEY_CLASSES_ROOT;
    Result:=Reg.OpenKey('\Licenses\'+LicString,False);
  finally
    Reg.Free;
  end;
end;
把许可字符串加到注册表文件的REG文件:
REGEDIT4

[HKEY_CLASSES_ROOT\Licenses\{C06EFEA0-06B2-11D1-A9BF-B18A9F703311}]
@="Licensing info for DDG demo ActiveX control"

属性页提供了通过一个对话框修改ActiveX控件属性的方法。在控件容器中,通过在控件上单击右键并在产
生的菜单中选择命令,就能打开一个控件的属性页。
1. 标准的属性页
  DAX为类型IString、IPicture、TColor和IFont提供了标准的属性页。这些属性页的CLSID定义在AxCtrls
单元中。它们声明如下:
const
  Class_DColorPropPage:TGUID='{5CFF5D59-5946-11D0-BDEF-00A024D1875C}';
  Class_DFontPropPage:TGUID='{5CFF5D5B-5946-11D0-BDEF-00A024D1875C}';
  Class_DPicturePropPage:TGUID='{5CFF5D5A-5946-11D0-BDEF-00A024D1875C}';
  Class_DStringPropPage:TGUID='{F42D677E-754B-11D0-BDFB-00A024D1875C}';
在ActiveX控件中使用上述任何一种属性页时,仅需要把它们的CLSID传递到控件DefinePropertyPages()方
法中的DefinePropertyPage参数即可。示例如下:
procedure TMemoX.DefinePropertyPages(DefinePropertyPage:TDefinePropertyPage);
begin
  DefinePropertyPage(Class_DColorPropPage);
  DefinePropertyPage(Class_DFontPropPage);
  DefinePropertyPage(Class_DStringPropPage);
end;
2、自定义的属性页
   示例:先新建一个ActiveX Control,再新建一个Property Page,在Property Page上设计界面与代码,
将属性页的默认类型标志符Class_PropertyPage1改名为其它喜欢的名字,再在ActiveX控件类的
DefinePropertyPages方法中加入以下代码:
procedure TMemoX.DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage);
begin
  DefinePropertyPage(Class_DStringPropPage);//这个是标准的属性页的CLSID
  DefinePropertyPage(Class_PropertyPage1);
end;
  实现自定义属性页时,用OleObject来与属性页中的ActiveX控件交互。OleObject是变体,它能引用
ActiveX控件的IDispatch接口,属性页的UpdatePropertyPage()方法和UpdateObject()方法由向导产生。
在属性页激活时UpdatePropertyPage()被调用,这样就有机会把ActiveX控件的属性值显示在属性页上。当
用户单击属性页上的OK键或Apply按钮时会调用UpdateObject()方法。这样就有机会以用户所做的修改来更
新Activex控件的属性。属性页上的按钮被按下时应该调用属性页的Modified()方法,它能使Apply按钮有效,
并临时更新ActiveX控件的属性。

ActiveForm:
从功能上讲,ActiveForm非常像ActiveX控件,
ActiveForm在类型库中的接口是“平面”的,而不是像VCL那样是嵌套的。这表示如果一个ActiveForm上有
几个按钮,则无法用类似于ActiveForm.Button.ButtonProperty的方式来访问ActiveForm上的按钮(访问者
是使用该ActiveForm的客户端程序)。要解决这个问题的最简单的方法是把按钮的属性转换为ActiveForm的
属性。只要采取两个步骤。这里假设要转换按钮的Caption属性:
1) 在实现文件的ActiveForm声明中增加一个公开的被称为ButtonCaption的新属性,它有读、写方法,来读
写按钮的Caption属性。
2) 在类型库中中的ActiveForm接口中加入一个名字为ButtonCaption的新属性。Delphi将为这个属性自动生
成读、写方法的程序框架。必须自己编写代码通过对ActiveForm的ButtonCaption属性的读、写来完善程序。
ActiveForm最理想的用途是在WWW上作为传送小型程序的载体。小小的ActiveX框架同样能增加Web页的功能和
外观。因为ActiveX控件能运行在Web浏览器上,如果它能调用Web浏览器的函数和接口,这非常有意义。Web
浏览器的函数和接口大部分在UrlMon单元中,其中最简单的是Hlinkxxx()函数,它能让浏览器跳转到不同的
地方。例如,HlinkGoForward()和HlinkGoBack()函数可以使浏览器在历史记录中前后跳转。
HlinkNavigateString()函数能使浏览器跳转到一个特定URL,这些函数在UrlMon单元中是这样声明的:
function HlinkGoForward(pUnk:IUnknown):HResult;stdcall;
function HlinkGoBack(pUnk:IUnknown):HResult;stdcall;
function HlinkNavigateString(pUnk:IUnknown;szTarget:PWideChar):HResult;stdcall;
  pUnk参数是ActiveX控件的IUnknown接口,对于ActiveX控件来说,可以传递Control as IUnknown给这个参
数;对于ActiveForm来说,可以传递IUnknown(VclComObject)给这个参数。HlinkNavigateString()的
szTarget参数用于指定一个URL。调用URLDownloadToFile()函数可以从服务器下载一个文件,这个函数在
UrlMon中是这样声明的:
function URLDownloadToFile(p1:IUnknown;p2:PChar;p3:PChar;p4:DWORD;p5:
  IBindStatusCallback):HResult;stdcall;
  p1代表ActiveX控件的IUnknown接口,它类似于HlinkXXX()函数的pUnk参数。p2参数是要下载的文件的URL。
p3参数用于指定该文件下载到本地的路径和名称。p4参数必须设为0。p5参数用于指定一个可选的
IBindStatusCallback接口的指针。这个接口用于获取文件在下载时的附加信息。
  Delphi的IDE可以很方便地把ActiveX控件在Web站点上发布,要能实现这个功能,必须在编辑ActiveX控件
项目时选择菜单项Project|Web Deployment Options。该对话框中的各个选项解释如下:
1. Project页
  Target Dir框用于指定ActiveX控件要发布的目标路径。这里假设能把一个驱动器映射到Web服务器上—
Target Dir框中必须输入一个常规的或UNC路径名,其中不应当有文件名。
  Target URL框用于输入Target Dir框所指定的路径的URL。一个合法的URL必须以http://、file://、
ftp://等为前缀。这个框中也不要输入文件名。
  HTML Dir 框用于指定一个路径,用于存试生成的HTML文档。它通常跟Target Dir框中指定的路径相同。
  use CAB file compression,如果选中了这个选项, OCX文件将以Microsoft Cabinet(CAB)格式压缩。在
低带宽的网络上,建议选中这个选项。
  Include file version number,这个选项决定生成的HTML文件或INF文件中是否要有版本号。推荐选中这
个选项,它能避免用户下载已经下载过的控件。
  Autoincrement release number,如果选中这个选项,版本信息中的发布号将自动增大。
  Code sign project,如果有数字签名的授权证书,可以让IDE自动给ActiveX项目加上数字签名。
  Deploy required packages,如果ActiveX项目使用了包,发布ActiveX项目时会自动包括所需要的包。
  Deploy additional files,如果还需要跟其他文件一起发布,就选中这个复选框。
2. Packages页和Additional Files页
如果在Project页上选中了use CAB file compression复选框,在Packages页和Additional Files页上的
CAB Options框中就可以选择把CAB文件与OCX一起压缩还是单独分别压缩,一般都选择分别压缩到各自的
CAB中,这样能使用户避免每次都下载所有文件。如果选中Use File VersionInfo 复选框,发布引擎将决
定选中的文件是否有版本信息。如果有,在VersionInfo中的版本号将加到INF文件中。Target URL框缺省
地是Project页中Target URL框中的内容,即文件可以被下载的URL,如果ActiveX控件的用户已经安装了这
个文件,就让这个框空着。Target Directory编辑框用于指定文件被复制到服务器的哪个路径中。如果文件
已经在服务器中,就让这个编辑框空着,以避免重复复制。
3. Code Signing页
  Code Signing页可以用来指定授权文件和私人密钥文件。另外还能指定ActiveX控件的名称、公司的URL、
压缩算法类型、是否对授权文件加盖时间戳。推荐加盖时间戳,这样即使授权文件过期了,签名仍然有效。
注意:如果在Project页上的设置有错误,控件在Web页上出现的时候,在控件的左上角有一个红色的X。出
现这种情况后,要在HTML文件和INF文件中寻找错误,最通常的错误是控件的URL不正确。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多