views:

344

answers:

4

This should be a simple one for someone. I just can't figure out how to do it.

Upon exiting of my program, I want to hide the main form and make a final "Thank You" form appear on its own, like this:

procedure TMainForm.ExitExecute(Sender: TObject);
begin
  MainForm.Visible := false;
  ThankYouForm.Show;
  MainForm.Close;
end;

But when I do that, I get the Exception:

EInvalid Operation: Cannot change Visible in OnShow or OnHide

So how do I show a final form, while hiding the main form when exiting a program in Delphi?


Conclusion: Mghie confirmed that what I was trying was correct and should have worked. That indicated that I had a bug somewhere in my procedures of exiting and closing from my forms that was bringing up this exception.

Now that I know that, it won't take me long to find and fix the problem.


Found the problem: I was closing my main form from within the ThankYouForm, and that somehow looped back through into ExitExecute and, well, it got all bunged up.

But all's well again. The MainForm.Hide before the ThankYouForm.ShowModal works perfectly.

Thanks again, guys.

+4  A: 

You could do that in the OnClose handler of the main form. Be sure to ShowModal the other form, because otherwise it will be closed immediately when the closing of the main form terminates the application:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Hide;
  with TThankYouForm.Create(nil) do try
    ShowModal;
  finally
    Free;
  end;
  Action := caFree;
end;

or even

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Hide;
  with TThankYouForm.Create(Application) do
    ShowModal;
  Action := caFree;
end;

And be sure to make the behaviour optional - when the user closes the app they are finished with it, and not everybody is pleased with programs that are so reluctant to go away.

Edit:

OK, showing such a form at the end of the trial period does indeed make sense. And while I can't really say why your code raises the exception - you should be able to find out by compiling with debug DCUs, setting a breakpoint on the line that raises the exception, and examine the stack trace. I assume some combination of the form properties and your code leads to another change of the Visible property higher up the stack, and you need to find out what it is and correct that. The code above should really work.

mghie
No. That code gives the same exception I mentioned above. It is putting the "Hide;" in there that causes it.
lkessler
Then it's something that is in your code, which I can't really comment on. Above code works in a test app, try it.
mghie
The intention is to use this after a person's trial has expired and they've closed the program for the last time. It will bring up a box thanking them, and asking them if they have any feedback or would like an extention to the trial.
lkessler
If you've verified that it works okay in your test app, then I agree it is me. I shall try to find my problem. Thanks.
lkessler
+11  A: 

Instead of trying to shoehorn something into the main form, go to the place where you know everything else is finished running: the point where Application.Run returns. Create a new procedure that creates, shows, and destroys your farewell form, and then call it in your DPR file like this:

begin
  Application.Initialize;
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;
  TThankYouForm.Execute;
end.

The display function can be along the lines of what Mghie's answer demonstrated:

class procedure TThankYouForm.Execute;
begin
  with Create(nil) do try
    ShowModal;
  finally
    Free;
  end;
end;
Rob Kennedy
Thank you, Rob. That is a nice way to always display a final form. I am actually conditionally executing the ThankYouForm based on a IsLastRun variable from the MainForm, so that would mess this method up a bit.
lkessler
So store your condition somewhere else.
Rob Kennedy
A: 

I would put (try) any of the code supplied above in the main form's OnCloseQuery event. Ensure that can close := false until you are ready to close the main form.

JohnJ
A: 

This may be caused by difference between order of method calls with order of message handler processing. After your method has completed there are still messages in operating system queue and they are being dispatched and handled by VCL.

RocketSurgeon