Browse Source

* Patch by Ludo Brands to support creation of activeX containers and event sink components (bug 20991)

git-svn-id: trunk@19935 -
michael 13 years ago
parent
commit
c20d68baec
1 changed files with 293 additions and 40 deletions
  1. 293 40
      packages/winunits-base/src/typelib.pas

+ 293 - 40
packages/winunits-base/src/typelib.pas

@@ -44,13 +44,16 @@ Reads type information from 'FileName' and converts it in a freepascal binding u
 contents of the unit is returned as the function result.
 contents of the unit is returned as the function result.
 Returns in 'sUnitName' the unit name with '.pas' extension.
 Returns in 'sUnitName' the unit name with '.pas' extension.
 Appends to 'slDependencies' the filenames of the additional typelibs needed.
 Appends to 'slDependencies' the filenames of the additional typelibs needed.
+If bActiveX is true an ActiveXContainer descendant is created with the evenual OnEvent hooks
+If bActiveX is false and an event source is found an TEventSink descendant is created with the OnEvent hooks
 
 
 By default, the type library is extracted from the first resource of type ITypeLib.
 By default, the type library is extracted from the first resource of type ITypeLib.
 To load a different type of library resource, append an integer index to 'FileName'.
 To load a different type of library resource, append an integer index to 'FileName'.
 
 
 Example:  C:\WINDOWS\system32\msvbvm60.dll\3
 Example:  C:\WINDOWS\system32\msvbvm60.dll\3
 }
 }
-function ImportTypelib(FileName: WideString;var sUnitName:string;var slDependencies:TStringList):string;
+function ImportTypelib(FileName: WideString;var sUnitName:string;var slDependencies:TStringList;
+    bActiveX:boolean):string;
 
 
 
 
 Type
 Type
@@ -59,6 +62,7 @@ Type
 
 
   TTypeLibImporter = Class(TComponent)
   TTypeLibImporter = Class(TComponent)
   private
   private
+    FActiveX: Boolean;
     FAppendVersionNumber: Boolean;
     FAppendVersionNumber: Boolean;
     FDependencies: TStringList;
     FDependencies: TStringList;
     FUnitSource: TStringList;
     FUnitSource: TStringList;
@@ -70,6 +74,12 @@ Type
     FInterface : TStrings;
     FInterface : TStrings;
     FImplementation : TStrings;
     FImplementation : TStrings;
     FTypes : TStrings;
     FTypes : TStrings;
+    FEventDisp : TStrings;
+    FEventIID : TStrings;
+    FEventSignatures: TStrings;
+    FEventFunctions: TStrings;
+    FEventProperties: TStrings;
+    FEventImplementations: TStrings;
     function GetDependencies: TStrings;
     function GetDependencies: TStrings;
     function GetUnitSource: TStrings;
     function GetUnitSource: TStrings;
     procedure SetOutputFileName(AValue: String);
     procedure SetOutputFileName(AValue: String);
@@ -87,7 +97,8 @@ Type
     Procedure AddToImplementation(Const ALine : String);virtual;
     Procedure AddToImplementation(Const ALine : String);virtual;
     Procedure AddToImplementation(Const Fmt : String; Args : Array of const);
     Procedure AddToImplementation(Const Fmt : String; Args : Array of const);
     // utility functions
     // utility functions
-    function interfacedeclaration(iName, iDoc: string; TI: ITypeInfo; TA: LPTYPEATTR; bIsDispatch: boolean): string;
+    function interfacedeclaration(iName, iDoc: string; TI: ITypeInfo; TA: LPTYPEATTR;
+      bIsDispatch,bCreateEvents:boolean): string;
     function VarTypeIsAutomatable(ParamType: integer): boolean; virtual;
     function VarTypeIsAutomatable(ParamType: integer): boolean; virtual;
     function VarTypeToStr(ParamType: integer): string; virtual;
     function VarTypeToStr(ParamType: integer): string; virtual;
     function TypeToString(TI: ITypeInfo; TD: TYPEDESC): string; virtual;
     function TypeToString(TI: ITypeInfo; TD: TYPEDESC): string; virtual;
@@ -113,6 +124,8 @@ Type
     Property Dependencies : TStrings Read GetDependencies;
     Property Dependencies : TStrings Read GetDependencies;
     Property UnitSource : TStrings Read GetUnitSource;
     Property UnitSource : TStrings Read GetUnitSource;
   Published
   Published
