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 总是出现在其所有者之上。
我们有一个 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 总是出现在其所有者之上。