2010-11-09 60 views
6

我使用德尔福2010年建立一个Win32 GUI应用程序在Windows XP/Vista和Windows 7上运行开关Application.Mainform并调用MainformOnTaskBar原因闪烁Windows任务栏

基本上,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将窗体2为MainForm,然后更新Windows的任务栏缩略图预览。但是,任务栏可能会闪烁开关。

我的问题是:

  1. 有什么办法走这样的闪烁?
  2. 设置Application.MainformOnTaskBar:False是否安全并在运行时再次将其设置为True?

回答

9

主窗体不是你允许在Delphi中改变的东西。你设法找到了一种看似工作的方式,但这是一种破解。别那样做。

一个应用程序只有一个主窗体,它是通过CreateForm创建的第一个窗体。如果您需要为主要形成了两个完全不同的行为,那么你可以尝试一些技巧:

  • 定义你的两种主要形式。把你所有的功能放在那里。然后定义一个表单作为两个框架之一的父代。而不是切换主窗体,只需销毁框架并将其替换为新窗体即可。

  • 与框架解决方案类似,但使用表单代替。创建表单,并将Parent属性设置为“真实”主表单。这可能会有一个较低的初始成本,因为你已经有两种形式,但根据我的经验,重新生成表格比框架更脆弱,因为它是儿童控制的,所以更喜欢框架技术。

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

+0

此外,您也可以在它们之间建立两个不同的过程和交换数据。这当然有点贵,如果你不得不分享数据,这可能并不理想。 – 2010-11-09 15:22:34

+0

这将是阻止任务栏闪烁,@Jens的反义词。任务栏将来自同一进程的按钮分组,这就是为什么Chau的代码似乎将一个按钮替换为另一个按钮 - 它们占据了任务栏上的相同位置。但是,如果按钮属于两个不同的进程,那么任务栏不会将它们放在一起。你不仅有闪烁的按钮,而且有从一个地方跳到另一个地方的按钮。 – 2010-11-09 15:29:30

+0

取决于它们是否应该同时可见,以及它们是否足够分离两个不同的可执行文件。问题是为什么Chau需要改变主要形式呢?我在猜测,使用两个相同的可执行程序甚至两个不同的进程可能是一个更好的主意。 – 2010-11-09 15:34:46

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; 
+1

查看旧的新事物为什么[将桌面作为应用程序窗口的父级是错误的](http://blogs.msdn.com/b/oldnewthing/archive/2004/02/24/79212.aspx)。 – 2012-12-12 09:16:22