+    // Create ActiveXContainer descendant: default false
+    Property ActiveX : Boolean Read FActiveX write FActiveX Default False;
     // Append version number to unit name.
     // Append version number to unit name.
     Property AppendVersionNumber : Boolean Read FAppendVersionNumber Write FAppendVersionNumber Default True;
     Property AppendVersionNumber : Boolean Read FAppendVersionNumber Write FAppendVersionNumber Default True;
     // File to read typelib from.
     // File to read typelib from.
@@ -129,12 +142,14 @@ implementation
 Resourcestring
 Resourcestring
   SErrInvalidUnitName = 'Invalid unit name : %s';
   SErrInvalidUnitName = 'Invalid unit name : %s';
 
 
-function ImportTypelib(FileName: WideString;var sUnitName:string;var slDependencies:TStringList):string;
+function ImportTypelib(FileName: WideString;var sUnitName:string;var slDependencies:TStringList;
+  bActiveX:boolean):string;
 var i:integer;
 var i:integer;
 begin
 begin
   With TTypeLibImporter.Create(Nil) do
   With TTypeLibImporter.Create(Nil) do
     try
     try
       InputFileName:=FileName;
       InputFileName:=FileName;
+      ActiveX:=bActiveX;
       Execute;
       Execute;
       Result:=UnitSource.Text;
       Result:=UnitSource.Text;
       sUnitname:=UnitName+'.pas';
       sUnitname:=UnitName+'.pas';
@@ -174,7 +189,7 @@ begin
     vt_dispatch  : Result := 'IDispatch';
     vt_dispatch  : Result := 'IDispatch';
     vt_error : Result := 'SCODE';
     vt_error : Result := 'SCODE';
     vt_bool : Result := 'WordBool';
     vt_bool : Result := 'WordBool';
-    vt_variant : Result := 'OleVariant';
+    vt_variant : Result := 'Variant';
     vt_unknown : Result := 'IUnknown';
     vt_unknown : Result := 'IUnknown';
     vt_i1  : Result := 'ShortInt';
     vt_i1  : Result := 'ShortInt';
     vt_ui1 : Result := 'Byte';
     vt_ui1 : Result := 'Byte';
@@ -322,7 +337,7 @@ begin
     begin
     begin
     TD:=TD.lptdesc^;
     TD:=TD.lptdesc^;
     result:='P'+TypeToString(TI,TD);
     result:='P'+TypeToString(TI,TD);
-    bIsAutomatable:=(VarTypeIsAutomatable(TD.vt) and (TD.vt<>VT_VARIANT)) or bIsCustomAutomatable;
+    bIsAutomatable:=(VarTypeIsAutomatable(TD.vt) {and (TD.vt<>VT_VARIANT)}) or bIsCustomAutomatable;
     exit;
     exit;
     end
     end
   else if TD.vt=VT_CARRAY then //C type array
   else if TD.vt=VT_CARRAY then //C type array
@@ -343,7 +358,8 @@ begin
   bIsAutomatable:=VarTypeIsAutomatable(TD.vt) or bIsCustomAutomatable;
   bIsAutomatable:=VarTypeIsAutomatable(TD.vt) or bIsCustomAutomatable;
 end;
 end;
 
 
-function TTypeLibImporter.interfacedeclaration(iName,iDoc:string;TI:ITypeInfo;TA:LPTYPEATTR;bIsDispatch:boolean):string;
+function TTypeLibImporter.interfacedeclaration(iName,iDoc:string;TI:ITypeInfo;TA:LPTYPEATTR;
+  bIsDispatch,bCreateEvents:boolean):string;
 
 
 type
 type
   TPropertyDef=record
   TPropertyDef=record
@@ -362,13 +378,14 @@ var
   RTIT: HREFTYPE;
   RTIT: HREFTYPE;
   TIref: ITypeInfo;
   TIref: ITypeInfo;
   BstrName,BstrNameRef,BstrDocString : WideString;
   BstrName,BstrNameRef,BstrDocString : WideString;
-  s,sl,sPropIntfc,sPropDispIntfc,sType,sConv,sFunc,sVarName,sMethodName,sPropParam,sPropParam2:string;
+  s,sl,sPropIntfc,sPropDispIntfc,sType,sConv,sFunc,sPar,sVarName,sMethodName,sPropParam,sPropParam2:string;
+  sEventSignatures,sEventFunctions,sEventProperties,sEventImplementations:string;
   i,j,k:integer;
   i,j,k:integer;
   FD: lpFUNCDESC;
   FD: lpFUNCDESC;
   BL : array[0..99] of TBstr;
   BL : array[0..99] of TBstr;
   cnt:LongWord;
   cnt:LongWord;
   TD: TYPEDESC;
   TD: TYPEDESC;
