【问题标题】:Make 2 forms able to overlap each other?使2个表格能够相互重叠?
【发布时间】:2011-07-20 14:28:24
【问题描述】:

我想要一个单独的表单,与我的主表单“一起”显示,因此它不会与主表单重叠。

这是一个例子:

注意主程序如何重叠日志?我不知道如何在 Delphi 中做到这一点。

谢谢!

【问题讨论】:

  • +1 抵消匿名反对票。
  • +1,这是一个非常好的问题
  • 恐怕我不明白你在纠结什么?如果您创建一个全新的应用程序并添加第二个表单,这正是您所得到的。你不需要任何特别的事情。如果您解释您的应用程序正在在做什么而您不满意,也许会有所帮助。
  • @Craig:不,你不明白。创建一个新的 VCL 表单应用程序,并将主窗口设为蓝色。现在,向应用程序添加一个新表单;把它变小变红。最后,在主窗体上创建一个OnClick 处理程序并执行Form2.Show。您会注意到,新的红色表单永远不会显示在蓝色主表单后面。所以你真的确实需要一些特别的东西。

标签: delphi forms vcl tform


【解决方案1】:

这个问题的答案在于非常有用的Window Features MSDN 主题。

相关信息是:

重叠或弹出窗口可以是 由另一个重叠或弹出窗口拥有 窗户。被拥有的地方有几个 对窗口的约束。

  • 拥有的窗口在 z 顺序中始终位于其所有者之上。
  • 当一个拥有的窗口的所有者被删除时系统会自动销毁它 销毁。
  • 拥有的窗口在其所有者最小化时被隐藏。

您的应用程序中的主要窗体是其他弹出窗口的所有者(在 Windows 术语中,而不是 Delphi 术语中)。上面的第一个要点意味着拥有的窗口总是出现在主窗体(所有者)之上。

尝试创建一个包含 3 个表单的应用,并将它们全部展示出来。 .dpr 看起来像这样:

program OwnedWindows;

uses
  Forms,
  Main in 'Main.pas' {MainForm},
  Popup1 in 'Popup1.pas' {PopupForm1},
  Popup2 in 'Popup2.pas' {PopupForm2};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMainForm, Main);
  Application.CreateForm(TPopupForm1, PopupForm1);
  Application.CreateForm(TPopupForm2, PopupForm2);
  PopupForm1.Show;
  PopupForm2.Show;
  Application.Run;
end.

您会看到主表单始终位于其他两个表单的下方,但这些其他拥有的表单可以在彼此之上或之下。当您最小化主窗体时,它们都会消失。

如果您想让所有表单成为顶级无主窗口,您可以这样做:

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

在我的示例中同样适用于 TPopupForm2。这将导致所有 3 个窗口都有任务栏按钮。

另一种方法是恢复到Vista 之前的方式,并使应用程序的隐藏窗口成为顶级所有者窗口。为此,请确保 Application.MainFormOnTaskbar 为 False。跳过所有 CreateParams 代码,您现在将在任务栏上有一个窗口,并且您的任何窗口都可以在任何其他窗口之上,因为顶级所有者窗口是隐藏窗口 Application.Handle。当然,缺点是你失去了 Aero Peek。

所以,我想你需要做的是让主窗体像往常一样出现在任务栏上,但确保其他窗体不属于主窗体(在 Windows 意义上)。但是需要拥有它们以避免将它们放在任务栏中。因此,您可以使用 CreateParams 方法使隐藏的应用程序窗口成为所有者,如下所示:

procedure TOverlappedPopupForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := Application.Handle;
end;

尽管您在 cmets 中另有说明,但当我这样做时,我发现当我最小化主窗体时弹出窗体确实被隐藏了。并在主窗体恢复时再次显示。因此,我认为这确实可以完全解决您的问题。

【讨论】:

  • 感谢您,+1!有没有办法让任务栏上只有一个图标(根据我的经验,这不是隐藏窗口,因为 Windows 7 Thumb Preview 是空白的)?
  • @Jeff 主要形式通常是任务栏。这就是您想要 Aero Peek 预览的那个。其他弹出窗口将是拥有的窗口,因此始终位于主窗口的顶部。这不是你想要的吗?
  • @David - 我们越来越近了! :) 当我最小化 ImgBurn 的 MainForm 时,日志也被最小化了!这将是完整的解决方案:)
  • @Jeff 你必须自己做。检测到主窗体正在被最小化并在其他窗体上调用 Minimize。当窗口恢复时,你会想要做相反的事情。当您制作弹出窗口拥有的窗口时,这是您免费获得的。
  • @Jeff 当应用程序隐藏窗口是任务栏窗口时,TApplication 中有处理此类问题的代码。实际上,您可能想要隐藏弹出窗口而不是最小化它们,因为如果您这样做,它们的最小化窗口将出现在任务栏上方。
【解决方案2】:

我现在还没有打开Delphi,但会设置

mainform.formstyle := fsStayOnTop 

并用

显示子窗体
childform.show;

工作?

或者尝试使用 SetWindowPos() 并将 hWndInsertAfter 属性设置为类似于主窗体上的 HWND_TOPMOST

【讨论】:

  • 这在不使窗口最顶部的情况下肯定是可能的。
  • 也许将子窗体设置为 HWND_BOTTOM
  • -1 将样式设置为 fsStayOnTop 会在应用程序内外产生其他影响,您在答案中未提及。
  • @jachguate 是虚拟的 -1 吗?
  • @David,哈哈哈……现在不行。 :)
猜你喜欢
  • 1970-01-01
  • 2014-07-27
  • 2012-08-09
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
相关资源
最近更新 更多