Jump to content

if possible load dfm files at runtime using ObjectTextToBinary ?


KingOrmon

Recommended Posts

Hello,

 

I would like to load DFM files at runtime, for allows me modify uniforms without recompile.

 

I am trying to load without succes via this function:

procedure LoadComponentFromFile(Component: TComponent; const FileName: TFileName);
var
  FileStream : TFileStream;
  MemStream : TMemoryStream;
  i: Integer;
begin
  MemStream := nil;

  if not Assigned(Component) then
    raise Exception.Create('Component is not assigned');

  if FileExists(FileName) then
  begin
    FileStream := TFileStream.Create(FileName,fmOpenRead);
    try
      for i := Component.ComponentCount - 1 downto 0 do
      begin
        if Component.Components[i] is TControl then
          TControl(Component.Components[i]).Parent := nil;
        Component.Components[i].Free;
      end;

      MemStream := TMemoryStream.Create;
      ObjectTextToBinary(FileStream, MemStream);
      MemStream.Position := 0;
      MemStream.ReadComponent(Component);
      Application.InsertComponent(Component);
    finally
      MemStream.Free;
      FileStream.Free;
    end;
  end;
end;
Link to comment
Share on other sites

  • 8 years later...
  • 3 months later...
On 3/20/2023 at 3:21 AM, Luis German said:
Hi:
Following the links and writing a similar scenery on unigui, I got an Access violation message error when readcomponent function is called.

I Attached the code, a text with saved form, and a picture where the function is called.

Thanks for your help.-

Luis.

Readcomponent.png

Basico.zipUnavailable forma1.txtUnavailable

 

Your samples is unavailable.

Please retry upload files again.

 

Link to comment
Share on other sites

I did it in a different way

I created a form changer
I'm still going to adapt it to Unigui but I believe it's simple

see the code below


Procedure P_ObjListaLayoutCtrl(FormSelf: TForm_HostBase; SalvarLer: String; ListObjetos: TStrings; DiminuirScala: Boolean = True; Modified: Boolean = False);
Var I: Integer;
Var aHeightScala, aWidthScala: Double;
Var Linha, aNameComp, aNameForm, aPropComp, aValorComp: String;
Var aComp: TControl;
Var ctx: TRttiContext;
Var Prop: TRttiProperty;
Var varPropInfo: PPropInfo;

 Function F_AnchorsToString(Tipo: TAnchorKind): String;
 Begin
  Result := 'False';

  if akLeft = Tipo Then Begin
   if akLeft in aComp.Anchors Then
    Result := 'True'
   Else
    Result := 'False';
  End;

  if akTop = Tipo Then Begin
   if akTop in aComp.Anchors Then
    Result := 'True'
   Else
    Result := 'False';
  End;

  if akRight = Tipo Then Begin
   if akRight in aComp.Anchors Then
    Result := 'True'
   Else
    Result := 'False';
  End;

  if akBottom = Tipo Then Begin
   if akBottom in aComp.Anchors Then
    Result := 'True'
   Else
    Result := 'False';
  End;

 End;

