Recent

Author Topic: Free TControl created at runtime  (Read 782 times)

TomTom

  • Full Member
  • ***
  • Posts: 170
Free TControl created at runtime
« on: November 27, 2022, 12:08:48 pm »
Hello :)
I'm creating TEdit with code (it's used to edit some TLabels caption). How do I free it after the editing is done? Everything is working fine except freeing created TEdit. I could hide it and disable it but that's not what I would Like.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.CreateLabelEditBox(aObject:TControl; aOnEditingDone: TNotifyEvent);
  2. begin
  3.   edLabelEdit:=TEdit.Create(self);
  4.   edLabelEdit.Left:=aObject.Left;
  5.   edLabelEdit.Top:=aObject.top;
  6.   edLabelEdit.BorderStyle:=bsNone;
  7.   edLabelEdit.Height:=aObject.Height;
  8.   edLabelEdit.Width:=aObject.Width;
  9.   edLabelEdit.Color:=RGBToColor(100,100,100);
  10.   edLabelEdit.OnEditingDone:=aOnEditingDone;
  11.   edLabelEdit.Font:=aObject.Font;
  12.   edLabelEdit.Parent:=self;
  13.   edLabelEdit.SetFocus;
  14. end;
  15.  

In some Label OnClick event:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.lbPlatformClick(Sender: TObject);
  2. begin
  3. CreateLabelEditBox(lbPlatform,@DoSomething2);
  4.  
  5. end;  
  6.  

And DoSomething2() procedure.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.DoSomething2(Sender: TObject);
  2. begin
  3.   Memo1.lines.add('Ok Editing done');
  4.   edLabelEdit.Free;
  5. end;  
  6.  


« Last Edit: November 27, 2022, 12:28:12 pm by TomTom »

wp

  • Hero Member
  • *****
  • Posts: 11832
Re: Free TControl created at runtime
« Reply #1 on: November 27, 2022, 01:39:50 pm »
Is it necessary to destroy the TEdit when editing is done? Simply hiding or disabling it would be much simpler.

Basically you destroy a control by calling its Free method: edLabelEdit.Free. If, however, there is a chance that the control will be used later, e.g. by calling CreateLabelEditbox again, you must set edLabelEdit to nil after destruction, in short: FreeAndNil(edLabelEdit). Note that in every access to it you must check against nil.

Setting the variable to nil is particularly important when you create the instance with an owner like you do. Your "edLabelEdit := TEdit.Create(self)" makes the form ("self") the owner of the edLabelEdit, and thus the form automatically destroys the edit when the form itself is destroyed. But when you destroyed the edit yourself during the lifetime of the application and did not set it to nil the form will still attempt to destroy it again - and your application will crash, because the variable edLabelEdit points to invalid memory.

You should also protect the procedure CreateLabelEditBox from creating the edLabelEdit a second time:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.CreateLabelEditBox(aObject:TControl; aOnEditingDone: TNotifyEvent);
  2. begin
  3.   if edLabelEdit = nil then
  4.     edLabelEdit:=TEdit.Create(self);
  5.   edLabelEdit.Left:=aObject.Left;
  6.   edLabelEdit.Top:=aObject.top;
  7.   edLabelEdit.BorderStyle:=bsNone;
  8.   edLabelEdit.Height:=aObject.Height;
  9.   edLabelEdit.Width:=aObject.Width;
  10.   edLabelEdit.Color:=RGBToColor(100,100,100);
  11.   edLabelEdit.OnEditingDone:=aOnEditingDone;
  12.   edLabelEdit.Font:=aObject.Font;
  13.   edLabelEdit.Parent:=self;
  14.   edLabelEdit.SetFocus;
  15. end;

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Free TControl created at runtime
« Reply #2 on: November 27, 2022, 03:52:11 pm »
Quote
But when you destroyed the edit yourself during the lifetime of the application and did not set it to nil the form will still attempt to destroy it again - and your application will crash, because the variable edLabelEdit poin

  I don't see this happening. When you destroy a child control, an owned control, it normally removes it from the list of owned control of the current owner.
 
  I do this all the time where I may or may not destroy the control and the owner will handle this action just fine.

  Unless something has changed? I still use older Laz among testing with the trunk.

The only true wisdom is knowing you know nothing

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: Free TControl created at runtime
« Reply #3 on: November 27, 2022, 04:07:12 pm »
I don't know if I get it right... So in edLabelEdit.onEditingDone procedure I should do it like this?

