我们有一个Delphi应用程序(XE8),我最近发现它几乎完美地在wine(OSX 10.6)上运行,除了一件事。假设用户在主窗体上选择一个菜单选项,打开另一个窗体(如'File | New ...')。新表单显示,部分涵盖主要表单。问题是没有办法让第一个表单回到顶部。单击主窗体不会像在窗口中那样将其重新显示在子窗体的顶部。如果显示两个子窗体,再次点击一个孩子不会将它带到前台 - 它似乎是可聚焦的(如果你可以抓住它就可以拖动它),但它的任何部分都被覆盖另一种形式仍然存在
当我们使用winebottler和使用交叉应用程序时都会出现这种情况。
我们在装瓶过程中遗漏了一些图书馆吗?或者可能只是完全误解了'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.
在unit1中,我们有一个按钮来启动第二个表单
procedure Tfmain.Button1Click(Sender: TObject);
begin
form2m.show
end;
运行.exe,主窗体显示;按下按钮:新表单覆盖主表单。
在Windows中,单击主窗体的标题栏 - 它将返回到前台。
在winebottler中,单击主窗体的标题栏,它不会恢复;即使看起来标题栏有焦点,表格的其余部分仍然隐藏 - 见截图
答案 0 :(得分:1)
<强>所有权强>
问题是你的第二种形式归主体形式所有
拥有的窗口始终显示在其所有者的顶部。
手动设置所有权
解决方案是更改第二个表单的所有权。
首先,您需要禁用自动创建第二个表单并手动执行所有操作:
在菜单中选择:
项目 - &gt;选项 - &gt;形式
选择您的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;
现在你选择的任何窗口都会出现在最顶层。
<强>说明强>
这与MainFormOnTaskbar
无关,它只是简单的Windows行为:拥有的窗口始终显示在其所有者的顶部。