-  bPropHasParam,bIsFunction:boolean;
+  bPropHasParam,bIsFunction,bParamByRef:boolean;
   VD: lpVARDESC;
   VD: lpVARDESC;
   aPropertyDefs:array of TPropertyDef;
   aPropertyDefs:array of TPropertyDef;
   Propertycnt,iType:integer;
   Propertycnt,iType:integer;
@@ -403,7 +420,10 @@ var
 begin
 begin
   Propertycnt:=0;
   Propertycnt:=0;
   SetLength(aPropertyDefs,TA^.cFuncs+TA^.cVars);   // worst case, all functions getters or all setters
   SetLength(aPropertyDefs,TA^.cFuncs+TA^.cVars);   // worst case, all functions getters or all setters
-  result:='TA^.cFuncs';
+  sEventSignatures:='';
+  sEventFunctions:='';
+  sEventProperties:='';
+  sEventImplementations:='';
   if not bIsDispatch then
   if not bIsDispatch then
     begin
     begin
     // find base class
     // find base class
@@ -490,28 +510,37 @@ begin
           AddToHeader('//  Warning: ''%s'' not automatable in %sdisp.%s',[stype,iname,BstrName],True);
           AddToHeader('//  Warning: ''%s'' not automatable in %sdisp.%s',[stype,iname,BstrName],True);
           sType:='{!! '+sType+' !!} OleVariant';
           sType:='{!! '+sType+' !!} OleVariant';
           end;
           end;
