richard
richard

Reputation: 25

Child form must not overlap its parent

We have a Delphi app (XE8) that I recently found out runs almost perfectly on wine (OSX 10.6), except for one thing. Say the user selects a menu option on the main form that opens another form (like 'File|New ...'). The new form shows, and partially covers the main form. The problem is there is no way to get the first form to come back to the top. Clicking on the main form does not bring it back on top of the child form like it does in windows. If two child forms are showing, again, clicking on one child does not bring it to the foreground--it seems to be focusable (you can drag it if you can get a hold of it), but whatever part of it is covered by another form remains covered

This behavior occurs both when we use the winebottler and when we use the crossover app.

Are we missing some library in the bottling process? Or maybe just completely misunderstanding how 'windows' works on OSX? Is our windows app poorly designed? Do we need to redesign the app to just use one form (and launch everything using tabs instead of forms)?

Edit: Here is a sample delphi project that illustrates the issue

program ProjectM;

uses
  Vcl.Forms,
  Unit1m in 'Unit1m.pas' {fmain},
  Unit2m in 'Unit2m.pas' {form2m},

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := False;
  Application.CreateForm(Tfmain, fmain);

  Application.CreateForm(Tform2m, form2m);

  Application.Run;
end.

In unit1 we have a button to launch the second form

procedure Tfmain.Button1Click(Sender: TObject);
begin
  form2m.show
end;

Run the .exe, the main form shows; press the button: The new form overlays the main form.

In windows, click the title bar of the main form--it comes back to the foreground.

In winebottler, click the title bar of the main form, it does not come back up; even tho it looks like the title bar gets focused, the rest of the form is still hidden--see screenshot

enter image description here

Upvotes: 0

Views: 524

Answers (1)

Johan
Johan

Reputation: 76753

Ownership
The problem is that your second form is owned by the mainform.
Owned windows always appear on top of their owners.

Set the ownership manually
The solution is to change the ownership of the second form.

First you need to disable the automatic creation of the second form and do everything manually:

In the menu choose:
Project -> Options -> Forms Select your form2 and move it from the auto create to the available forms.

enter image description here

Now you need to create the form:

procedure Tfmain.FormCreate(Sender: TObject);
begin
  Form2:= TForm2.Create(Application); 
end;

Wine naughtyness
You can force the WndParent of the new form to be 0 by interposing a CreateParams like so:

unit Unit2m;
interface

type 
  TForm2Interposer = class(TForm)
    procedure CreateParams(var Params: TCreateParams); override;
  end;

  TForm2m = class(TForm2Interposer)
  ....
implementation

procedure TForm2Interposer.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := 0;
end;

Showing the form
Note that the owner is Application not your main form. Application is a hidden form that Delphi uses for bookkeeping. Both your mainform and form2 now have Application as their owner. And they have exactly equal status as far as Z-order is concerned.

procedure Tfmain.Button1Click(Sender: TObject);
begin
  form2m.show
end;

No cleanup needed
You've manually created the form, so your instinct would be to manually destroy the form, however because Application is the owner of the form. It will take care of the cleanup, so you don't have to.

procedure Tfmain.FormDestroy(Sender: TObject);
begin
  //Form2.Free;  <<-- The owner does the cleanup.
end;

Now whatever window you select will come out on top.

Remarks
This has nothing to do with MainFormOnTaskbar it is simple Windows behavior: an owned window always appears on top of its owner.

Upvotes: 1

Related Questions