【问题标题】:How to hide a MDI Child form in Delphi?如何在 Delphi 中隐藏 MDI 子窗体?
【发布时间】:2012-08-29 13:08:13
【问题描述】:

如何在 Delphi 中隐藏 MDIChild 窗口?

我在我的 MDI 孩子的 FormClose() 事件中使用此代码,但它似乎不起作用:

procedure TfrmInstrument.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caNone;
  ShowWindow(Handle, SW_HIDE);
  frmMainForm.MDIChildClosed(Handle);
end;

我的子窗口被最小化而不是被隐藏。

【问题讨论】:

  • @AndreasRejbrand 当我点击红十字时,默认行为是在 Delphi 中最小化一个 mdi 子窗口。我想隐藏窗口。
  • iMan:好点子。现在我明白你的意思了。你不想最小化,也不想破坏。您想暂时隐藏它,以便稍后再次显示它。我不知道这是否可能。 [嗯,显而易见的解决方案确实是销毁它,然后在需要时创建一个新的类似窗口。]
  • @AndreasRejbrand 我不想销毁并重新创建一个类似的窗口,因为每个子窗口都会加载一些库、打开一个串行端口以及其他一些需要几秒钟的初始化内容。因此,我在启动时创建了所有子表单,使用 ShowWindow 隐藏它们,具有讽刺意味的是,它在那里工作,当用户选择它们时显示它们,并希望在用户关闭它们时再次隐藏它们
  • @iManBiglari: 如果你把你所有的组件和相应的代码移动到每个 MDI 子窗口的数据模块中,并将 MDI 子窗口视为一个简单的视图(可以随意打开和关闭),那么您无需与 MDI Windows 子系统作斗争。我敢说这样的改变也会改善程序设计。
  • @mghie 我不明白为什么需要数据模块来实现这种分离。我想它可以节省您编写样板代码来实例化组件,但我从未发现这特别引人注目。

标签: windows delphi winapi mdi


【解决方案1】:

TCustomForm 中有一个受保护的过程定义为:

procedure TCustomForm.VisibleChanging;
begin
  if (FormStyle = fsMDIChild) and Visible and (Parent = nil) then
    raise EInvalidOperation.Create(SMDIChildNotVisible);
end;

在您的 MDI 子窗口中将其覆盖为:

procedure TMDIChildForm.VisibleChanging;
begin
  // :-P
end;

Here's a simple example

在阅读了 Jeroen 的评论后,我尝试了另一种同样有效的解决方案,但有点闪烁:

procedure TMDIChildForm.VisibleChanging;
begin
  if Visible then
    FormStyle := fsNormal
  else
    FormStyle := fsMDIChild;
end;

也许这适用于所有 Windows 版本。

PS:我在 Windows 2k3SP2 x86 和 Windows 7 Ultimate x86 上的第一个解决方案没有发现任何问题

【讨论】:

  • Windows 中的 MDI 支持包含许多错误,这些错误(或者至少当我在 90 年代看到这个时)在 Microsoft 的“无法修复”列表中。这是几乎没有任何看起来像 MDI 的 Microsoft 应用程序实际上使用 Windows MDI 代码的原因之一。 TCustomForm.VisibleChanging 正在防止这些错误显示其丑陋的头部。因此,您的建议可能会导致您的应用程序在某些版本的 Windows 上失败。
  • @JeroenWiertPluimers 然后看看另一个答案。也许这会绕过所有这些错误
  • +1;另一个答案(设置FormStyle)确实会绕过这些错误。我很确定这些错误从 Windows 3.0 到 Windows 2000 左右都存在。之后我只切换到 SDI 和 Outlook 风格的应用程序。
  • 我会在所有目标操作系统版本上广泛测试解决方案 1。如果它有效,我会说去吧。我的猜测是TCustomForm.VisibleChanging 背后的原因已经消失在时间的深处。或许您可以在 Emba 论坛上询问相关问题,看看是否有任何旧时的 Emba 开发人员还记得这个推理。
  • 我什至经常在工业领域看到 DOS、Windows 95 和 Windows NT 4 解决方案。它们中的大多数都是与机器连接的独立系统。
【解决方案2】:

您不能隐藏 MDI 子窗口。这是 Win32 的限制。

【讨论】:

  • 但是mdi子窗口怎么会抗拒ShowWindow() API调用呢?
  • 因为这样的窗口不是为了隐藏而设计的?
  • 我相信 Andreas 是正确的,但我不确定为什么会做出这个设计决定。毫无疑问,您已经尝试调用Hide,然后在 VCL 引发“无法隐藏 MDI 子窗口”错误时放弃。但这是 VCL 告诉您不支持此功能的方式。
  • @DavidHeffernan 我在 Vcl.Forms.pas` 中窥视了一下,发现了这个过程:procedure TCustomForm.VisibleChanging; begin if (FormStyle = fsMDIChild) and Visible and (Parent = nil) then raise EInvalidOperation.Create(SMDIChildNotVisible); end; 我在我的 mdi 子表单中覆盖了它,我的表单第一次被隐藏了。但第二次它又把自己最小化了。所以我想我是在正确的轨道上
  • 不,我不这么认为。这个例外是因为 MDI 和隐藏的子窗体不混合。删除引发异常的代码不会改变这个基本问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
相关资源
最近更新 更多