+        if bCreateEvents then
+          begin
+          sEventSignatures:=sEventSignatures+format('  T%s%s = procedure(Sender: TObject;',[iname,sMethodName]);
+          sEventFunctions:=sEventFunctions+format('    FOn%s:T%s%s;'#13#10,[sMethodName,iname,sMethodName]);
+          sEventProperties:=sEventProperties+format('    property On%s : T%s%s read FOn%s write FOn%s;'#13#10,
+            [sMethodName,iname,sMethodName,sMethodName,sMethodName]);
+          sEventImplementations:=sEventImplementations+
+            format('    %d: if assigned(On%s) then'#13#10+
+                   '          On%s(Self,',[FD^.memid,sMethodName,sMethodName]);
+          end;
         // parameters
         // parameters
         for k:=0 to FD^.cParams-1 do
         for k:=0 to FD^.cParams-1 do
           begin
           begin
+          bParamByRef:=(FD^.lprgelemdescParam[k].tdesc.vt=VT_PTR) and                         // by ref
+            not((FD^.lprgelemdescParam[k].tdesc.lptdesc^.vt=VT_USERDEFINED) and bIsInterface);// but not pointer to interface
           if (FD^.lprgelemdescParam[k].paramdesc.wParamFlags and PARAMFLAG_FRETVAL ) <>0 then  //return type
           if (FD^.lprgelemdescParam[k].paramdesc.wParamFlags and PARAMFLAG_FRETVAL ) <>0 then  //return type
             continue;
             continue;
           sl:=TypeToString(TI,FD^.lprgelemdescParam[k].tdesc);
           sl:=TypeToString(TI,FD^.lprgelemdescParam[k].tdesc);
-          if sMethodName='Clone' then
-            sl:=sl;
-          if (FD^.lprgelemdescParam[k].tdesc.vt=VT_PTR) and                                        // by ref
-            not((FD^.lprgelemdescParam[k].tdesc.lptdesc^.vt=VT_USERDEFINED) and bIsInterface) then // but not pointer to interface
+          if bParamByRef then
              delete(sl,1,1);
              delete(sl,1,1);
           if bIsDispatch and not bIsAutomatable then
           if bIsDispatch and not bIsAutomatable then
             begin
             begin
             AddToHeader('//  Warning: ''%s'' not automatable in %sdisp.%s',[sl,iname,sMethodName],True);
             AddToHeader('//  Warning: ''%s'' not automatable in %sdisp.%s',[sl,iname,sMethodName],True);
             sl:='{!! '+sl+' !!} OleVariant';
             sl:='{!! '+sl+' !!} OleVariant';
             end;
             end;
-          if (FD^.lprgelemdescParam[k].tdesc.vt=VT_PTR) and                                          // by ref
-              not((FD^.lprgelemdescParam[k].tdesc.lptdesc^.vt=VT_USERDEFINED) and bIsInterface) then // but not pointer to interface
+          sPar:='';
+          if bParamByRef then
             case FD^.lprgelemdescParam[k].paramdesc.wParamFlags and (PARAMFLAG_FIN or PARAMFLAG_FOUT) of
             case FD^.lprgelemdescParam[k].paramdesc.wParamFlags and (PARAMFLAG_FIN or PARAMFLAG_FOUT) of
-            PARAMFLAG_FIN or PARAMFLAG_FOUT:sFunc:=sFunc+'var ';
-            PARAMFLAG_FOUT:sFunc:=sFunc+'out ';
-            PARAMFLAG_FIN:sFunc:=sFunc+'var '; //constref in safecall? TBD
+            PARAMFLAG_FIN or PARAMFLAG_FOUT:sPar:='var ';
+            PARAMFLAG_FOUT:sPar:='out ';
+            PARAMFLAG_FIN:sPar:='var '; //constref in safecall? TBD
             end;
             end;
           if ValidateID(BL[k+1]) then
           if ValidateID(BL[k+1]) then
             sVarName:=BL[k+1]
             sVarName:=BL[k+1]
@@ -520,13 +549,53 @@ begin
             sVarName:=BL[k+1]+'_';
             sVarName:=BL[k+1]+'_';
             AddToHeader('//  Warning: renamed parameter ''%s'' in %s.%s to ''%s'''#13#10,[BL[k+1],iname,sMethodName,sVarName],True);
             AddToHeader('//  Warning: renamed parameter ''%s'' in %s.%s to ''%s'''#13#10,[BL[k+1],iname,sMethodName,sVarName],True);
             end;
             end;
-          sFunc:=sFunc+format('%s:%s;',[sVarName,sl]);
+          sPar:=sPar+format('%s:%s;',[sVarName,sl]);
+          sFunc:=sFunc+sPar;
+          if bCreateEvents then
+            begin
+            sEventSignatures:=sEventSignatures+sPar;
+            //params are numbered last to first
+            if bParamByRef and not(bIsDispatch and not bIsAutomatable) then
+              begin
+              case FD^.lprgelemdescParam[k].tdesc.lptdesc^.vt of
+                VT_UI1:       sl:='pbVal';
+                VT_UI2:       sl:='puiVal';
+                VT_UI4:       sl:='pulVal';
+                VT_UI8:       sl:='pullVal';
+                VT_I1:        sl:='pcVal';
+                VT_I2:        sl:='piVal';
+                VT_I4:        sl:='plVal';
+                VT_I8:        sl:='pllVal';
+                VT_R4:        sl:='pfltVal';
+                VT_R8:        sl:='pdblVal';
+                VT_BOOL:      sl:='pbool';
+                VT_ERROR:     sl:='pscode';
+                VT_CY:        sl:='pcyVal';
+                VT_DATE:      sl:='pdate';
+                VT_BSTR:      sl:='pbstrVal';
+                VT_UNKNOWN:   sl:='punkVal';
+                VT_DISPATCH:  sl:='pdispVal';
+                VT_ARRAY:     sl:='pparray';
+                VT_VARIANT:   sl:='pvarVal';
+              end;
+              sEventImplementations:=sEventImplementations+format(' Params.rgvarg[%d].%s^,',[FD^.cParams-1-k,sl]);
+              end
+            else
+              sEventImplementations:=sEventImplementations+format(' OleVariant(Params.rgvarg[%d]),',[FD^.cParams-1-k]);
+            end;
           end;
           end;
         // finish interface and dispinterface
         // finish interface and dispinterface
         if sFunc[length(sFunc)]=';' then
         if sFunc[length(sFunc)]=';' then
           sFunc[length(sFunc)]:=')'
           sFunc[length(sFunc)]:=')'
         else  // no params
         else  // no params
           delete(sFunc,length(sFunc),1);
           delete(sFunc,length(sFunc),1);
+        if bCreateEvents then
+          begin
+          sEventSignatures[length(sEventSignatures)]:=')';
+          sEventSignatures:=sEventSignatures+' of object;'#13#10;
+          sEventImplementations[length(sEventImplementations)]:=')';
+          sEventImplementations:=sEventImplementations+';'#13#10;
+          end;
         if bIsFunction then
         if bIsFunction then
           sFunc:=sFunc+format(':%s',[sType]);
           sFunc:=sFunc+format(':%s',[sType]);
         if bIsDispatch then
         if bIsDispatch then
@@ -647,6 +716,15 @@ begin
         end;
         end;
       end;
       end;
     end;
     end;
+  if bCreateEvents then
+    begin
+    FEventDisp.Add(iname);
+    FEventIID.Add(GUIDToString(TA^.GUID));
+    FEventSignatures.Add(sEventSignatures);
+    FEventFunctions.Add(sEventFunctions);
+    FEventProperties.Add(sEventProperties);
+    FEventImplementations.Add(sEventImplementations);
+    end;
   if bIsDispatch then
   if bIsDispatch then
     result:=s + sPropDispIntfc +'  end;'#13#10
     result:=s + sPropDispIntfc +'  end;'#13#10
   else
   else
@@ -827,7 +905,7 @@ Var
   slDeferredType,slDeferredPendingType,slDeferredDeclaration:TStrings;
   slDeferredType,slDeferredPendingType,slDeferredDeclaration:TStrings;
   sl,sldeclaration,stype,smembername,srecordname:string;
   sl,sldeclaration,stype,smembername,srecordname:string;
   bIsDeferred:boolean;
   bIsDeferred:boolean;
- 
+
   procedure ReleasePendingType(sPen:string);
   procedure ReleasePendingType(sPen:string);
   var k:integer;
   var k:integer;
     sDec,sTyp:string;
     sDec,sTyp:string;
@@ -860,7 +938,6 @@ begin
   slDeferredPendingType:=TStringList.Create;
   slDeferredPendingType:=TStringList.Create;
   slDeferredDeclaration:=TStringList.Create;
   slDeferredDeclaration:=TStringList.Create;
   try
   try
-
   for i:=0 to TIcount-1 do
   for i:=0 to TIcount-1 do
     begin
     begin
     bIsDeferred:=false;
     bIsDeferred:=false;
@@ -871,7 +948,7 @@ begin
     OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
     OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
     OleCheck(TI.GetTypeAttr(TA));
     OleCheck(TI.GetTypeAttr(TA));
     case TIT of
     case TIT of
-     TKIND_RECORD,TKIND_UNION:
+      TKIND_RECORD,TKIND_UNION:
         begin
         begin
         if ValidateID(BstrName) then
         if ValidateID(BstrName) then
           sRecordName:=BstrName
           sRecordName:=BstrName
@@ -949,7 +1026,7 @@ begin
           begin
           begin
           AddToInterface(sl);
           AddToInterface(sl);
           FTypes.Add(sRecordName);
           FTypes.Add(sRecordName);
-		  ReleasePendingType(sRecordName);
+          ReleasePendingType(sRecordName);
           end;
           end;
         end;
         end;
       end;
       end;
@@ -981,7 +1058,6 @@ Var
   TA,TAref : LPTYPEATTR;
   TA,TAref : LPTYPEATTR;
   TIT : TYPEKIND;
   TIT : TYPEKIND;
   RTIT : HREFTYPE;
   RTIT : HREFTYPE;
-
 begin
 begin
   // interface declarations
   // interface declarations
   AddToInterface('//interface declarations');
   AddToInterface('//interface declarations');
@@ -1001,13 +1077,15 @@ begin
           OleCheck(TI.GetRefTypeOfImplType(-1,RTIT));
           OleCheck(TI.GetRefTypeOfImplType(-1,RTIT));
           OleCheck(TI.GetRefTypeInfo(RTIT,TIref));
           OleCheck(TI.GetRefTypeInfo(RTIT,TIref));
           OleCheck(TIref.GetTypeAttr(TAref));
           OleCheck(TIref.GetTypeAttr(TAref));
-          AddToInterface(interfacedeclaration(BstrName,BstrDocString,TIref,TAref,false));
+          AddToInterface(interfacedeclaration(BstrName,BstrDocString,TIref,TAref,false,false));
           TIref.ReleaseTypeAttr(TAref);
           TIref.ReleaseTypeAttr(TAref);
-          end;
-        AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,true));
+          AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,true,false));
+          end
+        else
+          AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,true,true));
         end
         end
       else
       else
