Delphi生成的ActiveX创建模板的研究--Com对象是如何创建的

Delphi 生成的XXX_TLB.pas文件中生成了一个类

TActiveFormX = class(TOleObject)
…
end;

另外在XXX_Impl.pas文件中同样生成了一个类:TActiveFormX,经过研究,这两个类的确是:一个是接口,一个是实现类。

前者TActiveFormX从TOleObject继承,并且实现了方法:

procedure TActiveFormX.InitControlData;
const
    CEventDispIDs: array [0..8] of DWORD = (
        $000000C9, $000000CA, $000000CB, $000000CC, $000000CD, $000000CE,
        $000000CF, $000000D0, $000000D1);
    CTFontIDs: array [0..0] of DWORD = ($FFFFFE00);
    CControlData: TControlData2 = (
        ClassID: '{B90C2778-2158-48F5-A279-3A52BA87B423}';
        EventIID: '{8791E2BA-D57D-4CC9-91DA-81403D4E1144}';
        EventCount: 9;
        EventDispIDs: @CEventDispIDs;
        LicenseKey: nil (HR:$80040154);
        Flags: $0000001D;
        Version: 401;
        FontCount: 1;
        FontIDs: @CTFontIDs
    );
begin
    ControlData := @CControlData;
    TControlData2(CControlData).FirstEventOfs := Cardinal(@@FOnActivate) - Cardinal(Self);
end;

该方法负责定义这个OLE控件的类ID,事件接口ID,在TOleObject的方法TOleControl.createInstance中
则利用到了这些注册信息,创建COM对象:

procedure TOleControl.createInstance;
var
    ClassFactory2: IClassFactory2;
    LicKeyStr: WideString;

    procedure LicenseCheck(Status: HResult; const Ident: string);
    begin
        if Status = CLASS_E_NOTLICENSED then
        raise EOleError.createFmt(Ident, [ClassName]);
        OleCheck(Status);
    end;
begin
    if not (csDesigning in ComponentState) and (FControlData^.LicenseKey <> nil) then
    begin
        //创建COM对象,其中FControlData^.ClassID为子类定义的COM对象的ID
        OleCheck(CoGetClassObject(FControlData^.ClassID, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, nil, IClassFactory2, ClassFactory2));
        LicKeyStr := PWideChar(FControlData^.LicenseKey);
        LicenseCheck(ClassFactory2.createInstanceLic(nil, nil, IOleObject,
            LicKeyStr, FOleObject), SInvalidLicense);
    end 
    else 
    begin
        LicenseCheck(
            CocreateInstance(FControlData^.ClassID, nil,
                CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IOleObject,
                FOleObject), 
            SNotLicensed);
    end;
end;

COM对象的实现单元XXX_Impl.pas则定义了该COM对象的实现,并且创建了一个TActiveXControlFactory,用于生成该COM对象:

initialization
TActiveFormFactory.create(
    ComServer,
    TActiveFormControl,
    TActiveFormX,
    Class_ActiveFormX,
    1,
    '',
    OLEMISC_SIMPLEFRAME or OLEMISC_ACTSlikeLABEL,
    tmApartment);
end.

因此前一个TActiveXForm 被称为OLEProxy,即Ole的调用网关。

COM 系统 CocreateInstance(IID) 的时候会请求相应的TActiveFormFactory 调用相应的createIntance方法。

1,574 次阅读

发表评论

电子邮件地址不会被公开。 必填项已用*标注