Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

auto-create form question. 3

Status
Not open for further replies.

pierrotsc

Programmer
Nov 25, 2007
358
0
0
US
Is it best to have the form auto created at run time or have them created on the fly when you need them?
What are the advantages or drawback to have them created automaticcaly?
Thanks.
P
 
Memory is allocated for all forms as they are created, so if you auto create all your application's forms at start up, then you're using that memory. Creating a form dynamically, when needed, saves memory.

Also, I put all my initialization code in my formcreate, or at the end of the unit. If you have the form auto created, then this initialization code only runs once rather than every time you make the form visible. So if you want the form to always start in the same state, you either dynamically create it, or you have to clean up after every operation to put it back.

If you need multiple copies of the same form available, then dynamically creating it obviously makes more sense.

For large applications, auto creating all the forms up front just does not make sense.
 
One big advantage of dynamically creating forms is that you can create multiple instances of them. I've built an instant messaging system, where you can have numerous PM windows open at a time.

JD Solutions
 
Ok, so i assume that when you say dynamically, you mean on demand, that means when you need the form.
So i have a code saying:
if form=nil then form:=tform.create;
Form.show;

in the onclose event of the form, i have form:=nil;

Am i doing it right?
Thanks.
 
In the onClose event of your dynamically created form you should put:

Code:
action := caFree;

That frees the memory associated with your form. Setting the variable to nil, does not. You just lose the reference to the form, and can never recover the memory after that.

Also, since your checking to see if the form variable is nil, I assume you want to limit the application to just one instance of a form. A better way to limit this is to define a "class procedure or function" in the form itself. The interesting thing about class methods, is that the form does not need to exist to call it. So, you can ask the form, do you exist, if not, create it.

So in your dynamically created form add a method to the public section, add the method to the implementation section.

Code:
unit second;

interface

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

type
  TForm2 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
    class function FormExists:  Boolean;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

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

class function TForm2.FormExists: Boolean;
var
   F: TForm2;
   I: Integer;
begin
   F := nil;
   for i := Screen.FormCount - 1 DownTo 0 do
    if (Screen.Forms[i].Name = 'Form2') then
       F := Screen.Forms[I] As TForm2;
   if F = nil then
      Result := False
   else
      result := True;
end;

end.

Then from the main form, you call the class function (make sure you add the unit where Form2 is declared to the uses clause).

Code:
uses Form2Unit;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
   Child:  TForm2;
begin
   if Not TForm2.FormExists then
   begin
      Child := TForm2.Create(Application);
      Child.Show;
   end;
end;
 
I should add a warning about using a class method. Don't make the mistake of accessing variables/methods of the form itself. Since you can call a class method even if the form doesn't exist, you'll get an access violation if you attempt to.
 
the action := cafree; causes a crash when i close the form. I had tried that. Maybe because all my forms are fsnormal formstyle. I do not use fsmdichild.
So i am not sure that the code above will work. Maybe i am using the wrong approach and my main form should be a style of mdiform instead.
What is the best way to do it?
Pierrot
 
i think i know why i get the crash if i use action:=cafree;
by looking at your code i had form:=tform.create(nil); instead of form:=tform.create(application);

which one should i use? the form i create only need one instance. when they are closed, they are not needed anymore.
thanks.
 
Neither way should crash the program.

Where do you have Action := caFree?

It should be in the OnClose Method of the form itself.

Also, make sure you aren't setting the form var to nil before the onclose event fires.
 
Another way, if you need the form to run modally, is like:

Code:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
   fForm2:  TForm2;
begin
   fForm2 := TForm2.Create(Application);
   try
      //here you can initialize form variables
      fForm2.ShowModal;
      //here you can read data from the form
   finally
      fForm2.Free;
   end;
end;
 
If i create form:=tform.create(nil);
form.show;

Then i have action:=cafree; in the onclose event of the form, it crashes.. if i have tform.create(application), it does not..Wonder why..

Thanks for all the tips..
 
Interesting..

The parameter sets the object's parent. I've always set it to Application, but I always thought nil would also work.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top