Search code examples
delphipropertiesintrospectionevent-handlingdelphi-6

Is there a way to auto-assign a dynamically created component's event handlers in Delphi 6?


I have a design and run-time component that contains a large number of event handlers. I'll call it TNewComp for now. I create an instance of TNewComp on a TForm and fill in the event stubs with specific code via the property editor at design time, and realize I would like to be able to create new instances of TNewcomp that use the current set of event handler code.

To do this now, I call TNewComp's constructor and then "manually" assign each of the new instance's event handlers the corresponding event stub code resident on the form that contains the TNewComp instance created at design time. So if I have an instance of TNewComp assigned to a variable named FNewComp on a form called TNewForm, for each event handler I would do:

FNewComp.onSomething = TNewform.onSomething
(... repeat for each event handler belonging to TNewComp ...)

This works fine, but it is cumbersome and worse, if I add a new event handler to TNewComp, I have to remember to update my "newTComp()" function to make the event handler assignment. Rinse and repeat this process for every unique component type that I create new instances of dynamically.

Is there way to automate this process, perhaps using property inspection or some other Delphi 6 introspection technique?

-- roschler


Solution

  • I used the following code. Be careful with the Dest owner when creating, the safest way is to pass Nil and free the component by yourself later.

    implementation uses typinfo;
    
    procedure CopyComponent(Source, Dest: TComponent);
    var
      Stream: TMemoryStream;
      TypeData : PTypeData;
      PropList: PPropList;
      i, APropCount: integer;
    begin
      Stream:=TMemoryStream.Create;
      try
        Stream.WriteComponent(Source);
        Stream.Position:=0;
        Stream.ReadComponent(Dest);
      finally
        Stream.Free;
      end;
    
      TypeData := GetTypeData(Source.ClassInfo);
      if (TypeData <> nil) then
      begin
        GetMem(PropList, SizeOf(PPropInfo)*TypeData^.PropCount);
        try
          APropCount:=GetPropList(Source.ClassInfo, [tkMethod], PropList);
          for i:=0 to APropCount-1 do
            SetMethodProp(Dest, PropList[i], GetMethodProp(Source, PropList[i]))
        finally
          FreeMem(PropList);
        end;
      end;
    end;