Persönlich glaube ich, dass die Einschränkung der DELPHI-Implementierung der ActiveX-Steuerung darin besteht, dass die Basisklasse der DELPHI-ActiveX-Steuerung wie folgt von TAutoObject abgeleitet ist:
TActiveXControl = class(TAutoObject,
IConnectionPointContainer,
IDataObject,
IObjectSafety,
IOleControl,
IOleInPlaceActiveObject,
IOleInPlaceObject,
IOleObject,
iperPROpertyBrowsing,
IPersistPropertyBag,
IPersistStorage,
IPersistStreamInit,
IQuickActivate,
ISimpleFrameSite,
ISpecifyPropertyPages,
IViewObject,
IViewObject2)
....
....
Ende;
Jeder, der DELPHI zum Erstellen von ActiveX-Steuerelementen verwendet hat, weiß, dass der ActiveX-Steuerelementassistent von DELPHI das im Steuerelement enthaltene VCL-Formularsteuerelement angeben muss (von TWinControl abgeleitetes VCL-Steuerelement), sodass seine Implementierung ein VCL-Formularsteuerelement enthalten muss, um dieses VCL-Formularsteuerelement zu erstellen Jederzeit verfügbar stellt DELPHI auch ein übergeordnetes Fenster für die Steuerung zur Verfügung. Schauen Sie sich den folgenden Code an:
Prozedur TActiveXControl.Initialize;
beginnen
geerbt Initialisieren;
FConnectionPoints := TConnectionPoints.Create(Self);
FControlFactory := Factory als TActiveXControlFactory;
wenn FControlFactory.EventTypeInfo <> nil dann
FConnectionPoints.CreateConnectionPoint(FControlFactory.EventIID,
ckSingle, EventConnect);
FPropertySinks := FConnectionPoints.CreateConnectionPoint(IPropertyNotifySink,
ckMulti, nil);
FControl := FControlFactory.WinControlClass.CreateParented(ParkingWindow);
wenn csReflector in FControl.ControlStyle dann
FWinControl := TReflectorWindow.Create(ParkingWindow, FControl) sonst
FWinControl := FControl;
FControlWndProc := FControl.WindowProc;
FControl.WindowProc := WndProc;
InitializeControl;
Ende;
Dies ist die Einschränkung der ActiveX-Steuerung durch DELPHI. Wie steuern wir dieses ParkingWindow? Auch wenn wir die Größe der gesamten ActiveX-Steuerung steuern können, gilt: Je kleiner die ActiveX-Steuerung im Internet Zumindest muss DELPHI jetzt etwas Ähnliches wie vc Light erreichen (implementiert nur IPersistStreamInit). IOleControl, IOleObject, IOleInPlaceActiveObject, IViewObjectEx, IOleInPlaceObjectWindowless-Schnittstellen (COM-Objekte) sind sehr schwierig, geschweige denn die Schnittstelle bei Bedarf zu implementieren (abhängig davon, ob das ActiveX-Steuerelement in IE, Word oder anderen verwendet wird). Eine Lösung besteht darin, nicht von TAutoObject abzuleiten, sondern wie folgt direkt vom Formularsteuerelement:
TMyActiveXControl=class(TMyControl,
//TMyControl ist eine allgemeine Klasse oder eine VCL-Formularkontrollklasse.
//Die folgenden Schnittstellen müssen nicht immer abgeleitet und implementiert werden. Kann bei Bedarf abgeleitet und implementiert werden
IConnectionPointContainer,
IDataObject,
IObjectSafety,
IOleControl,
IOleInPlaceActiveObject,
IOleInPlaceObject,
IOleObject,
IPerPropertyBrowsing,
IPersistPropertyBag,
IPersistStorage,
IPersistStreamInit,
IQuickActivate,
ISimpleFrameSite,
ISpecifyPropertyPages,
IViewObject,
IViewObject2)
....
....
Ende;
Aber wenn ja, entsteht ein neues Problem. Wie registriert man dieses ActiveX-Steuerelement? Da es kein geeignetes Klassenfabrikobjekt gibt, weist die Klassenfabrik von DELPHI die folgende Beziehung auf:
->TActiveXControlFactory ->TActiveFormFactory
Und TComObjectFactory wird so implementiert:
TComObject = class(TObject, IUnknown, ISupportErrorInfo)
. . . .
Ende;
TComClass = Klasse von TComObject;
TComObjectFactory = class(TObject, IUnknown, IClassFactory, IClassFactory2)
…..
Konstruktor Create(ComServer: TComServerObject; ComClass: TComClass;
const ClassID: TGUID; const ClassName, Beschreibung: string;
Instanzierung: TClassInstancing; ThreadingModel: TThreadingModel = tmSingle);
Ende;
Der Konstruktor der Klassenfabrik erfordert den Parameter ComClass, und TComObject wird von TObject abgeleitet. Daher können wir keine geeignete Klassenfabrik-Basisklasse zum Ableiten finden, es sei denn, es gibt die folgende Delphi-Implementierung:
TMyComObject = class(TMyControl, IUnknown, ISupportErrorInfo)
. . . .
Ende;
TMyComClass = Klasse von TMyComObject;
TMyComObjectFactory = class(TObject, IUnknown, IClassFactory, IClassFactory2)
…..
Konstruktor Create(ComServer: TComServerObject; MyComClass: TMyComClass;
const ClassID: TGUID; const ClassName, Beschreibung: string;
Instanzierung: TClassInstancing; ThreadingModel: TThreadingModel = tmSingle);
Ende;
Selbst wenn es eine solche Klasse gibt, können wir sie leider nicht verwenden. Diese Einschränkung ergibt sich aus der Implementierung der COM-Klassenfabrik durch DELPHI wie folgt:
TComServer = class(TComServerObject)
Privat
. . . .
procedure FactoryFree(Factory: TComObjectFactory);
procedure FactoryRegisterClassObject(Factory: TComObjectFactory);
procedure FactoryUpdateRegistry(Factory: TComObjectFactory);
Prozedur LastReleased;
Ende;
Das Problem liegt darin, dass diese Funktionen vom Typ TComObjectFactory sein müssen, was bedeutet, dass die von Delphi bereitgestellte Implementierung des COM-Objekts verwendet werden muss Ich habe herausgefunden, warum, ohne eine Schnittstelle zu verwenden, zum Beispiel die folgende Implementierung:
TComServer = class(TComServerObject)
Privat
. . . .
procedure FactoryFree(Factory: IClassFactory);
procedure FactoryRegisterClassObject(Factory: IClassFactory);
procedure FactoryUpdateRegistry(Factory: IClassFactory);
Prozedur LastReleased;
Ende;
Letztendlich liegt das Problem in der Implementierung des COM-Servers und der von Delphi bereitgestellten Klassenfabrik. Zumindest habe ich noch keine gute Lösung gefunden Implementieren Sie die COM-Server-DLL und meine eigene ActiveX-Steuerklassenfabrik (ich habe tatsächlich eine erstellt, es fühlt sich sehr einfach an, einige Delph-Methoden zur Implementierung von COM-Servern können direkt verwendet werden).