-2

I am trying to create an application with 2 forms in Delphi XE6. Depending on a ParamStr setting Form2 may or may not be shown before Form1.

In a quick test app both forms are created before Form1.Show is invoked - during which Form2 is shown or not

procedure TForm1.FormShow(Sender: TObject);
begin
  if ParamStr(1) = 'foo' then
      Form2.FooShow;
end;

procedure TForm2.FooShow;
begin
   ShowModal;
end;

However in the "real" application I am seeing a different behaviour.

In this case Form1.Show is being called as soon as Application.CreateForm(TForm1, Form1) is called. This is before Form2 is being created, which is causing problems as Form2 doesn't exist when it is needed.

Any explanation why the behaviour would differ? Am I missing a setting buried somewhere in Project>Options

Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
Dan Kelly
  • 2,634
  • 5
  • 41
  • 61
  • I've recreated the application using fresh Forms and it's now behaving as expected - there certainly seems to be a setting that's snuck into the original somewhere – Dan Kelly Jun 30 '14 at 12:03
  • As I pointed out in my [answer](http://stackoverflow.com/a/24488482/224704): the setting that "snuck in" is the `Visible` property on `Form1`. I doubt you wrote additional code to explicitly show the form when created, otherwise you would have solved you problem far more easily. This leaves the only thing that will cause a form to be shown as soon as it's created is if the property `Visible = True` at design time. – Disillusioned Jun 30 '14 at 15:39
  • Visible is set to true in the "working" version of the application. – Dan Kelly Jul 01 '14 at 08:22
  • 1
    You claim: "_Visible is set to true in the "working" version of the application_." To put it bluntly that's **absolute rubbish**! Unless there is something very significant you neglected to mention about your "working" quick test, going to `Form1` and setting `Visible=True` in the _design-time property editor_ **will cause an access violation** when `TForm1.FormShow` attempts to show `Form2`. I can only assume you mistakenly think Visible was true because `Form1` was automatically shown when you ran the app. **REMINDER**: The main form is always shown automatically, even if Visible is false. – Disillusioned Jul 01 '14 at 18:26
  • Dan, seriously try following **your own instructions** in your question, **AND** set Visible=True in `Form1`'s ***property editor at design time***. You will observe that: **(1)** `Form1` is shown as soon as it's created. **(2)** I.e. Before `Form2` is created. **(3)** And this will cause an access violation if `TForm1.FormShow` attempts to show `Form2`. – Disillusioned Jul 01 '14 at 18:30
  • Craig - you're right - and apologies - Visible is set to True in the "broken" version. – Dan Kelly Jul 03 '14 at 09:47

1 Answers1

3

If your form is persisted with Visible set to True, then it will be shown as soon as it's created.

Setting the property to False should resolve your problem.

EDIT

PS: Just in case someone with a similar problem has their main form unexpectedly show even though Visible is set to False. This happens because by default the application will show the main form regardless of its Visible property in the call to Application.Run.
If so, the following question should help: How can I start Delphi application with the hidden main form?

EDIT2

For the sake of completeness, there are a couple other things that could cause a form to be shown as soon as it's created. However, these probably aren't applicable to this specific question.

  • Any code that explicitly shows the form when it's created (such as the OnCreate event) would obviously cause the form to be shown. However, one would hope that such actions don't lead to these kinds of questions.
  • An MDI child form can never be hidden. At best it can be minimised.

TIP

The quickest way to finding the answer to such questions is usually just a little bit of debugging.

  • Set a break-point in your FormShow method.
  • Go to Compiler Settings, and enable the option to build with debug DCU's. (You'll want to see the VCL code.)
  • Rebuild and run your application.
  • When you get to your break-point, open the Call Stack debug window.
  • Navigate the call-stack looking for the trigger.

In this case you should have found the following code in Forms.pas.

procedure TCustomForm.DoCreate;
begin
  //...
  if fsVisible in FFormState then Visible := True; //<-- The trigger
end;

And a little more investagation on fsVisible would reveal the root cause as: The Visible property is set to True.


That said, you don't want to be coding this way because you're creating dependencies via globals. This is error-prone; and your little experiment shows shows just one of many subtle things that can cause problems.

Rather avoid the globals with something like the following changes in your DPR:

begin
  Application.Initialize;
  ShowForms;
end;

Where ShowForms is implemented as:

procedure ShowForms;
var
  LForm1: TForm1;
  LForm2: TForm2;
begin
  Application.CreateForm(TFrom1, LForm1);
  Application.CreateForm(TFrom2, LForm2);

  if (ParamStr(1) = 'foo') then
    LForm2.Show
  else
   LForm1.Show;
end;

If you don't have any dependencies between the forms, the above will suffice. If you do have a dependency, e.g. Form2 uses Form1: then you can explicitly pass a reference after creating the forms, bu before you start doing anything with them.

//Define a property on TForm2 E.g.
property MainForm: TForm1 read FMainForm write SetMainForm;

//Immediately after creating both forms tell form2 which to use as its main form.
LForm2.MainForm := LForm1;
Community
  • 1
  • 1
Disillusioned
  • 14,635
  • 3
  • 43
  • 77
  • Thanks Craig. This is a secondary Form that is set to Showmodal during the OnShow of the Main Form, but is normally `Visible = False` – Dan Kelly Jun 30 '14 at 12:02
  • @DanKelly Your comment makes me wonder whether you understood my answer? You asked why your production `Form1` would be shown as soon as it is created. ***It will be if it is set to `Visible = True` at deisgn time***. The only time I referred to your secondary form was in the second part of my answer to suggest a less error-prone way of determining whether to show Form2. I.e. one that won't trigger an AV even if `Form1` is shown as soon as it's created. – Disillusioned Jun 30 '14 at 12:54
  • In the "working" version of the application Form1 only shows (and I expect this) **after** Form2 (showing Modally) has been dismissed. – Dan Kelly Jul 01 '14 at 08:21