Solved

Freeing components

Posted on 2000-03-27
17
253 Views
Last Modified: 2010-04-04
I create a components at run time such as Memos, labes, and even forms. I make the owner and parent of these component a Form. When I close this form (Not a main form) I free all component that I was created at run-time, but when I close the main form and my application terminated (And when the owner of these component destroyed) Access violation exception alwyas raised.

I think the owner only who must destroy it's components, and when it find it is already destroyed it will rais the exception. In my application I need to destroy that component when I close that form, and I create new ones when I open that form again.

The only thing that I can do now is to assign Visible property of these components to False when I close the form, it works very well but the problem is that will consume memory resource. Is there any safe freeing for such components?

Motaz
www.geocities.com/motaz1
0
Comment
Question by:Motaz
  • 5
  • 4
  • 2
  • +5
17 Comments
 
LVL 13

Expert Comment

by:Epsylon
ID: 2663142
You don't have to free the components on that form. They will be freed automatically when the form is destroyed since the form is their owner.
Btw, use TForm.Release to free the form.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2663145
You don't have to free the components on that form. They will be freed automatically when the form is destroyed since the form is their owner.
Btw, use TForm.Release to free the form.
0
 
LVL 6

Expert Comment

by:Jaymol
ID: 2663260
I get this problem too Motaz.  I usually find that Whatever.Destroy is a little less volatile than .Free, but still has the same problems sometimes.

Worth a try anyway.

John.
0
 

Expert Comment

by:vinnair
ID: 2663343
Have you written some code in the formdestroy event or the form close event of the main form as well as the component owner form. If yes, please post that code.
0
 
LVL 2

Expert Comment

by:Tussin
ID: 2663345
If you want to safe memory, you can create components with owner=nil, So you can free them properly.

Another issue is "don't forget to set all events back to nil".
Normally when you create component at runtime, you often set its event right?
Before free them, set it back to nil first.
0
 
LVL 7

Author Comment

by:Motaz
ID: 2663386
To Tussin
>create components with owner=nil

Can I create Memo without Onwer?

To Vinnair
I write code in OnClose event at the parent form which deletes all created components at run-time.

To Epsylon:
What exactly Realease do? I do not want to lose the parent form, even I do not want to free all it's components, only I need to free some components (which created at run-time)

Motaz
0
 

Expert Comment

by:omeralfaroug
ID: 2663415
hi
 i don't understand " A componentS" and
"Labes" tell me the meaning and i will answered u.
omeralfaroug
0
 
LVL 7

Author Comment

by:Motaz
ID: 2663446
To Omer:
I mean control components such as Labels and Memos

Azzoz
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 2

Expert Comment

by:florisb
ID: 2663768
question is probably answered, but:

write some procedures that you can use to place controls on certain possitions, you could use the tag to be able to find those controls again, or to use one onclick event and check the Sender's tag there. To make this a bit more comfortable, you could add adssociate property's to controls, to be able to fill a list that belongs with a button or something.

Had problems with free's run-time generated controls, too. Tussin: owner nil! Offcourse.

saw this too:
  if assigned(MyRegel.VarControl1) then
      begin
      MyRegel.VarControl1.free;
      MyRegel.VarControl1 := nil;
      end;


procedure placeSomeControl(AParent: TWinControl; x: integer);
var
  CheckboxHaakjeOpen: TUMSAdvancedCheckbox;
  begin
  ///
  checkboxHaakjeOpen := TUMSAdvancedCheckbox.Create(Aparent);
  checkboxHaakjeOpen.parent := Aparent;
  checkboxHaakjeOpen.Left := left1;
  checkboxHaakjeOpen.top := firstspace + ((x - 1) * linespace) + 1;
  checkboxHaakjeOpen.width := checkwidth;
  checkboxHaakjeOpen.Caption := '(';
  checkboxHaakjeOpen.regelnummer := x;
  checkboxHaakjeOpen.enabled := false;
  checkboxHaakjeOpen.checked := true;
  end;

Floris.
0
 
LVL 6

Expert Comment

by:DrDelphi
ID: 2664898
Another thing that I am suprised that no-one else mentioned is that you would want to free these controls in the OnCloseQuery event of the form rather than the OnClose. This way you can test to see if all components=nil prior to passing true to the CanClose parameter.
0
 
LVL 7

Author Comment

by:Motaz
ID: 2667928
Is this code can solve my problem:

for i:= 0 to Components.Count - 1 do
  if TControl(Components[i]).Tag = 255 then
begin
  Components[i].Free;
  Components[i]:= nil;
end;

Is that a right code?

0
 
LVL 2

Expert Comment

by:florisb
ID: 2668672
I do think so (that's what I posted)... ...but I'm no 'Delphi docter'...:-)

Floris
0
 
LVL 2

Expert Comment

by:Tussin
ID: 2672257
To Motaz,
   In case that I want dynamic array of component, I normally create component with Owner=nil and free them whenever I want. It works well.
   This is a sample. (don't forget to set event back to nil, otherwise sometimes it will become Access Violation)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

const MAXMEMO=8;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure MemoClick(Sender: TObject);
  private
    { Private declarations }
    MemoList:array[0..MAXMEMO-1] of TMemo;
    MemoCount:Integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  MemoCount:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if MemoCount=MAXMEMO then
    exit;
  MemoList[MemoCount]:=TMemo.Create(nil);
  with MemoList[MemoCount] do
  begin
    Parent:=Self;
    Left:=MemoCount*40;
    Top:=MemoCount*40;
    OnClick:=MemoClick;
  end;
  Inc(MemoCount);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if MemoCount=0 then
    exit;
  with MemoList[MemoCount-1] do
  begin
    OnClick:=nil;
    Free;
  end;
  Dec(MemoCount);
end;

procedure TForm1.MemoClick(Sender: TObject);
begin
  ShowMessage('Click Click');
end;

end.
0
 
LVL 7

Author Comment

by:Motaz
ID: 2677432
Tussin, what kind of components can I create without having an owner or parent, my componets which cause the problem is Visual components such Lebels, and Memos, so that can I create it without owner or parent?
0
 
LVL 2

Accepted Solution

by:
Tussin earned 25 total points
ID: 2678748
I cut this message from delphi help. (topic "TComponent.Create")

For components created manually, that is, not created in the form designer, call Create and pass in an owner componentas the AOwner parameter. The owner will dispose of the component when the owner is destroyed. If the component is not owned, then call Free so that it is destroyed.

That means, all object which inherit from TComponent can be created properly with owner=nil, and you have to call method "Free" by yourself.

you can test on my previous sample.
0
 
LVL 7

Author Comment

by:Motaz
ID: 2679016
Tussin, what about MDI child forms, I think it must has an owner, isn't it?
0
 
LVL 2

Expert Comment

by:Tussin
ID: 2679196
Normally, all forms is created with owner=Application and will be free before terminate a program.

This is an example of MDIChild form creation.
procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMDIChild;
begin
  { create a new MDI child window }
  Child := TMDIChild.Create(Application);
  Child.Caption := Name;
end;
That means this form will be free automatically when application is terminated.

you can safe memory by using Event OnFormClose.

TForm provides a variable "Action" in OnFormClose event, if you set it to "cafree", it will free itself after close form

procedure TMDIChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

Anyway you can create MDIChild windows with Owner=nil.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now