Jump to content
JohnLM

Is it possible to copy all properties from one TMemo to a dynamically created TMemo?

Recommended Posts

Specs:  XE7, VCL, Win7 

 

I have a Panel with a TabControl in it and a Memo inside the first TabSheet on a Form that was all created and configured during design time.  And, on the Form in another Panel, I have a [Add] button to dynamically create a new TabSheet and Memo. 


The main Memo is the default with all the settings that I would like the dynamically created Memos to have.  But setting up all the necessary properties would be tedious and if I change something in the main Memo at design-time, I may not remember to update that to the dynamic ones.   

 

var
  Form1: TForm1;
  idx: integer=0; // index numb, for adding new tabs to the pagecontrol.

procedure TForm1.btnAddClick(Sender: TObject);
var
  TabSheet: TTabSheet;
  memo: TMemo;
begin
  inc(idx);
  TabSheet := TTabSheet.Create(PageControl1);
  TabSheet.Caption := 'Untitled-'+idx.ToString;
  TabSheet.PageControl := PageControl1;

  memo := tmemo.Create(pagecontrol1);
  // settings section
  memo.Color := $0017110D;
  memo.Align := alClient;
  .
  .
  .
  // end of settings section
  memo.Parent := tabsheet;
  memo.Show;
  memo.SetFocus;
end;

note: I have a lot more properties than what is posted above. 


Is there a better way to copy all the properties of the main Memo to the dynamically created ones and how can I do this?
 

Edited by JohnLM
updated missing code fragment

Share this post


Link to post
1 hour ago, JohnLM said:

if I change something in the main Memo at design-time, I may not remember to update that to the dynamic ones.

So don't set them at design-time; Set them at run-time in a function that will then also be used setup the other memos.

 

There aren't that many properties on a TMemo so I really don't think it's worth it to try and be clever here but if you really want to you can either use RTTI or streaming (see TStream.WriteComponent/ReadComponent). If your memo use event handlers you will get into trouble with the stream method.

Share this post


Link to post

Keep it simple - create a class helper for TMemo and add an Assign method and just set the props you need. This will be quicker and easier than messing with RTTI (which can be a bit of a rabbit hole with some property types).

  • Like 1

Share this post


Link to post
19 hours ago, Vincent Parrett said:

Keep it simple - create a class helper for TMemo and add an Assign method and just set the props you need. This will be quicker and easier than messing with RTTI (which can be a bit of a rabbit hole with some property types).

This is the way.

 

Share this post


Link to post

Update on my progress. . . 
 

You guys can do this!  I have no doubt!  I know you all can figure this out, lickady-split or a few minutes, but I am not in your category.  I am just a lowly hobbiest at best. 


Unfortunately, I am no component expert, nor am I am Pro at Pascal programming, let alone OOP and all. I am just a casual guy who codes small Windows utilities and other fun and interesting things. Occasionally I will try and learn OOP and component anything but I do not get very far, as I am a very slow learner.  
Anyway. I have looked into the suggestions here, and also my own searches. 


I found some resources and spent a great deal of time trying to understand them and then build them, but to no avail. I am just a complete failure in these advanced areas. 


For instance, in one resource (web search) I did find a routine that shows how to pull properties from all components on the form.  


And in another resource (web search) I found another routine showing how to pull properties similarly but slitely less detail.  


And yet in another resource showing similar, I can pull and narrow down to just tmemo's properties, which is just what I was looking for as a start. 


And then, in another resource, I found where I could: pull the properties of a tmemo and show it in another memo and make changes to the properties in that memo and the routine would show a memo with the changed state.  But, I could not get it to copy from another memo, its properties because it would issue an error: "memo has no parent window" and other errors as well.  I tried many scenarios of code ideas but to no avail. 


There is one more resource that I found (from the lazarus website) to try out, the next time I come back from a break from this endeavor.  


As for now and after three very long days and nights and many many hours, so many hours, of trying to figure this out, I am giving this up.  I am taking a break and going back to other projects.  

 

Thank you all for your suggestions. 

Share this post


Link to post
On 1/7/2025 at 3:11 PM, JohnLM said:

Is there a better way to copy all the properties of the main Memo to the dynamically created ones and how can I do this?

Yes - don't make a copy at all! Use a TFrame instead.
 

https://docwiki.embarcadero.com/RADStudio/en/Working_with_Frames

 

At design-time, create a new TFrame class, put a TMemo on it, and configure it as needed.  Then at runtime, you can create a new instance of your Frame class (which will have all of your design-time property values) and assign a Parent to it as needed.  In this case, a new TabSheet.

 

With this approach, you also won't need to waste a TabSheet at design-time just to hold your default values. But, if you really want to, you can place your Frame on the 1st TabSheet at design-time, too.

Edited by Remy Lebeau

Share this post


Link to post

Update on progress. . . continues. . . 

 

@Remy Lebeau, I have tried your suggestion.  And after many hours, I finally got it working, I think.  I never worked with Frames before.  I still don't understand them but in this case, I do believe I have it working, but with a few slight issues. 

 

1st, the code, now modified for Frame support: 

procedure TForm1.btnAddClick(Sender: TObject);
var
  TabSheet: TTabSheet;
  mem: unit2.TFrame2;
begin
  inc(idx);
  TabSheet := TTabSheet.Create(PageControl1);
  TabSheet.Caption := 'Untitled-'+idx.ToString;
  TabSheet.PageControl := PageControl1;
  mem := tframe2.Create(nil);
  mem.Parent       := tabsheet;
  mem.Name         := 'Untitled'+idx.ToString;
  mem.memo1.Align  := alClient;
  mem.memo1.Show;
  mem.memo1.SetFocus;
end;

And the results: 

 

2060238209_im-dyanmicallycreatedtabswithframessupport.png.faec7fd031dbb8b86217607bf4b8886c.png

 

As for the issues: 

 

1) all the tabs I create have the same name, "memo1".  (see code) 

2) the alignment to client is quirky, but I managed to get it to work to fill the tab area.  (see code) 

3) the memo's names (for each tab do not show up in the memo's view.  They all say the same thing, "memo1". (see code) 

   they should be "Untitled1, Untitled2, Untitled3, ..." in each memo, just like when you add a new memo to your form in the IDE. 
 

Share this post


Link to post

Instead of setting a unique name, you can set it to an empty string.

And what you show in the screen shot is not the memo's name but the memo's Lines property contents. You can set that easily to whatever you want either. Memo.Lines.Text := 'bla blub';

 

But that's not what was meant when you were told use frames:

 

Just design a frame the way you want it, and create multiple instances of that particular frame class.

Edited by dummzeuch

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×