2

in my project i have two form's(form1,form2), form1 is configuration form.

i want to show Form1 and when we click Button1 then show Form2 and free(Release) Form1. how can to i do this?

i use this code. but this project start and then exit automatically.A Friend said because the application message loop never start, and application terminates because main form does not exist. how i can to solve this problem?

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Application.CreateForm(TForm2, Form2);
  Release;
end;

///

program Project1;
uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Form1:= TForm1.Create(Application);
  Application.Run;
end.
return
  • 1,049
  • 5
  • 17
  • 27
  • I think you asked same question here: http://stackoverflow.com/questions/4623345/how-i-can-to-destoryfree-a-form-from-memory If you have additional information or comment about this question so you must write there... – SimaWB Jan 07 '11 at 20:46
  • @SimaWB: Yes i ask same question at that link. but some Friend's said to me you must ask a "new" question!!! you can read comment's at that link. – return Jan 07 '11 at 20:53
  • 1
    @SimaWB to be fair to Hamidm, he's only following the instructions of Rob Kennedy which was to post a new question on exactly this subject. I don't think this is the same question as before. – David Heffernan Jan 07 '11 at 20:54

3 Answers3

7

Do exactly what you asked in the question title: Create and show the configuration form, and then create and show the main form. The trick is in how you create them. Only use Application.CreateForm for the one form that you want to be your main form. Use the ordinary object creation technique for all other forms.

Modify your DPR file like so:

var
  ConfigForm: TConfigForm;
begin
  Application.Initialize;

  ConfigForm := TConfigForm.Create(nil);
  try
    if ConfigForm.ShowModal <> mrOK then
      exit;
  finally
    ConfigForm.Free;
  end;

  Application.CreateForm(TMainForm, MainForm);
  Application.Run;
end.
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • @Rob: I put your code in my DPR file but i have received a Error message at line "if not ConfigForm.ShowModal then" with this text: "[DCC Error] Project1.dpr(11): E2076 This form of method call only allowed for class methods" Why?? – return Jan 07 '11 at 21:25
  • Is `ConfigForm` the name of a *class* or the name of a *variable*? In my code, it's the name of a variable. In yours, the error message suggests it's the name of a class. Or maybe it's the name of a unit. – Rob Kennedy Jan 07 '11 at 21:28
  • I change your code to this but i already get that Error.(in my project form1 is configuration form and form2 is main form).Here is my modified code: Application.Initialize; Form1 := TForm1.Create(nil); try if not (Form1.ShowModal) then exit; finally Form1.Free; end; Application.CreateForm(Form2, TForm2); Application.Run; – return Jan 07 '11 at 21:31
  • @Hamidm - Switch the form class and variable reference: `Application.CreateForm(TForm2, Form2)`. See the [documentation](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Forms_TApplication_CreateForm.html). – Sertac Akyuz Jan 08 '11 at 01:48
  • +1, not using `Application.CreateForm()` for splash or any other forms that are to appear before the main form is the correct solution. – mghie Jan 08 '11 at 11:38
  • Just for the records: ShowModal doesn't return a Boolean. The code should be changed to 'if ConfigForm.ShowModal <> mrOK then'. This will also require to use Controls and in TConfigForm ModalResult has to be set accordingly when clicking the button or closing the form otherwise. Perhaps ignoring the result of ShowModal is sufficient for the application. – Uwe Raabe Jan 09 '11 at 15:42
0

You need to create Form2 first and this will be your main form. You want it to start hidden and be shown after Form1 has done its job. Something like this:

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.Show;
  Release;
end;

///

program Project1;
uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};
{$R *.res}
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm2, Form2);
  Form2.Hide;
  Form1 := TForm1.Create(Application);
  Form1.Show;
  Application.Run;
end.

The reason is that the app terminates when your main form closes. And your main form is typically the first one that you create.

