개인적으로 DELPHI의 ActiveX 컨트롤 구현의 한계는 DELPHI ActiveX 컨트롤의 기본 클래스가 다음과 같이 TAutoObject에서 파생된다는 사실에 존재한다고 생각합니다.
TActiveXControl = 클래스(TAutoObject,
IConnectionPointContainer,
IData객체,
IObject안전,
IOle컨트롤,
IOleInPlaceActiveObject,
IOleInPlace객체,
IOleObject,
iperPROperty브라우징,
IPersistPropertyBag,
IPersist스토리지,
IPersistStreamInit,
IQuick활성화,
ISimpleFrameSite,
ISpecifyPropertyPages,
IView객체,
IViewObject2)
....
....
끝;
DELPHI를 사용하여 ActiveX 컨트롤을 만든 사람은 DELPHI의 ActiveX 컨트롤 마법사가 컨트롤에 포함된 VCL 양식 컨트롤(TWinControl에서 파생된 VCL 컨트롤)을 지정해야 하므로 이 VCL 양식 컨트롤을 만들려면 해당 구현에 VCL 양식 컨트롤이 포함되어야 한다는 것을 알고 있습니다. 언제든지 사용할 수 있는 DELPHI는 컨트롤을 위한 상위 창도 제공합니다. 아래 코드를 보세요:
절차 TActiveXControl.Initialize;
시작하다
상속된 초기화;
FConnectionPoints := TConnectionPoints.Create(Self);
FControlFactory := TActiveXControlFactory로서의 팩토리;
FControlFactory.EventTypeInfo <> nil인 경우
FConnectionPoints.CreateConnectionPoint(FControlFactory.EventIID,
ckSingle, 이벤트커넥트);
FPropertySinks := FConnectionPoints.CreateConnectionPoint(IPropertyNotifySink,
ckMulti, nil);
FControl := FControlFactory.WinControlClass.CreateParented(ParkingWindow);
FControl.ControlStyle에 csReflector가 있는 경우
FWinControl := TReflectorWindow.Create(ParkingWindow, FControl) else
FWinControl := FControl;
FControlWndProc := FControl.WindowProc;
FControl.WindowProc := WndProc;
초기화컨트롤;
끝;
이것이 DELPHI의 ActiveX 컨트롤 구현의 한계입니다. 이 ParkingWindow를 어떻게 제어합니까? 전체 ActiveX 컨트롤의 크기를 제어할 수 있고 많이 확장되었다고 해도 인터넷의 ActiveX 컨트롤은 작을수록 좋습니다. 적어도 이제 DELPHI는 vc light와 유사한 것을 달성해야 합니다(IPersistStreamInit만 구현함). IOleControl, IOleObject, IOleInPlaceActiveObject, IViewObjectEx, IOleInPlaceObjectWindowless 인터페이스(COM 개체)는 요구에 따라 인터페이스를 구현하는 것은 말할 것도 없고 매우 어렵습니다(activex 컨트롤이 IE, Word 또는 기타에서 사용되는지 여부에 따라 다름). 한 가지 해결책은 TAutoObject에서 파생되지 않고 다음과 같이 양식 컨트롤에서 직접 파생되는 것입니다.
TMyActiveXControl=클래스(TMyControl,
//TMyControl은 일반 클래스이거나 VCL 폼 컨트롤 클래스입니다.
//다음 인터페이스가 항상 파생되고 구현될 필요는 없습니다. 요청 시 파생 및 구현 가능
IConnectionPointContainer,
IData객체,
IObject안전,
IOle컨트롤,
IOleInPlaceActiveObject,
IOleInPlace객체,
IOleObject,
IPerProperty브라우징,
IPersistPropertyBag,
IPersist스토리지,
IPersistStreamInit,
IQuick활성화,
ISimpleFrameSite,
ISpecifyPropertyPages,
IView객체,
IViewObject2)
....
....
끝;
그렇다면 이 ActiveX 컨트롤을 어떻게 등록해야 할까요? 적합한 클래스 팩토리 개체가 없기 때문에 DELPHI의 클래스 팩토리는 다음과 같은 관계를 갖습니다.
-->TActiveXControlFactory-->TActiveFormFactory
TComObjectFactory는 다음과 같이 구현됩니다.
TComObject = 클래스(TObject, IUnknown, ISupportErrorInfo)
. . . .
끝;
TComClass = TComObject의 클래스;
TComObjectFactory = 클래스(TObject, IUnknown, IClassFactory, IClassFactory2)
…..
생성자 Create(ComServer: TComServerObject; ComClass: TComClass;
const ClassID: TGUID; const ClassName, 설명: 문자열;
인스턴싱: TClassInstancing: TThreadingModel = tmSingle);
끝;
클래스 팩토리의 생성자에는 ComClass 매개변수가 필요하며 TComObject는 TObject에서 파생됩니다. 따라서 파생할 적절한 클래스 팩토리 기본 클래스를 찾을 수 없는 경우 다음과 같은 델파이 구현이 없습니다.
TMyComObject = 클래스(TMyControl, IUnknown, ISupportErrorInfo)
. . . .
끝;
TMyComClass = TMyComObject의 클래스;
TMyComObjectFactory = 클래스(TObject, IUnknown, IClassFactory, IClassFactory2)
…..
생성자 Create(ComServer: TComServerObject; MyComClass: TMyComClass;
const ClassID: TGUID; const ClassName, 설명: 문자열;
인스턴싱: TClassInstancing: TThreadingModel = tmSingle);
끝;
불행하게도 그러한 클래스가 있더라도 우리는 그것을 사용할 수 없습니다. 이 제한은 다음과 같은 DELPHI의 COM 클래스 팩토리 구현에서 비롯됩니다.
TComServer = 클래스(TComServerObject)
사적인
. . . .
절차 FactoryFree(공장: TComObjectFactory);
절차 FactoryRegisterClassObject(공장: TComObjectFactory);
절차 FactoryUpdateRegistry(공장: TComObjectFactory);
절차 마지막 릴리스;
끝;
문제는 이러한 함수에 있습니다. 이러한 함수에는 TComObjectFactory 유형의 매개변수가 필요합니다. 이는 Delphi에서 제공하는 COM 서버의 구현을 사용해야 함을 의미합니다. 그런 다음 COM 객체의 클래스 팩토리를 TComObjectFactory에서 파생해야 합니다. 예를 들어 인터페이스를 사용하지 않고 이유를 알아냈습니다.
TComServer = 클래스(TComServerObject)
사적인
. . . .
절차 FactoryFree(공장: IClassFactory);
절차 FactoryRegisterClassObject(공장: IClassFactory);
절차 FactoryUpdateRegistry(공장: IClassFactory);
절차 마지막 릴리스;
끝;
결국 문제는 델파이에서 제공하는 클래스 팩토리와 COM 서버의 구현에 있습니다. 적어도 아직은 좋은 해결책을 찾지 못했습니다. COM 서버 dll과 내 자신의 ActiveX 컨트롤 클래스 팩토리를 구현합니다(실제로 하나 만들었습니다. 매우 간단해 보이며 COM 서버 구현을 위한 일부 Delph 메서드를 직접 사용할 수 있습니다).