This does nothing to me. It didn't give me an error but edLabelEdit is still present on Form and is still functional.  How do I remove it completly from form?
Code: Pascal  [Select][+][-]
  1. procedure TForm1.DoSomething(Sender: TObject);
  2. begin
  3.   Memo1.lines.add('Done somethin');
  4.   edLabelEdit:=nil;
  5.   edLabelEdit.free;
  6. end;
  7.  

wp

  • Hero Member
  • *****
  • Posts: 11832
Re: Free TControl created at runtime
« Reply #4 on: November 27, 2022, 04:29:26 pm »
Quote
But when you destroyed the edit yourself during the lifetime of the application and did not set it to nil the form will still attempt to destroy it again - and your application will crash, because the variable edLabelEdit poin
  I don't see this happening. When you destroy a child control, an owned control, it normally removes it from the list of owned control of the current owner.
Your're right.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.DoSomething(Sender: TObject);
  2. begin
  3.   Memo1.lines.add('Done somethin');
  4.   edLabelEdit:=nil;
  5.   edLabelEdit.free;
  6. end;
  7.  
First Free, then nil:
Code: Pascal  [Select][+][-]
  1. ]procedure TForm1.DoSomething(Sender: TObject);
  2. begin
  3.   Memo1.lines.add('Done somethin');
  4.   edLabelEdit.free;
  5.   edLabelEdit:=nil;
  6. end;
  7. // or
  8. ]procedure TForm1.DoSomething(Sender: TObject);
  9. begin
  10.   Memo1.lines.add('Done somethin');
  11.   FreeAndNil(edLabelEdit);
  12. end;
  13.  

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: Free TControl created at runtime
« Reply #5 on: November 27, 2022, 04:49:55 pm »
@wp This gives me an error. I have no trouble freeing controls placed when designing a form but for some reason I can't free anything created in code.
Well there is something wrong in my code, because in fresh project there is no problem at all...
EDIT
I've added sample project
« Last Edit: November 27, 2022, 05:25:55 pm by TomTom »

wp

  • Hero Member
  • *****
  • Posts: 11832
Re: Free TControl created at runtime
« Reply #6 on: November 27, 2022, 05:27:13 pm »
You are destroying the Edit within its OnEditingDone event where it is still needed (e.g. focus change). Use Application.ReleaseComponent(edLabelEdit) instead which is called when all running activities are finished.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.DoSomething2(Sender: TObject);
  2. begin
  3.   Memo1.lines.add('Ok Editing done');
  4.   Application.ReleaseComponent(edLabelEdit);
  5. end;

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: Free TControl created at runtime
« Reply #7 on: November 27, 2022, 07:12:18 pm »
Do I have to make something afterwards? I mean free something or destroy or everything is ok after Application.ReleaseComponent(edLabelEdit); I still can get text from edLabelEdit.text after ReleaseComponent even though it's not visible.

EDIT
Or I'll rather try to use on TKeyEvent and after user presses ENTER KEY it will free the edLabelEdit... Well I did just that and it also doesn't work :P
« Last Edit: November 27, 2022, 07:22:06 pm by TomTom »

wp

  • Hero Member
  • *****
  • Posts: 11832
Re: Free TControl created at runtime
« Reply #8 on: November 27, 2022, 07:19:43 pm »
For me, the application crashes when I call "ShowMessage(edLabelEdit)". You can add an "edLabelEdit := nil" after calling Application.ReleaseComponent to zero the variable.

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: Free TControl created at runtime
« Reply #9 on: November 27, 2022, 07:43:34 pm »
Ok. I'm giving up for now. I'll add this TEdit at design and I'll be turning it's visibility and readonly and changing it's top and left instead of creating and freeing each time new control...

wp

  • Hero Member
  • *****
  • Posts: 11832
Re: Free TControl created at runtime
« Reply #10 on: November 27, 2022, 07:47:37 pm »
Ok. I'm giving up for now. I'll add this TEdit at design and I'll be turning it's visibility and readonly and changing it's top and left instead of creating and freeing each time new control...
Good idea. That's the way the StringGrid does it...

TomTom

  • Full Member
  • ***
  • Posts: 170
Re: Free TControl created at runtime
« Reply #11 on: November 27, 2022, 08:09:07 pm »

Good idea. That's the way the StringGrid does it...
Really? It's TEdit? I'm using TStringGrid in 99% of my apps and I didn't know. So it's basicly instering TEdit in a cell every time Edit mode is turned on?

 

TinyPortal © 2005-2018