-        AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,false));
+        AddToInterface(interfacedeclaration(BstrName,BstrDocString,TI,TA,false,false));
       TI.ReleaseTypeAttr(TA);
       TI.ReleaseTypeAttr(TA);
       end;
       end;
     end;
     end;
@@ -1016,14 +1094,15 @@ end;
 Procedure TTypeLibImporter.CreateCoClasses(Const TL : ITypeLib; TICount : Integer);
 Procedure TTypeLibImporter.CreateCoClasses(Const TL : ITypeLib; TICount : Integer);
 
 
 Var
 Var
-  i : integer;
+  i, j ,idx: integer;
   BstrName, BstrDocString, BstrHelpFile, BstrNameRef : WideString;
   BstrName, BstrDocString, BstrHelpFile, BstrNameRef : WideString;
   dwHelpContext : DWORD;
   dwHelpContext : DWORD;
   TI,TIref : ITypeInfo;
   TI,TIref : ITypeInfo;
   TA : LPTYPEATTR;
   TA : LPTYPEATTR;
   TIT : TYPEKIND;
   TIT : TYPEKIND;
   RTIT : HREFTYPE;
   RTIT : HREFTYPE;
-
+  sDefIntf, sDefEvents : string;
+  ITF:WINT;
 begin
 begin
   //CoClasses
   //CoClasses
   AddToInterface('//CoClasses');
   AddToInterface('//CoClasses');
