Delphi 应用主窗体暂时弹到最前面

Posted

技术标签:

【中文标题】Delphi 应用主窗体暂时弹到最前面【英文标题】:Delphi Application Main Form temporarly flicking to the front 【发布时间】:2017-02-20 16:04:36 【问题描述】:

我们有一个 Delphi 2007 应用程序,并且最近启用了 MainFormOnTaskBar 以更好地支持 Windows Aero。但是,由于单击时主窗体不会出现在所有子窗体的顶部,因此我们添加了以下代码。

procedure TBaseForm.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);

  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent := 0; 
end;

这样做的一个副作用是,当在不处理该特定热键的子窗体上按 Alt + key 热键时,主窗体会弹到前面然后再回来。如果处理了热键,则不会发生此行为,可能是因为热键被吞了。

有没有其他人经历过这种行为并且可以提出解决方法。

谢谢

【问题讨论】:

MainFormOnTaskbar 为真时,您不需要像那样覆盖CreateParams()。基本实现已经为您设置了相同的值。单击MainForm 应该会在单击时将其置于顶部,这是正常的窗口行为。 @Remy - 当 MainFormOnTaskbar 为真时,所有辅助表单都归主表单所有。这可以防止主要形式出现在次要形式之前。 您可能还会遇到其他问题。一个在解决方法部分提到了here。可能还有其他人...... @SertacAkyuz:“当 MainFormOnTaskbar 为 true 时,所有辅助表单都归主表单所有”——这是一个很好的观点,我忘记了。在这种情况下,您必须在辅助表单上覆盖 CreateParams() 以破坏该所有权。 【参考方案1】:

观察到的行为是 VCL 加速器支持主窗体上可能的主菜单的结果,因此即使在另一个窗体处于活动状态时,您也可以从主窗体的菜单中选择菜单项。

主窗体的激活是通过在主窗体的句柄上调用SetFocus 来实现的,而“应用程序”正在处理从“WinControl”的WM_SYSCOMMAND 处理程序发送的CM_APPSYSCOMMAND 消息(辅助窗体)当命令类型为SC_KEYMENU(窗口菜单激活 - Alt 键)时。

请注意,此行为不是使用 MainFormOnTaskBar 然后覆盖 CreateParams 以使表单可以放在前面的副作用。无论MainFormOnTaskBar 的设置如何,都会发生相同的行为。唯一不同的是,激活的主窗体在设置时不能出现在辅助窗体之前,但主窗体是一样的。

您可以在多个位置进行拦截以修改行为,例如辅助表单上的 WM_SYSKEYDOWN 处理程序,或辅助表单的 OnKeyDown 处理程序。语义上更正确的覆盖,IMO,应该在辅助形式的IsShortCut 上完成。正如您所发现的,当辅助表单处理组合键时,系统键的处理将终止。然后,您可以告诉 VCL 您的表单需要密钥:

type
  TSecondaryForm = class(TForm)
    ..
  public
    function IsShortCut(var Message: TWMKey): Boolean; override;

...

function TSecondaryForm.IsShortCut(var Message: TWMKey): Boolean;
begin
  Result := True;
end;

当然你可以根据参数进行微调以有条件地返回 true。

【讨论】:

以上是关于Delphi 应用主窗体暂时弹到最前面的主要内容,如果未能解决你的问题,请参考以下文章

delphi 如何改变主窗体

delphi 子窗体如何继承主窗体的方法

delphi 怎样绘制半透明窗体,只让窗体背景半透明,而窗体里面的控件 不透明

delphi 让子窗体在主窗体内,其在主窗体内最大化,但又不遮盖主窗体的菜单栏

delphi平台,在一个主窗体上打开两个子窗体,也就是:打开一个子窗体之后,再打开第二个窗体第一个窗体不关闭

delphi 托盘图标 主窗体就隐藏,跳出一个窗体就缩小的