begin
 // Button1:Width=150
 Try

  if SalvarLer = 'L' then Begin

   if Trim(ListObjetos.Text) = EmptyStr then
    Exit;

   For I := 0 To ListObjetos.Count - 1 do Begin
    Linha := ListObjetos.Strings[I];

    if (Pos('[', Linha) > 0) And (Pos(']', Linha) > 0) then Begin
     aNameForm := Copy(Linha, 2, Pos(']', Linha) - 2);
     Break;
    End;

   End;

   if aNameForm <> FormSelf.ClassName Then Begin
    ShowDialog(FormSelf, 'Esse Arquivo de DFM "' + aNameForm + '" Não corresponde a esse Form "' + FormSelf.ClassName + '"');
    Exit;
   End;

   For I := 0 To ListObjetos.Count - 1 do Begin
    Linha := ListObjetos.Strings[I];

    aNameComp := Copy(Linha, 1, Pos(':', Linha) - 1);
    aPropComp := Copy(Linha, Pos(':', Linha) + 1, (Pos('=', Linha)) - Pos(':', Linha) - 1);
    aValorComp := Copy(Linha, Pos('=', Linha) + 1, 999);

    if Trim(aNameComp) <> EmptyStr then Begin

     aComp := TControl(FormSelf.FindComponent(aNameComp));

     if Not Assigned(aComp) Then
      continue;

     if Modified Then Begin
      aComp.Tag := -3377;
      continue;
     End;

     if aPropComp = 'Align' Then
      aComp.Align := TAlign(StrtointDef(aValorComp, 0));

     if aPropComp = 'Parent' Then Begin
      if (aValorComp = FormSelf.Name) Or (aValorComp = F_ClassNameForm(FormSelf)) then
       aComp.Parent := FormSelf
      Else
       aComp.Parent := {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF}(FormSelf.FindComponent(aValorComp));

      if Not Assigned(aComp.Parent) Then
       aComp.Parent := F_GetPanelParentNil(FormSelf);
     End;

     if aPropComp = 'Left' Then
      aComp.Left := StrToInt(aValorComp);

     if aPropComp = 'Top' Then
      aComp.Top := StrToInt(aValorComp);

     if aPropComp = 'Height' Then
      aComp.Height := StrToInt(aValorComp);

     if aPropComp = 'Width' Then
      aComp.Width := StrToInt(aValorComp);

     if aComp is {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF} Then Begin
      if aPropComp = 'TabOrder' Then
       {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF}(aComp).TabOrder := StrtointDef(aValorComp, 0);

      if (aPropComp = 'TabStop') And (Trim(aValorComp) <> EmptyStr) Then Begin
       if aValorComp = 'True' Then
        {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF}(aComp).TabStop := True
       Else
        {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF}(aComp).TabStop := False;
      End;
     End;

     if (aPropComp = 'akLeft') And (Trim(aValorComp) <> EmptyStr) Then Begin
      if aValorComp = 'True' Then
       aComp.Anchors := aComp.Anchors + [akLeft]
      Else
       aComp.Anchors := aComp.Anchors - [akLeft];
     End;

     if (aPropComp = 'akTop') And (Trim(aValorComp) <> EmptyStr) Then Begin
      if aValorComp = 'True' Then
       aComp.Anchors := aComp.Anchors + [akTop]
      Else
       aComp.Anchors := aComp.Anchors - [akTop];
     End;

     if (aPropComp = 'akRight') And (Trim(aValorComp) <> EmptyStr) Then Begin
      if aValorComp = 'True' Then
       aComp.Anchors := aComp.Anchors + [akRight]
      Else
       aComp.Anchors := aComp.Anchors - [akRight];
     End;

     if (aPropComp = 'akBottom') And (Trim(aValorComp) <> EmptyStr) Then Begin
      if aValorComp = 'True' Then
       aComp.Anchors := aComp.Anchors + [akBottom]
      Else
       aComp.Anchors := aComp.Anchors - [akBottom];
     End;

     if (aPropComp = 'Caption') And (Trim(aValorComp) <> EmptyStr) Then Begin
      if aComp is TButton then
       TButton(aComp).Caption := aValorComp;

      if aComp is TLabel then
       TLabel(aComp).Caption := aValorComp;
     End;

     if aPropComp = 'PageIndex' Then Begin
      if (aComp is TTabSheet) And (StrtointDef(aValorComp, -1) > -1) then
       if (TPageControl(TTabSheet(aComp).Parent).PageCount - 1) >= (StrtointDef(aValorComp, 0)) Then
        TTabSheet(aComp).PageIndex := StrtointDef(aValorComp, 0);
     End;

    End;

   End;
  End;

  if SalvarLer = 'S' then Begin

   if FormSelf is TForm_HostDae then Begin
    {$IFDEF VCL}
    aHeightScala := TForm_HostDae(FormSelf).LfResizerVcl.HeightScala;
    aWidthScala := TForm_HostDae(FormSelf).LfResizerVcl.WidthScala;
    {$ELSE}
    {$ENDIF}
   End
   Else Begin
    aHeightScala := 1;
    aWidthScala := 1;
   End;

   ListObjetos.Clear;
   ListObjetos.Add('[' + FormSelf.ClassName + ']');

   For I := 0 To FormSelf.ComponentCount - 1 do Begin
    if (FormSelf.Components[I] is TControl) And (TControl(FormSelf.Components[I]).Tag = -3377) then Begin
     aComp := {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF}(FormSelf.Components[I]);

     if Not Assigned(aComp) Then
      continue;

     if Assigned(aComp.Parent) Then
      ListObjetos.Add(aComp.Name + ':Parent=' + aComp.Parent.Name)
     Else
      ListObjetos.Add(aComp.Name + ':Parent=Nil');

     if Assigned(aComp.Parent) Then Begin
      Prop := ctx.GetType(aComp.ClassType).GetProperty('Caption');
      if (Assigned(Prop)) and (Prop.Visibility in [mvPublic, mvPublished]) then
       ListObjetos.Add(aComp.Name + ':Caption=' + Prop.GetValue(aComp).Asstring);
     End;

     ListObjetos.Add(aComp.Name + ':Align=' + IntToStr(Integer(aComp.Align)));

     ListObjetos.Add(aComp.Name + ':Left=' + Floattostr(F_GetTamOriginal(aComp.Left, aWidthScala, DiminuirScala)));
     ListObjetos.Add(aComp.Name + ':Top=' + Floattostr(F_GetTamOriginal(aComp.Top, aHeightScala, DiminuirScala)));
     ListObjetos.Add(aComp.Name + ':Height=' + Floattostr(F_GetTamOriginal(aComp.Height, aHeightScala, DiminuirScala)));
     ListObjetos.Add(aComp.Name + ':Width=' + Floattostr(F_GetTamOriginal(aComp.Width, aWidthScala, DiminuirScala)));

     ListObjetos.Add(aComp.Name + ':akLeft=' + F_AnchorsToString(akLeft));
     ListObjetos.Add(aComp.Name + ':akTop=' + F_AnchorsToString(akTop));
     ListObjetos.Add(aComp.Name + ':akRight=' + F_AnchorsToString(akRight));
     ListObjetos.Add(aComp.Name + ':akBottom=' + F_AnchorsToString(akBottom));

     if aComp is {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF} Then Begin
      ListObjetos.Add(aComp.Name + ':TabOrder=' + IntToStr({$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF}(aComp).TabOrder));

      if {$IFDEF VCL} TWinControl {$ELSE} TUniControl {$ENDIF}(aComp).TabStop Then
       ListObjetos.Add(aComp.Name + ':TabStop=True')
      Else
       ListObjetos.Add(aComp.Name + ':TabStop=False');
     End;

     if aComp is TTabSheet Then
      ListObjetos.Add(aComp.Name + ':PageIndex=' + IntToStr(TTabSheet(aComp).PageIndex));

    End;
   End;
  End;

 except
  on E: Exception do begin
   P_LogException(E); // Mudo
  end;
 end;

