【问题标题】:Proper handling of modal window "Minimize" behavior正确处理模态窗口“最小化”行为
【发布时间】:2011-09-12 07:34:35
【问题描述】:

我有以下问题:我们正在构建一个相当大的应用程序(win32、Delphi 6 Enterprise)。在应用程序的几个部分中,使用了模态窗口,通常包含选择主窗口的详细信息。

我们对 WM_SYSCOMMAND 消息的处理进行了修改,这样,如果窗口是模态窗口,则 SW_SHOWMINNOACTIVE 消息将被发送到应用程序的主窗口。这会导致整个应用程序被最小化,而不仅仅是模态表单。

但是,在特定情况下会发生一个问题:如果调用窗口设置为全屏,那么在恢复时,模式窗口将出现在(禁用)最大化的主窗口下(这似乎发生在 Windows 7)

我的问题有两个:

首先,当应用程序恢复时,我似乎没有收到任何 syscommand 消息,因此我无法引入代码来恢复 Z-Order,因为我不知道将它放在哪里。 其次,在我看来,如果整个应用程序被最小化,单击任务栏中的应用程序按钮应该将其恢复到相同的状态,而不是在它下面有一个模态窗口。有没有办法解决这个问题?

编辑:我们做了一些额外的测试,看起来我们实际上可以在主窗体的 WM_ACTIVATE 处理程序中检测到问题。我们还可以在那个阶段识别模态窗口。但是,我无法找到将其恢复到 Z-Order 顶部的方法。

Edit2:这里是模态窗体最小化时应用最小化的代码:

procedure TfmGITForm.WMSysCommand(var Message: TWMSysCommand);
begin
  if (fsModal in FormState) or
      not Application.MainForm.Visible then
  begin
    case Message.CmdType of
      SC_MINIMIZE:
      begin
        ShowWindow(Application.Handle, SW_SHOWMINNOACTIVE);
      end;
      SC_RESTORE:
      begin
        ShowWindow(Application.Handle, SW_SHOWNORMAL);
        inherited;
      end;
    else
      inherited;
    end;    // case
  end
  else
    inherited;
end;

我们所有的形式都源自那个。

【问题讨论】:

  • Delphi 的哪个版本?
  • 嗯,我记得 Delphi 6 的类似问题,我认为通过引入 PopupParent 属性及其相关属性在最近的 Delphi 版本中得到了改进。毫无疑问,其他人会更了解确切的细节。
  • 您能否扩展SW_SHOWMINNOACTIVE 的发送。这样是不是最小化模态表单会导致整个应用程序最小化?如果是这样,请尝试调用 Application.Minimize。
  • 另一个问题:模态窗口的所有者是哪个窗口?我的意思是指窗口所有者而不是 VCL 所有者。
  • 我最近也犯了同样的错误,正确的大小写是case Message.CmdType and $FFF0 of。请参阅WM_SYSCOMMAND 中的备注。

标签: delphi winapi windows-7 delphi-6


【解决方案1】:

这与(我认为)XP 中引入的 Windows 窗口重影有关。我在这些操作系统上的 D5 应用程序中遇到了同样的问题。当时彼得·弗莱德提供了以下解决方法,它仍然对我很有帮助:

procedure DisableProcessWindowsGhosting;
type
  TDisableProcessWindowsGhostingProc = procedure; stdcall;
const
  sUser32 = 'User32.dll';
var
  ModH: HMODULE;
  _DisableProcessWindowsGhosting: TDisableProcessWindowsGhostingProc;
begin
  ModH := GetModuleHandle(sUser32);
  if ModH <> 0 then begin
    @_DisableProcessWindowsGhosting := nil;
    @_DisableProcessWindowsGhosting := GetProcAddress(ModH,
        'DisableProcessWindowsGhosting');
    if Assigned(_DisableProcessWindowsGhosting) then begin
      _DisableProcessWindowsGhosting;
    end;
  end;
end;

我在应用主窗体的 OnCreate 处理程序的开头调用它。

【讨论】:

  • 不知道你从哪里得到了重影。并且禁用重影通常并不理想——继续排队!
  • @David:通常不是一个好主意。然而,鬼魂是在不同的时间产生的。关于无响应性(我认为您在抽队列时暗示了这一点)只是其中之一。在最小化应用程序窗口(你知道隐藏的窗口)是/是另一个。 D5、D6 和可能的 D7 应用程序都受此影响,在这种情况下,只是告诉 Windows 不要为这个过程创建一个幽灵窗口对我来说似乎可以,作为替代方案,隐藏在你的主窗体后面的模式对话框要糟糕得多......
  • 感谢您的想法。我试过了,不幸的是,它不起作用:(
  • @Stephane,对此感到抱歉。不确定我可以提供更多帮助。恐怕这对我来说也有点“古老的历史”了。
  • edit:对不起,当我写“它不起作用”时,我的意思是它不能解决从最小化状态恢复应用程序时模态窗体处于最大化窗体下的问题。代码执行正确且完整。
【解决方案2】:

覆盖对话框的CreateParams 函数并将Params.WndParent 设置为全屏窗口(或Owner.Handle,如果您拥有正确的东西)。默认为Application.Handle,会导致此类问题。在以后的 Delphi 版本中引入的 PopupParent 属性完全相同。

【讨论】:

    猜你喜欢
    • 2010-10-21
    • 2017-12-16
    • 2010-09-22
    • 2018-08-24
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    相关资源
    最近更新 更多