Delphi应用程序主窗体暂时闪到最前面。

4
我们有一个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+热键时,主窗体会闪到前面,然后再回来。如果处理了热键,则不会出现这种行为,可能是因为热键被吞噬了。是否有其他人经历过这种行为并能提供解决方法?
谢谢!

MainFormOnTaskbar 为真时,您不需要像那样覆盖 CreateParams()。基本实现已经为您设置了相同的值。单击 MainForm 应该在单击时将其置于顶部,这是正常的窗口行为。 - Remy Lebeau
1
@Remy - 当MainFormOnTaskbar为true时,所有次要窗体都归主窗体所有。这可以防止主窗体出现在次要窗体前面。 - Sertac Akyuz
您可能会遇到其他问题。 其中一个在此处的解决方法部分提到。 可能还有其他问题... - Sertac Akyuz
@SertacAkyuz:“当MainFormOnTaskbar为true时,所有次要窗体都归主窗体所有”-这是一个很好的观点,我忘记了这一点。在这种情况下,您需要在次要窗体上重写CreateParams()以打破该所有权。 - Remy Lebeau
1个回答

5
观察到的行为是VCL在主窗体上支持加速器的结果,因此即使另一个表单处于活动状态,您也可以从主窗体菜单中选择菜单项。
主窗体的激活是通过在处理"Application"的CM_APPSYSCOMMAND消息时,在主窗体的句柄上调用SetFocus。该消息是从"WinControl"(次要窗体)的WM_SYSCOMMAND处理程序发送的,当命令类型为SC_KEYMENU(窗口菜单激活-Alt键)时。
请注意,这种行为不是使用MainFormOnTaskBar并覆盖CreateParams以具有可前置的窗体的副作用。无论设置MainFormOnTaskBar如何,都会出现相同的行为。唯一的区别是,设置后激活的主窗体不能出现在次要窗体的前面,但是主窗体仍然被激活。
您可以拦截修改行为的多个位置,例如次要窗体的WM_SYSKEYDOWN处理程序或次要窗体的OnKeyDown中。在我的看法中,更语义正确的覆盖应该在次要窗体的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。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接