Child 表格不得与其 parent 重叠

Child form must not overlap its parent

我们有一个 Delphi 应用程序 (XE8),我最近发现它在 wine (OSX 10.6) 上运行几乎完美,除了一件事。假设用户在打开另一个窗体的主窗体上选择了一个菜单选项(如 'File|New ...')。新窗体显示并部分覆盖主窗体。问题是没有办法让第一个表格回到顶部。单击主窗体不会像在 windows 中那样将其返回到 child 窗体的顶部。如果显示两个 child 表单,再次单击一个 child 不会将其带到前台——它似乎是可聚焦的(如果你能抓住它,你可以拖动它),但它的任何部分被另一种形式覆盖仍然被覆盖

当我们使用 winebottler 和 crossover 应用程序时都会出现此行为。

我们在装瓶过程中是否遗漏了一些图书馆?或者可能只是完全误解了 'windows' 对 OSX 的作用?我们的 windows 应用程序设计不佳吗?我们是否需要重新设计应用程序以仅使用一种表单(并使用选项卡而不是表单启动所有内容)?

编辑:这是一个示例 delphi 项目来说明问题

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.

在单元 1 中,我们有一个启动第二个表单的按钮

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

运行.exe,主窗体显示;按下按钮:新窗体覆盖主窗体。

在windows中点击主窗体的标题栏--回到前台。

在winebottler中,点击主窗体的标题栏,没有回来;即使标题栏看起来像焦点一样,表单的其余部分仍然隐藏着——见截图

所有权
问题是您的第二个表单归主表单所有。
拥有的 windows 始终显示在其所有者之上。

手动设置所有权
解决方案是改变第二种形式的所有权。

首先您需要禁用第二个表单的自动创建并手动执行所有操作:

在菜单中选择:
项目 -> 选项 -> 表格 Select 您的 form2 并将其从自动创建移动到可用表单。

现在您需要创建表单:

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

酒调
您可以通过像这样插入 CreateParams 来强制新表单的 WndParent 为 0:

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;

显示表格
请注意,所有者 Application 不是您的主要表单。 Application 是 Delphi 用于簿记的隐藏形式。您的 mainform 和 form2 现在都有 Application 作为它们的所有者。就 Z 顺序而言,它们具有完全平等的地位。

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

无需清理
您已经手动创建了表单,所以您的直觉是手动销毁表单,但是因为 Application 是表单的所有者。它会负责清理工作,因此您不必这样做。

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

现在无论 window 你 select 都将名列前茅。

备注
这与 MainFormOnTaskbar 无关,它是简单的 Windows 行为:拥有的 window 总是出现在其所有者之上。