在运行时切换Application.Mainform并调用MainformOnTaskBar导致Windows任务栏上的闪烁

时间:2010-11-09 08:32:59

标签: delphi

我正在使用Delphi 2010构建在Windows XP / Vista和Windows 7上运行的Win32 GUI应用程序。

基本上,Application.MainForm是一个只读属性,一旦通过Application.CreateForm创建第一个表单,就无法在运行时更改:

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

上面的示例将使Form1成为应用程序的mainform。它将显示在Windows 7任务栏的缩略图预览中。

在运行时将Application.MainFormOnTaskBar设置为true,我们可以享受Windows aero主题功能。

我需要在运行时切换应用程序的mainform。例如,将Form2设置为主窗体。我使用以下代码使其工作:

procedure SetAsMainForm(aForm:TForm);
var
  P:Pointer;
begin
  Application.MainFormOnTaskBar := False;
  try
    P := @Application.Mainform;
    Pointer(P^) := aForm;
    aForm.Show;
  finally
    Application.MainFormOnTaskBar := True;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetAsMainForm(Form2);
end;

执行Button1.Click将使Form2成为主窗体并更新Windows的任务栏缩略图预览。但是,任务栏可能会在切换时闪烁。

我的问题是:

  1. 有没有办法消除这种闪烁?
  2. 设置Application.MainformOnTaskBar:= False并在运行时再次将其设置为True是否安全?

2 个答案:

答案 0 :(得分:9)

主要形式不是您可以在Delphi中更改的内容。你设法找到了一种似乎在中途工作的方法,但这是一个黑客攻击。停止这样做。

应用程序只有一个主窗体,它是通过CreateForm完成创建的第一个窗体。如果您需要两种截然不同的主要表单行为,那么您可以尝试几种技术:

  • 将两个主要表单定义为 frames 。把你所有的功能放在那里。然后定义一个单独的表单,作为两个帧之一的父表单。不要切换主窗体,只需破坏框架并将其替换为新框架。

  • 与框架解决方案类似,但改为使用表单。创建表单,并将Parent属性设置为“真正的”主表单。这可能会有较低的初始成本,因为你已经拥有这两种形式,但根据我的经验,重新创建表单比使用设计作为子控件的框架更脆弱,所以更喜欢框架技术

任务栏上的闪烁来自一个表格消失而另一个表格出现。使用上述任何一种技术,总会有一种形式,而不是两种,所以没有什么可以闪烁。

答案 1 :(得分:5)

要考虑的另一个选项是设置MainFormOnTaskbar=False,然后在流程的生命周期内创建隐藏的MainForm,并让Form1Form2成为您创建并动态释放的辅助表单在需要时,通过覆盖TForms.CreateParams()方法给他们自己的任务栏按钮,例如:

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent := GetDesktopWindow;
end;