jachguate
  • 16,976
  • 3
  • 57
  • 98
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • @David: i received a Error message in Delphi XE when i use your code. "[DCC Error] Project1.dpr(13): E2010 Incompatible types: 'class of TComponent' and 'TApplication'". Why?? – return Jan 07 '11 at 21:11
  • The main form is the first you create trough Application.CreateForm() method, but you can create any number of no-main forms via TxxxForm.Create() at any moment. – jachguate Jan 07 '11 at 21:35
  • @Hamidm: You got the error because the Application.CreateForm call was bad, but you must be able to fix it if you try to understand what's going on first. – jachguate Jan 07 '11 at 21:36
  • @Hamidm Yeah I was just writing off the top of my head without a compiler at hand! @jachguate thanks for fixing it up for me! – David Heffernan Jan 07 '11 at 22:48
  • @jachguate: When i use your code and i start my project, then both forms(form1,form2) are show, form2 is not hide. – return Jan 08 '11 at 06:42
  • Yes, not using `Application.CreateForm()` for splash or any other forms that are to appear before the main form is the correct solution. However, look at the solution by Rob to see that yours is more complex than required. – mghie Jan 08 '11 at 11:42
0

You can prohibit Form1 to be shown by setting ShowMainForm to false. Leave the code in the DPR just as the IDE creates it:

uses
  Forms,
  Unit2 in 'Unit2.pas' {Form2},
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

In the FormCreate event of Form2 just set ShowMainForm to false and call Show to make Form2 visible:

procedure TForm2.FormCreate(Sender: TObject);
begin
  Application.ShowMainForm := False;
  Show;
end;

and in the ButtonClick event of Form2 show Form1 and close Form2:

procedure TForm2.Button1Click(Sender: TObject);
begin
  Form1.Show;
  Close;
end;

This keeps all necessary changes inside unit2.

Edit Some remarks that came to mind after sleeping a night over it:

  1. Form2 should be the last one auto-created, i.e. the one directly before the Application.Run statement.
  2. The Form1.Show statement in the ButtonClick event should be moved to the FormClose event. Thus the user can close the form with the Windows close button or whatever he likes best.
  3. If for some reason Form1 should never be shown, some code must be added to close the application. A Halt may serve here.
Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
  • -1, not using `Application.CreateForm()` for splash or any other forms that are to appear before the main form is the correct solution. – mghie Jan 08 '11 at 11:38
  • Please clarify: Why do you rate this solution as not correct? It does exactly what the question asks for (tested with XE). In addition it keeps the DPR clean from any manual changes. Shall your comment imply there is only "one" correct solution to this problem? – Uwe Raabe Jan 08 '11 at 13:56
  • @Uwe: I don't think the solution is wrong, but it is (IMHO of course) ugly and more complicated than necessary. In other words not as helpful as Rob's solution. All three answers had 0 votes yesterday, my votes put them into the order I thought most useful to anyone looking for a simple solution to this problem. – mghie Jan 09 '11 at 12:14
  • @mghie: Well, I won't start to argue about taste here. Only this: 1) my solution requires changes in TForm2 only, 2) when you change 'Form1.Show' to 'Application.MainForm.Show' it will work with every mainform just by adding the form to the project and auto create it, and (last not least) 3) it works out of the box (what cannot be said from the other solutions). Sorry, but that doesn't look that ugly to me. – Uwe Raabe Jan 09 '11 at 15:48
  • @Uwe: I still think that Rob's code perfectly implements what the OP requires, and that having more than one call to `Application.CreateForm()` is misguided and unnecessary. Anyway, I don't want to argue about taste here either, so not voting on your answer would have been better - but it's too late to change that now. My apologies, I don't agree with your reasoning, but voting down was probably too heavy-handed. – mghie Jan 09 '11 at 17:03
  • Re 3): Rob's code works out of the box too, and it perfectly conveys its meaning to the reader. – mghie Jan 09 '11 at 17:04
  • Rob's code doesn't even compile - see my comment to his answer. – Uwe Raabe Jan 09 '11 at 18:23