1

I've created an SDI application using the Delphi Berlin VCL template. I can create additional instances by programming File|New as follows:

procedure TSDIAppForm.FileNew1Execute(Sender: TObject);
var
   LNewDoc: TSDIAppForm;
begin
   LNewDoc := TSDIAppForm.Create(Application);
   LNewDoc.Show;
end;

Only the owner form shows on the taskbar. Also, closing the owner form closes all the instances. How do I unlink the additional instances so that they operate independently and show individually on the taskbar?

RRUZ
  • 134,889
  • 20
  • 356
  • 483
Duns
  • 418
  • 2
  • 15
  • Possible duplicate of [How can I get taskbar buttons for forms that aren't the main form?](http://stackoverflow.com/questions/5493591/how-can-i-get-taskbar-buttons-for-forms-that-arent-the-main-form) – Remy Lebeau Jun 17 '16 at 20:41
  • Not entirely a duplicate because I was also asking about how to get multiple SDIAppForms that operate independently. – Duns Jun 18 '16 at 05:30
  • Duplicate of [Delphi, how to make independent windows](https://stackoverflow.com/questions/2618372/delphi-how-to-make-independent-windows/2619792#2619792) – Zoë Peterson Jun 20 '16 at 16:18

1 Answers1

4

Closing the TForm that is assigned as the Application.MainForm exits the app, that is by design.

If you want the MainForm to act like any other SDI window and be closed independently without exiting the app if other SDI windows are still open, you will have to create a separate TForm to act as the real MainForm and then hide it from the user (set Application.ShowMainForm to false at startup before Application.Run() is called), and then you can create TSDIAppForm objects as needed. When the last TSDIAppForm object is closed, you can then close the MainForm, or call Application.Terminate() directly, to exit the app.

To give each TSDIAppForm its own Taskbar button, you need to override the virtual CreateParams() method:

How can I get taskbar buttons for forms that aren't the main form?

Try this:

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMyRealMainForm, MyRealMainForm);
  Application.CreateForm(TSDIAppForm, SDIAppForm);
  SDIAppForm.Visible := True;
  Application.ShowMainForm := False;
  Application.Run;
end.

procedure TSDIAppForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent := 0;
end;

procedure TSDIAppForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TSDIAppForm.FormDestroy(Sender: TObject);
begin
  if Screen.FormCount = 2 then // only this Form and the MainForm
    Application.Terminate;
end;

procedure TSDIAppForm.FileNew1Execute(Sender: TObject);
var
  LNewDoc: TSDIAppForm;
begin
  LNewDoc := TSDIAppForm.Create(Application);
  LNewDoc.Show;
end;
Community
  • 1
  • 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Developing my SDI program a bit further, I added a TAdvStringGrid from TMS Software and saw that this resulted in the creation of two additional forms. So terminating the application when Screen.FormCount reduced to 2 no longer worked. I therefore modified FormDestroy as follows: `procedure TSDIAppForm.FormDestroy(Sender: TObject); var I: Integer; NumAppSDIForms: Integer; begin NumAppSDIForms := 0; for I := 0 to Screen.FormCount - 1 do if Screen.Forms[I].UnitName = 'SDIMAIN' then Inc(NumAppSDIForms); if NumAppSDIForms = 1 then Application.Terminate; end;` – Duns Jun 19 '16 at 01:22
  • @Duns you have the right jist. I would use `if Screen.Forms[i] is TSDIAppForm then`, though. – Remy Lebeau Jun 19 '16 at 03:29