2010-11-09 49 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