@@ -1039,24 +1118,186 @@ begin
       OleCheck(TL.GetTypeInfo(i, TI));
       OleCheck(TL.GetTypeInfo(i, TI));
       OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
       OleCheck(TL.GetDocumentation(i, @BstrName, @BstrDocString, @dwHelpContext, @BstrHelpFile));
       OleCheck(TI.GetTypeAttr(TA));
       OleCheck(TI.GetTypeAttr(TA));
-      OleCheck(TI.GetRefTypeOfImplType(0,RTIT));
-      OleCheck(TI.GetRefTypeInfo(RTIT,TIref));
-      OleCheck(TIRef.GetDocumentation(DISPID_UNKNOWN, @BstrNameRef, nil, nil, nil));
+      // get default interface and events.
+      sDefEvents:='';
+      for j:=0 to TA^.cImplTypes-1 do
+        begin
+        OleCheck(TI.GetImplTypeFlags(J,ITF));
+        if (ITF and IMPLTYPEFLAG_FDEFAULT)<>0 then
+          begin
+          OleCheck(TI.GetRefTypeOfImplType(J,RTIT));
+          OleCheck(TI.GetRefTypeInfo(RTIT,TIref));
+          OleCheck(TIRef.GetDocumentation(DISPID_UNKNOWN, @BstrNameRef, nil, nil, nil));
+          if (ITF and IMPLTYPEFLAG_FSOURCE)<>0 then
+            begin
+            sDefEvents:=BstrNameRef;
+            idx:=FEventDisp.IndexOf(sDefEvents);
+            if idx<0 then // should not happen
+              sDefEvents:='';
+            end
+          else
+            sDefIntf:=BstrNameRef;
+          end;
+        end;
+      if sDefEvents<>'' then //add event signatures
+        begin
+        AddToInterface(FEventSignatures[idx]);
+        FEventSignatures[idx]:='';  // only add event signatures only once. Multiple coclasses can use same events
+        AddToInterface('');
+        end;
       AddToInterFace('  Co%s = Class',[BstrName]);
       AddToInterFace('  Co%s = Class',[BstrName]);
-      AddToInterface('    Class Function Create: %s;',[BstrNameRef]);
-      AddToInterFace('    Class Function CreateRemote(const MachineName: string): %s;',[BstrNameRef]);
+      AddToInterface('  Public');
+      AddToInterface('    Class Function Create: %s;',[sDefIntf]);
+      AddToInterFace('    Class Function CreateRemote(const MachineName: string): %s;',[sDefIntf]);
       AddToInterFace('  end;');
       AddToInterFace('  end;');
       AddToInterFace('');
       AddToInterFace('');
