How to create an object by its "string" class name ? lazarus / 64-FPC development ---------------------------------------------------------------------- izd · 2017-03-07 17:40 Hi everybody !  I would like to found out an easy way to create an object by its class name from a string. It should look like : Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  obj: TObject;   obj := BuildObject( 'TButton', Self ); Of course, the NOT easy way is to cast the class name... nb: For now, my interest is about controls (cf. Self) Thank you in advance ---------------------------------------------------------------------- Thaddy · 2017-03-07 17:57 This is not a scripting language but probably the RTTI lovers  will give you an elaborate  answer on how exactly you can do that.   (And it's a bad idea) ---------------------------------------------------------------------- marcov · 2017-03-07 18:08 Afaik VCL classes are registered, so something like getclass('TButton').create(selfl); ---------------------------------------------------------------------- izd · 2017-03-07 18:11 Thank you mates  @marcov: Unfortunately, its not works... ---------------------------------------------------------------------- Thaddy · 2017-03-07 18:29 They are only registered when used somewhere. Otherwise you have to register them by hand. (code reduction) ---------------------------------------------------------------------- izd · 2017-03-07 18:33 This is what I thought after searching the web... ---------------------------------------------------------------------- sky_khan · 2017-03-07 19:29 Notice that, this is not thread-safe but it provides you a way to use classes you want, without interfering streaming of components Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit ControlReg; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Controls, fgl; type  TClassMap = specialize TFPGMap;   { TControlRegistry }   TControlRegistry = class(TClassMap)  public    procedure RegisterControl(aClass:TControlClass);    procedure RegisterControls(aClassArr : array of TControlClass);    function CreateControl(const aClassName:string;aOwner:TComponent):TControl;  end;    function ControlRegistry : TControlRegistry; implementationuses  rtlconsts; var  FReg : TControlRegistry; function ControlRegistry : TControlRegistry;begin  if FReg=nil then    FReg :=TControlRegistry.Create;  Result:=FReg;end; { TControlRegistry } procedure TControlRegistry.RegisterControl(aClass: TControlClass);begin  Add(aClass.ClassName,aClass);end; procedure TControlRegistry.RegisterControls(aClassArr: array of TControlClass);var  aClass : TControlClass;begin  for aClass in aClassArr do    RegisterControl(aClass);end; function TControlRegistry.CreateControl(const aClassName: string;  aOwner: TComponent): TControl;var  Ndx : Integer;begin  Ndx:=IndexOf(aClassName);  if Ndx>=0 then    Result:=Data[Ndx].Create(aOwner)  else    raise EClassNotFound.CreateFmt(SClassNotFound, [AClassName]);end; initializationfinalization  FReg.Free;end.  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses ControlReg; procedure TForm1.Button1Click(Sender: TObject);begin  with ControlRegistry.CreateControl('TEdit',Self) do    Parent:=Panel1;end; constructor TForm1.Create(aOwner: TComponent);begin  inherited Create(aOwner);  ControlRegistry.RegisterControls([TMemo,TButton,TEdit,TLabel]);end; ---------------------------------------------------------------------- Remy Lebeau · 2017-03-07 19:34 Quote from: marcov on March 07, 2017, 07:08:56 pm Afaik VCL classes are registered, so something like getclass('TButton').create(selfl); GetClass() returns a general purpose TPersistentClass (aka 'class of TPersistent').  You have to type-cast it in order to call the virtual TComponent.Create() constructor: Code: [Select]var   Btn: TButton; begin   Btn := TButton(TComponentClass(GetClass('TButton')).Create(Self)); end; Alternatively: Code: [Select]type   TButtonClass = class of TButton; var   Btn: TButton; begin   Btn := TButtonClass(GetClass('TButton')).Create(Self); end; Just make sure the desired classes are registered at runtime, either by the RTL itself when initializing packages, or explicitly in code: Code: [Select]RegisterClass(TDesiredControlHere); ---------------------------------------------------------------------- bylaardt · 2017-03-07 22:16 No magic: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function BuildControl(Const ObjectClass:String;ObjectOwner:TComponent):TwinControlbegin  case LowerCase(ObjectClass) of    'tbutton' : result:=TButton.create(ObjectOwner);    'tlabel'  : result:=TLabel.create(ObjectOwner);    'tedit'   : result:=TEdit.create(ObjectOwner);    'tmemo'   : result:=TMemo.create(ObjectOwner);    // and so on  else     raise Exception.create(ObjectClass+' not allowed in BuilControl');  end;end; ---------------------------------------------------------------------- izd · 2017-03-08 18:18 So.....no magic....(sic) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function BuildControl( const pClassName: String ): TObject;begin  case pClassName of    'TButton'  : Result := TButton.Create( nil );    .../... and so on .../...  end;end; Thank you all friends  ps: if someone found out the way to do so, I'll take it ---------------------------------------------------------------------- Ñuño_Martínez · 2017-03-09 10:33 May be you can use an array of a record to store the classes.  Something like: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   TYPE  { Any component. }    ClassType = CLASS OF TComponent;   { Stores class information. }    TClassListItem = RECORD      Name: STRING;      TheClass: ClassType;    END;   VAR    ClassList: ARRAY [...] OF TClassListItem;   BEGIN  { Add class information. }    ClassList[0].Name := 'TButton';    ClassList[0].TheClass := TButton;...  { Searchs "ClassName" and creates "TheObject" }    FOR Ndx := LOW (ClassList) TO HIGH (ClassList) DO      IF ClassName = ClassList[Ndx].ClassName THEN        TheObject := ClassList[Ndx].TheClass.Create (SELF)  END; I didn't test actually so may be it doesn't work at all. ---------------------------------------------------------------------- marcov · 2017-03-09 11:26 If you use LCL you might as well use the fact that such array/tlist already exist, see Remy's answer. ---------------------------------------------------------------------- Ñuño_Martínez · 2017-03-11 17:42 Quote from: marcov on March 09, 2017, 12:26:08 pmIf you use LCL you might as well use the fact that such array/tlist already exist, see Remy's answer. I see.  Didn't knew that.