End;

 

Change Forms.png

Unit_LayoutControl.pas Unit_LayoutControl.dfm

Link to comment
Share on other sites

  • 4 weeks later...
On 7/5/2023 at 5:05 PM, asapltda said:

+1

 

Guys sorry for the delay
Very correct the migration from 500,000 to unigui is not easy

no time to create a Demo.
I'll explain better

 

procedure TForm_CadastroTipoProduto.FormCreate(Sender: TObject);
begin
 F_LayoutControl(Self, 'L');

end;

procedure TForm_CadastroTipoProduto.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 F_LayoutControl(Self, 'S');
 
end;

another reason for the delay is that it is still not working 100%
in this way attached version 100% unigui

Note these forms are the VCL standard
as my system is Hybrid I transform from VCL to Unigui in the compilation, so colleagues will have to make the necessary changes.

Unit_LayoutControl.pas Unit_LayoutControl.dfm VCL_UniGUI.Inc Funcoes.pas

Link to comment
Share on other sites

Hello!  i use two functions:

function LoadDFM(p :TComponent; dfm :TStringList) :string;
var
   MemoryStream, FileStream :TMemoryStream;
begin
             MemoryStream := TMemoryStream.Create();
             FileStream   := TMemoryStream.Create();

             dfm.SaveToStream(FileStream);
             FileStream.Position := 0;

             ObjectTextToResource(FileStream, MemoryStream);

             MemoryStream.Position := 0;
             MemoryStream.ReadComponentRes(p);

             MemoryStream.Destroy();
             FileStream.Destroy();

             Result := p.Name;
end;

function SaveDFM(p :TComponent) :TStringList;
var
    MemoryStream, FileStream :TMemoryStream;
begin
     MemoryStream := TMemoryStream.Create;
     FileStream   := TMemoryStream.Create;

     MemoryStream.WriteComponentRes('aaa', p);
     MemoryStream.Position := 0;

     ObjectResourceToText(MemoryStream, FileStream);

     FileStream.Position := 0;

     Result := TStringList.Create;
     Result.LoadFromStream(FileStream);

     MemoryStream.Destroy;
     FileStream.Destroy;
end;

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...