Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 812
James Avatar asked Feb 13 '12 18:02

James


2 Answers

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.
like image 60
Ken White Avatar answered Sep 23 '22 14:09

Ken White


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.
like image 35
Francesca Avatar answered Sep 23 '22 14:09

Francesca