Create DELPHI Component at Runtime

1
texto := 'object DWResponseTranslator1: TDWResponseTranslator ' +
  'ElementAutoReadRootIndex = True'+
  'ElementRootBaseIndex = -1'+
  'RequestOpen = rtGet'+
  'RequestInsert = rtPost'+
  'RequestEdit = rtPost'+
  'RequestDelete = rtDelete'+
  'FieldDefs = <'+  
  '  item'+
  '    FieldName = 'ID''+
  '    ElementName = 'ID''+
  '    ElementIndex = -1'+
  '    FieldSize = 6'+
  '    Precision = 0'+
  '    DataType = ovInteger'+
  '    Required = False'+
  '  end'+  
  'left = 288'+
  'top = 32'+
  'end';

novoComponente := Criar_Componente(Texto);

I have this structure copied from a designer componen is it possible with this text to create a delphi component at runtime ??

    
asked by anonymous 27.06.2018 / 23:13

3 answers

1

To create a component at runtime, I do this:

var
  DWResponseTranslator1: TDWResponseTranslator;
begin
  DWResponseTranslator1 := TDWResponseTranslator.Create({Aqui é necessário colocar os parâmetros de construção});
  DWResponseTranslator1.ElementAutoReadRootIndex := True;
  DWResponseTranslator1.ElementRootBaseIndex := -1;

  ...

end;

In the case of property FieldDefs a Field must be created at a time and add to FieldDefs .

    
27.06.2018 / 23:27
0

To extract the DFM code from a component:

function ComponentToStringProc(Component: TComponent): string;
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try
    StrStream := TStringStream.Create(s);
    try
      BinStream.WriteComponent(Component);
      BinStream.Seek(0, soFromBeginning);
      ObjectBinaryToText(BinStream, StrStream);
      StrStream.Seek(0, soFromBeginning);
      Result:= StrStream.DataString;
    finally
      StrStream.Free;
    end;
  finally
    BinStream.Free
  end;
end;

To create the component from the DFM code:

function StringToComponentProc(Value: string): TComponent;
var
  StrStream:TStringStream;
  BinStream: TMemoryStream;
begin
  StrStream := TStringStream.Create(Value);
  try
    BinStream := TMemoryStream.Create;
    try
      ObjectTextToBinary(StrStream, BinStream);
      BinStream.Seek(0, soFromBeginning);
      Result:= BinStream.ReadComponent(nil);
    finally
      BinStream.Free;
    end;
  finally
    StrStream.Free;
  end;
end;

To use do the following:

Get the DFM code of an Edit;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Text := ComponentToStringProc(Edit1);
end;

To create Edit from the obtained DFM:

procedure TForm1.Button7Click(Sender: TObject);
var
  EdtX: TEdit;
begin
  EdtX := StringToComponentProc(Memo1.Text) as TEdit;
  EdtX.Parent := Form1;
end;

In initialization register the TEdit class or the components you want.

initialization
  RegisterClass(TEdit);

Source: link

    
29.06.2018 / 16:40
0

Based on the pure string you can implement as the need for other classes to appear.

In the following example I'm considering creating a component based on TEdit just because it does not have this component that it showed in the question, but the idea is the same.

function TForm14.Criar_Componente(aComponente: String): TComponent;
var
  vComponente : TArray<String>;
begin
  aComponente := aComponente.Substring(0, aComponente.Length - 3);
  vComponente := aComponente.Split([' ']);

  if (vComponente[2] = 'TEdit') then
  begin
    TEdit(Result)          := TEdit.Create(Self);
    TEdit(Result).Parent   := Self;
    TEdit(Result).Name     := vComponente[1].Replace(':', EmptyStr);
    TEdit(Result).Left     := StrToInt(vComponente[6]);
    TEdit(Result).Top      := StrToInt(vComponente[10]);
    TEdit(Result).Width    := StrToInt(vComponente[14]);
    TEdit(Result).Height   := StrToInt(vComponente[18]);
    TEdit(Result).TabOrder := StrToInt(vComponente[22]);
    TEdit(Result).Text     := vComponente[26];
  end;
end;

The Split([' ']); will give you an Array of data, just take each position equivalent to each property, that is "procedural", I do not know any other way.

As the result of the function is a TComponente it will satisfy most classes.

You can create overloads for different classes if you wish.

To use enough:

var
  vComponente : TComponent;
const
  _COMPONENTE =   'object Lb_Teste: TEdit'+
                  '  Left = 402'+
                  '  Top = 8'+
                  '  Width = 225'+
                  '  Height = 21'+
                  '  TabOrder = 0'+
                  '  Text = ''Teste'+
                  'end';
begin
  vComponente := Criar_Componente(_COMPONENTE);
end;
    
29.06.2018 / 21:28