-      AddToImplementation('Class Function Co%s.Create: %s;',[BstrName,BstrNameRef]);
+      if FActiveX then
+        begin
+        if FUses.IndexOf('ActiveXContainer')<0 then
+          FUses.Add('ActiveXContainer');
+        AddToInterFace('  T%s = Class(TActiveXContainer)',[BstrName]);
+        AddToInterface('  Private');
+        AddToInterface('    FServer:%s;',[sDefIntf]);
+        if (sDefEvents<>'') then //add function variables
+          begin
+          if FUses.IndexOf('Eventsink')<0 then
+            FUses.Add('EventSink');
+          AddToInterface(FEventFunctions[idx]);
+          AddToInterface('    FEventSink:TEventSink;',[sDefIntf]);
+          AddToInterface('    procedure EventSinkInvoke(Sender: TObject; DispID: Integer;');
+          AddToInterface('          const IID: TGUID; LocaleID: Integer; Flags: Word;');
+          AddToInterface('          Params: tagDISPPARAMS; VarResult, ExcepInfo, ArgErr: Pointer);');
+          end;
+        AddToInterface('  Public');
+        AddToInterface('    constructor Create(TheOwner: TComponent); override;');
+        AddToInterface('    destructor Destroy; override;');
+        AddToInterface('    property OleServer:%s read FServer;',[sDefIntf]);
+        AddToInterFace('  Published');
+        AddToInterFace('    property Align;');
+        AddToInterFace('    property Anchors;');
+        AddToInterFace('    property AutoSize;');
+        AddToInterFace('    property BorderSpacing;');
+        AddToInterFace('    property ChildSizing;');
+        AddToInterFace('    property ClientHeight;');
+        AddToInterFace('    property ClientWidth;');
+        AddToInterFace('    property Constraints;');
+        AddToInterFace('    property DockSite;');
+        AddToInterFace('    property DragCursor;');
+        AddToInterFace('    property DragKind;');
+        AddToInterFace('    property DragMode;');
+        AddToInterFace('    property Enabled;');
+        AddToInterFace('    property ParentShowHint;');
+        AddToInterFace('    property PopupMenu;');
+        AddToInterFace('    property ShowHint;');
+        AddToInterFace('    property TabOrder;');
+        AddToInterFace('    property TabStop;');
+        AddToInterFace('    property UseDockManager default True;');
+        AddToInterFace('    property Visible;');
+        AddToInterFace('    property OnContextPopup;');
+        AddToInterFace('    property OnDockDrop;');
+        AddToInterFace('    property OnDockOver;');
+        AddToInterFace('    property OnDragDrop;');
+        AddToInterFace('    property OnDragOver;');
+        AddToInterFace('    property OnEndDock;');
+        AddToInterFace('    property OnEndDrag;');
+        AddToInterFace('    property OnEnter;');
+        AddToInterFace('    property OnExit;');
+        AddToInterFace('    property OnGetSiteInfo;');
+        AddToInterFace('    property OnGetDockCaption;');
+        AddToInterFace('    property OnResize;');
+        AddToInterFace('    property OnStartDock;');
+        AddToInterFace('    property OnStartDrag;');
+        AddToInterFace('    property OnStatusText;');
+        AddToInterFace('    property OnUnDock;');
+        if (sDefEvents<>'') then
+          AddToInterface(FEventProperties[idx]);
+        AddToInterFace('    property Active;');
+        AddToInterFace('  end;');
+        AddToInterFace('');
+        end
+      else if (sDefEvents<>'') then //add function variables
+        begin
+        if FUses.IndexOf('Eventsink')<0 then
+          FUses.Add('EventSink');
+        AddToInterFace('  T%s = Class(TEventSink)',[BstrName]);
+        AddToInterface('  Private');
+        AddToInterface(FEventFunctions[idx]);
+        AddToInterface('    fServer:%s;',[sDefIntf]);
+        AddToInterface('    procedure EventSinkInvoke(Sender: TObject; DispID: Integer;');
+        AddToInterface('          const IID: TGUID; LocaleID: Integer; Flags: Word;');
+        AddToInterface('          Params: tagDISPPARAMS; VarResult, ExcepInfo, ArgErr: Pointer);');
+        AddToInterface('  Public');
+        AddToInterface('    constructor Create(TheOwner: TComponent); override;');
+        AddToInterface('    property ComServer:%s read fServer;',[sDefIntf]);
+        AddToInterface(FEventProperties[idx]);
+        AddToInterFace('  end;');
+        AddToInterFace('');
+        end;
+      AddToImplementation('Class Function Co%s.Create: %s;',[BstrName,sDefIntf]);
       AddToImplementation('begin');
       AddToImplementation('begin');
-      AddToImplementation('  Result := CreateComObject(CLASS_%s) as %s;',[BstrName,BstrNameRef]);
+      AddToImplementation('  Result := CreateComObject(CLASS_%s) as %s;',[BstrName,sDefIntf]);
       AddToImplementation('end;');
       AddToImplementation('end;');
       AddToImplementation('');
       AddToImplementation('');
-      AddToImplementation('Class Function Co%s.CreateRemote(const MachineName: string): %s;',[BstrName,BstrNameRef]);
+      AddToImplementation('Class Function Co%s.CreateRemote(const MachineName: string): %s;',[BstrName,sDefIntf]);
       AddToImplementation('begin');
       AddToImplementation('begin');
-      AddToImplementation('  Result := CreateRemoteComObject(MachineName,CLASS_%s) as %s;',[BstrName,BstrNameRef]);
+      AddToImplementation('  Result := CreateRemoteComObject(MachineName,CLASS_%s) as %s;',[BstrName,sDefIntf]);
       AddToImplementation('end;');
       AddToImplementation('end;');
       AddToImplementation('');
       AddToImplementation('');
