一般来说,第三方控件有三种情况,
1、只定义了接口函数,没有功能应用。控件包装好之后,需要自己写应用程序
2、没有第三方控件,直接写方法和应用程序
3、既有接口函数又有功能应用
包装第三方控件有三类情况:
一、对于平台不支持的技术(如接口等),需要在DELPHI里将调用这些技术的函数写好,然后按照包装BPL的步骤进行包装。如(OfficeOle的
实现):
unit OleAdvFunc;
interface
uses
OleCtnrs, Dialogs;
type
TOleWordExpand = class
private
FOle: TOleContainer;
FTrack: Boolean;
FUserName: String;
procedure SetOle(const Value: TOleContainer);
procedure SetTrack(const Value: Boolean);
public
end;
procedure OleTrackRevisions(AOle: TOleContainer; ATrack: Boolean);
implementation
uses Word2000, Forms, Controls, ExtCtrls;
procedure OleTrackRevisions(AOle: TOleContainer; ATrack: Boolean);
var
V: Variant;
begin
V := (AOle.OleObjectInterface as _Document) as IDispatch;
V.TrackRevisions := ATrack;
end;
procedure TOleWordExpand.SetTrack(const Value: Boolean);
var
V: Variant;
begin
FTrack := Value;
Activate;
V := (FOle.OleObjectInterface as _Document) as IDispatch;
V.TrackRevisions := FTrack;
if Length(FUserName)>0 then
begin
V := (FOle.OleObjectInterface as _Document).Application;
V.UserName := FUserName;
end;
Activate;
end;
这样在这个程序里面来实现平台不能支持的接口技术,再包装成平台的控件使用。
二、有第三方控件如OCX或dll,在DELPHI 上调用这些控件写应用程序。这种办法省略了包装第三方控件的麻烦,但是缺点是由于应用是在
DELPHI上做的,如果需要任何调整,都需要重新打包。
三、有第三方控件如bpl,OCX或dll,包装到平台上来,然后在平台上面做应用程序,有点是应用程序比较容易调整,缺点是包装过程可能复杂
。应该是最佳方案。
下面列举常见的情况处理方式:
1、第三步生成注册文件reg文件的时候,提示“[错误]ERESULTLib_TLB(0, 0): 重载方法“TFindResult::Get_Count”必须加“overload”指
示字”
1) 保存Delphi 6生成的_TLB.pas文件副本
2) 修改_TLB.pas文件,去掉Get_Count等函数中间的下划线,用修改过的_TLB.pas文件执行步骤三生成_TLB_reg.pas文件
3) 修改生成的_TLB_reg.pas文件中的对应的函数,改回原来的名称(加下划线)
4) 将_TLB.pas文件也改回使用Delphi 6生成的_TLB.pas文件来继续下面的步骤。
2、第三步生成注册文件reg文件的时候,提示“[错误]WHUILib_TLB(75, 6): Undeclared identifier "_DWhui"”
控件中调用了接口,因此接口在平台是不识别的,请将接口包装成一个对象,在对象中调用接口,如:
_DWhui = dispinterface
['{6AF99621-EEC8-4FA4-8810-774F5F7D486A}']
procedure AboutBox; dispid -552;
end;
TWhui = class(TOleControl)
private
FIntf: _DWhui;
function GetControlInterface: _DWhui;
protected
procedure CreateControl;
procedure InitControlData; override;
public
procedure AboutBox;
property ControlInterface: _DWhui read GetControlInterface;
property DefaultInterface: _DWhui read GetControlInterface;
改为:
IDWhui = dispinterface
['{6AF99621-EEC8-4FA4-8810-774F5F7D486A}']
procedure AboutBox; dispid -552;
end;
IDWhuiEvents = dispinterface
['{51EDAE62-A8DF-43DB-B794-1E0F3B241C4E}']
end;
TDWhui = class
private
FServer: Variant;
public
constructor Create(AServer: Variant);
end;
TWhui = class(TOleControl)
private
FIntf: TDWhui;
function GetControlInterface: TDWhui;
protected
procedure CreateControl;
procedure InitControlData; override;
property ControlInterface: TDWhui read GetControlInterface;
property DefaultInterface: TDWhui read GetControlInterface;
… …
procedure TWhui.CreateControl;
procedure DoCreate;
begin
FIntf := TDWhui.Create(IUnknown(OleObject) as IDWhui);
end;
begin
if FIntf = nil then DoCreate;
end;
function TWhui.GetControlInterface: TDWhui;
begin
CreateControl;
Result := FIntf;
end;
constructor TDWhui.Create(AServer: Variant);
begin
FServer := AServer;
end;
3、改
_DWhui = dispinterface;
_DWhuiEvents = dispinterface;
为:
IDWhui = dispinterface;
IDWhuiEvents = dispinterface;
4、去掉:
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
// *********************************************************************//
Whui = _DWhui;
5、如何声明接口里的属性:如:
IDWhui = dispinterface
['{6AF99621-EEC8-4FA4-8810-774F5F7D486A}']
property Count: Integer dispid 1;
procedure AboutBox; dispid -552;
end;
声明:
TDImgThumbnail= class
private
FServer: Variant;
function GetCount: Integer;
procedure SetCount(Value: Integer);
public
property Count: Integer read GetCount write SetCount;
constructor Create(AServer: Variant);
end;
实现:
function TDImgThumbnail= .GetCount: Integer;
begin
Result := FServer.Count;
end;
procedure TDImgThumbnail= .SetCount(Value: Integer);
begin
FServer.Count := Value;
end;
6、引入OCX控件时,对于和接口有关的类,如何引入
案例:
接口声明:
IStringCollect = dispinterface
['{0F098950-F9F0-11CD-8C3D-00AA004BB3B7}']
property Count: Integer dispid 1;
procedure DoQuery; dispid 2;
function Next: WideString; dispid 3;
procedure Skip(nSkip: SYSINT); dispid 4;
procedure Reset; dispid 5;
procedure SetPath(vScope: OleVariant; const Path: WideString); dispid 6;
procedure EndQuery; dispid 7;
property _NewEnum: IUnknown readonly dispid -4;
end;
CoCStringCollect = class
class function Create: IStringCollect;
class function CreateRemote(const MachineName: string): IStringCollect;
end;
打包后:
TCStringCollect = class
private
FServer: Variant;
function GetCount: Integer;
procedure SetCount(Value: Integer);
function GetNewEnum: IUnknown;
public
property Count: Integer read GetCount write SetCount;
property _NewEnum: IUnknown read GetNewEnum ;
constructor Create(AServer: Variant);
procedure DoQuery;
function Next: WideString;
procedure Skip(nSkip: SYSINT);
procedure Reset;
procedure SetPath(vScope: OleVariant; const Path: WideString);
procedure EndQuery;
end;
CoCStringCollect = class
class function Create: TCStringCollect;
class function CreateRemote(const MachineName: string): TCStringCollect;
end;
编译报错,找不到类TCStringCollect;(未结的疑问)
如果不作任何改动,可以编译通过,但是,不能在平台上使用,后来我去掉这个类就可以了。
7、在编译BPL包文件时,不要丢下\LIB里的生成的任何注册文件,如:DBOleCtl_reg.pas,如果丢下的话,在平台使用的时候会报找不到
TDBOLECONTROL的错误!
8、也可以在类声明文件中,封装其他的方法,用来补充控件本身无法实现的功能。
9、必须强调的是,在包装之前务必保证这些控件在DELPHI上能正常使用。有些演示版本的控件,即使打包进来,也是无法使用的。
10、对于OCX和DLL控件,在平台引入后,也得需要在操作系统里注册原来的OCX,才能保证控件的正常使用。 |