James
James

Reputation: 133

Correct way to destroy a form and show another in Delphi

Currently in my program I have a Startup form, and a Main form. The startup form shows for a second or two.

Right now, I have the following code within a timer:

  frmStartup.Destroy;

  frmMain := TfrmMain.Create(Self);
  frmMain.Show;

Right now, I'm not sure if this is the correct way to do it.. It works, but when calling application.Terminate(); I receive an access violation message, leading my to believe that I have done something wrong in the destruction of the startup form..

If anyone could show the the correct procedure for doing what I want (non-modally) It would be greatly appreciated.

Thanks in advance,

EDIT:

Thanks for all the feedback, I fixed my access violations by simply adding the code:

  Action := caFree;

Into the frmStartup.formClose method.

Upvotes: 6

Views: 10379

Answers (4)

slumpmax
slumpmax

Reputation: 1

Set frmMain as Main Form

On frmMain.FormCreate

frmStartup := TfrmStartup.Create(nil);
try
  frmStartup.ShowModal;
finally
  frmStartup.Free;
end;

Upvotes: 0

Francesca
Francesca

Reputation: 21640

You may want to have your Splash Screen showing up as early as possible, so ideally it should be done during the initialization phase, then it should disappear only when the MainForm is ready to take over.

That's exactly what we do in our application where we reuse the About dialog as a splash screen then release it when the MainForm steals the focus.

In the dpr, as high as possible in the uses clause after the needed VCL/RTL units:

  f_adtDlgAbout in 'f_adtDlgAbout.pas' {frmDlgAbout}, // ASAP to be used as a Splash screen

The About unit (FYI, FormStyle is fsStayOnTop and Position is poScreenCenter):

unit f_adtDlgAbout;

[...]

type
  TfrmDlgAbout = class(TForm)

[...]

procedure TfrmDlgAbout.SplashFormDeactivate(Sender: TObject);
begin
  Release;
end;

initialization
  // Use it as a Splash screen
  with TfrmDlgAbout.Create(nil) do begin
    AlphaBlend := True;
    AlphaBlendValue := 208;
    BorderStyle := bsNone;
    btnOK.Visible := False;
    OnDeactivate := SplashFormDeactivate;
    Show;
    Update;
  end;
end.

Upvotes: 4

Erik Knowles
Erik Knowles

Reputation: 1007

TFrmMain.Create(Self)??? What is "Self"? Are you doing that from inside frmStartup? If so, don't. Use TFrmMain.Create(NIL).

Use frmStartup.Release to release frmStartup, if all of the code you sent is inside a method of frmStartup, you need to put that line at the bottom of the method.

Upvotes: 1

Ken White
Ken White

Reputation: 125698

Don't create the frmStartup using Application.CreateForm. The first form created there becomes your application's main form, and if that's frmStartup you're destroying it outside Application knowledge.

Instead, use a normal Form.Create in your project source (.dpr) file:

var
  frmStartup: TfrmStartup;

begin
  Application.Initialize;
  Application.MainFormOnTaskBar := True;
  frmStartup := TfrmStartup.Create(nil);  // No owner assigned here!
  frmStartup.Show;
  frmStartup.Update;

  Application.CreateForm(TfrmMain, frmMain); // Let Application have this for main form
  // Delay here if needed
  frmfrmStartup.Free;
  Application.Run;
end.

Upvotes: 8

Related Questions