+      if FActiveX then
+        begin
+        AddToImplementation('constructor T%s.Create(TheOwner: TComponent);',[BstrName]);
+        AddToImplementation('begin');
+        AddToImplementation('  inherited Create(TheOwner);');
+        AddToImplementation('  FServer:=Co%s.Create;',[BstrName]);
+        AddToImplementation('  ComServer:=FServer;',[BstrName]);
+        if (sDefEvents<>'') then
+          begin
+          AddToImplementation('  FEventSink:=TEventSink.Create(Self);');
+          AddToImplementation('  FEventSink.OnInvoke:=EventSinkInvoke;');
+          AddToImplementation('  FEventSink.Connect(FServer,%s);',[FEventDisp[idx]]);
+          end;
+        AddToImplementation('end;');
+        AddToImplementation('');
+        AddToImplementation('destructor T%s.Destroy;',[BstrName]);
+        AddToImplementation('begin');
+        if (sDefEvents<>'') then
+          AddToImplementation('  FEventSink.Destroy;');
+        AddToImplementation('  inherited destroy;');
+        AddToImplementation('end;');
+        AddToImplementation('');
+        if (sDefEvents<>'') then
+          begin
+          AddToImplementation('procedure T%s.EventSinkInvoke(Sender: TObject; DispID: Integer;',[BstrName]);
+          AddToImplementation('  const IID: TGUID; LocaleID: Integer; Flags: Word; Params: tagDISPPARAMS;');
+          AddToImplementation('  VarResult, ExcepInfo, ArgErr: Pointer);');
+          AddToImplementation('begin');
+          AddToImplementation('  case DispID of');
+          AddToImplementation(FEventImplementations[idx]);
+          AddToImplementation('  end;');
+          AddToImplementation('end;');
+          AddToImplementation('');
+          end;
+        end
+      else if sDefEvents<>'' then //add event implementations
+        begin
+        AddToImplementation('constructor T%s.Create(TheOwner: TComponent);',[BstrName]);
+        AddToImplementation('begin');
+        AddToImplementation('  inherited Create(TheOwner);');
+        AddToImplementation('  OnInvoke:=EventSinkInvoke;');
+        AddToImplementation('  fServer:=Co%s.Create;',[BstrName]);
+        AddToImplementation('  Connect(fServer,%s);',[FEventDisp[idx]]);
+        AddToImplementation('end;');
+        AddToImplementation('');
+        AddToImplementation('procedure T%s.EventSinkInvoke(Sender: TObject; DispID: Integer;',[BstrName]);
+        AddToImplementation('  const IID: TGUID; LocaleID: Integer; Flags: Word; Params: tagDISPPARAMS;');
+        AddToImplementation('  VarResult, ExcepInfo, ArgErr: Pointer);');
+        AddToImplementation('begin');
+        AddToImplementation('  case DispID of');
+        AddToImplementation(FEventImplementations[idx]);
+        AddToImplementation('  end;');
+        AddToImplementation('end;');
+        AddToImplementation('');
+        end;
       TI.ReleaseTypeAttr(TA);
       TI.ReleaseTypeAttr(TA);
       end;
       end;
     end;
     end;
@@ -1088,7 +1329,7 @@ begin
   FUses.Add('Windows');
   FUses.Add('Windows');
   FUses.Add('ActiveX');
   FUses.Add('ActiveX');
   FUses.Add('Classes');
   FUses.Add('Classes');
-  FUses.Add('OleServer');
+  //FUses.Add('OleServer');
   FUses.Add('Variants');
   FUses.Add('Variants');
   AddToInterface('Const');
   AddToInterface('Const');
   AddToInterface('  %sMajorVersion = %d;',[BstrName,LA^.wMajorVerNum]);
   AddToInterface('  %sMajorVersion = %d;',[BstrName,LA^.wMajorVerNum]);
@@ -1247,11 +1488,23 @@ begin
   FImplementation:=TStringList.Create;
   FImplementation:=TStringList.Create;
   FUses:=TStringList.Create;
   FUses:=TStringList.Create;
   FTypes:=TStringList.Create;
   FTypes:=TStringList.Create;
+  FEventDisp:=TStringList.Create;
+  FEventIID:=TStringList.Create;
+  FEventSignatures:=TStringList.Create;
+  FEventFunctions:=TStringList.Create;
+  FEventProperties:=TStringList.Create;
+  FEventImplementations:=TStringList.Create;
   try
   try
     DoImportTypeLib;
     DoImportTypeLib;
     If (OutputFileName<>'') then
     If (OutputFileName<>'') then
       UnitSource.SaveToFile(OutputFileName);
       UnitSource.SaveToFile(OutputFileName);
   finally
   finally
+    FreeAndNil(FEventImplementations);
+    FreeAndNil(FEventProperties);
+    FreeAndNil(FEventFunctions);
+    FreeAndNil(FEventSignatures);
+    FreeAndNil(FEventIID);
+    FreeAndNil(FEventDisp);
     FreeAndNil(FTypes);
     FreeAndNil(FTypes);
     FreeAndNil(FUses);
     FreeAndNil(FUses);
     FreeAndNil(FInterface);
     FreeAndNil(FInterface);