2010-02-05 49 views
44

什麼是TApplication.Handle德爾福:什麼是Application.Handle?

  • 它從何而來?
  • 它爲什麼存在?
  • 而最重要的是:爲什麼所有表單都將它作爲父窗口處理?

Delphi幫助說:

TApplication.Handle

提供對窗口辦理 應用的主要形式(窗口)的 。調用Windows API的需要父窗口句柄 功能 時

property Handle: HWND; 

說明

用途把手。例如, 顯示其自己的頂層彈出窗口 一個DLL需要一個父窗口 在 應用顯示其窗口。使用手柄財產 使得 應用程序的窗口等部分,讓他們 最小化,恢復,啓用和 與應用程序禁用。

如果我專注於詞「應用的主要形式的窗口句柄」,我認爲這意味着應用的主要形式的窗口句柄,然後我可以比較:

  • 「應用程序的主要形式的窗口句柄」,用
  • Application
MainForm的窗口句柄

,但他們是不一樣的:

Application.MainForm.Handle: 11473728 
Application.Handle: 11079574 

那麼,什麼是Application.Handle

  • 它從何而來?
  • 什麼窗口®窗口句柄是它?
  • 如果它的Windows ®窗口句柄的ApplicationMainForm,那他們爲什麼不匹配?
  • 如果是不是Application的窗口句柄MainForm,那麼它是什麼?
  • 更重要的是:爲什麼它是每種形式的最終父母?
  • 而且最重要的是:如果我試圖讓一個窗體沒有顯示(所以我可以顯示在任務欄上),或者嘗試使用類似IProgressDialog的東西,爲什麼一切都會失控?

真的,我問的是:什麼是使Application.Handle存在的設計原理?如果我能理解爲什麼,那該如何變得明顯。


更新通過的二十個問題遊戲的認識:

此:

在談論如何讓一個窗口的解決方案通過使它的主人nullPeter Below in 2000 said出現在任務欄上可能會導致一些問題與 輔助形式顯示的模態形式。

如果用戶在模態 表單啓動時切換離開應用程序,然後回到顯示它的表單,模式表單可能會隱藏在表單下方 。這是可能通過確保 模式窗體父到顯示了它的形式( `params.WndParent``如上使用)

應對這種但這是不可能的從標準 對話Dialogs單元和例外,這就需要更多的努力 讓他們的工作權利(基本處理Application.OnActivate, 通過GetLastActivePopup 尋找父對象應用模式表單,並通過SetWindowPos將他們的Z順序的頂部) 。

  • 爲什麼模式表單最終會被卡在其他表單之後?
  • 什麼機制通常將模態形式帶到前面,爲什麼它在這裏不起作用?
  • Windows ®負責顯示窗口堆疊。 Windows ®沒有顯示正確的窗口出了什麼問題?

他還談到使用新的Windows擴展樣式,迫使一個窗口出現在任務欄上(當使它無主的一般規則是不夠的,不切實際的,或不希望),通過添加WS_EX_APPWINDOW擴展風格:

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

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

但他警告:

如果您在輔助形式單擊任務欄按鈕,而另一個應用是 活躍,這將仍然把所有的應用程序˚F orms前面。如果您 不希望有選擇

誰把所有形式的前面,當窗體的所有者仍然是Application.Handle。是應用程序這樣做?它爲什麼這樣做?而不是這樣做,不應該不是要做到這一點嗎? 不是這樣做的缺點是什麼;我看到的的缺點做它(系統菜單的不propertly工作,任務欄按鈕的縮略圖是不準確時,Windows ®外殼無法最小化窗口


在另一篇文章中涉及的ApplicationMike Edenfield says that the parent window sends other window's their minimize, maximize and restore messages

這將增加任務欄按鈕的形式,但也有其他一些小的細節 手柄。最明顯的是,你的表格仍收到最小化/最大化獲取發送到父 形式(理論上的主要形式e應用程序)。

procedure WMSysCommand(var Msg: TMessage); WM_SYSCOMMAND; 

procedure TParentForm.WMSysCommand(var Msg: TMessage); 
begin 
    if Msg.wParam = SC_MINIMIZE then 
    begin 
     // Send child windows message, don't 
     // send to windows with a taskbar button. 
    end; 
end; 

注意,此處理雲在家長形式要表現的一個independantly的>:爲了避免這種情況,你可以通過添加一條線,如安裝WM_SYSCOMMAND消息 處理器應用程序的其餘部分,以避免傳遞最小化消息。您可以添加類似>代碼SC_MAXIMIZE,SC_RESTORE等

它是如何最小化/最大化/還原我的Windows ® Windows消息都不會到我的窗口?這是否是因爲發往窗口的消息是由Windows ®發送給窗口的所有者?在這種情況下,Delphi應用程序中的所有表單均由Application「擁有」?這是否並不意味着讓車主空:

procedure TForm2.CreateParams(var Params: TCreateParams); 
begin 
    inherited; 
    Params.WndParent := 0; //NULL 
end; 

將刪除Application,並從我的形式,干擾它的窗口句柄,和Windows應該再次發出我mimimize /最大化/還原郵件?


或許,如果我們比較和對照現在「正常」的Windows應用程序做的事情,與Borland如何最初設計Delphi應用程序做的事情 - 對於此Application對象和它的主循環。

  • 什麼解決方案是Application對象解決?
  • Delphi的後續版本做了哪些修改,以便這些相同的問題不存在?
  • Delphi的後續版本中的更改是否引入了其他問題,即初始應用程序設計如何努力解決?
  • 這些較新的應用程序如何在沒有Application干擾的情況下仍能正常工作?

很明顯,Borland意識到了他們最初設計中的缺陷。他們最初的設計是什麼?它解決了什麼問題?缺陷是什麼?重新設計了什麼?它是如何解決問題的?

+0

我想你會有興趣瞭解這兩個技巧:http://yoy.be/item.asp?i89 http://yoy.be/item.asp?i87 – 2010-02-05 07:12:30

+2

@Stinh桑德斯:我'已經看到了這些,他們不解決問題。此外,絕對不要將GetDesktopWindow作爲窗口的所有者傳遞,因爲這些主題和其他帖子都暗示了這一點。這樣做會導致Windows凍結。這是微軟修補CreateWindow的一個問題,因此任何傳遞GetDesktopWindow作爲所有者的人都改爲使用NULL。如果我可以在** yoy.com **上編輯該帖子,我會的。 – 2010-02-05 14:52:39

回答

47

應用程序窗口的原因有點骯髒的歷史。在開發Delphi 1時,我們知道我們想要使用IDE的「SDI」(分佈在整個桌面上的窗口)ui模型。我們也知道Windows在該模型中吸引(並且仍然如此)。但是我們也注意到當時的Visual Basic使用了這個模型,它似乎運行良好。經過進一步檢查,我們發現VB使用了一個特殊的「隱藏」停車窗口,用作所有其他可見窗口的「所有者」(Windows有時會模糊父母和所有者的概念,但區別與VCL類似) 。

這就是我們如何解決包含主菜單的窗口很少聚焦的「問題」,因此處理文件菜單的Alt-F根本行不通。通過使用此中央停車窗口作爲中介,我們可以更輕鬆地跟蹤消息並將消息路由到適當的窗口。

這種安排也解決了另一個問題,即通常多個頂級窗口完全獨立。通過讓應用程序處理所有這些窗口的「所有者」,它們都將表現得一致。例如,您可能已經注意到,當您選擇任意的應用程序窗口,全部時,應用程序窗口將移動到前面並保持其相對於彼此的z順序。這也將使應用程序最小化和恢復爲一個功能分組。

這是使用此模型的結果。我們可能已經手動完成所有這些工作,以保持事情的順利,但設計理念是不重新發明Windows,而是在可能的地方利用它。這也是爲什麼TButton或TEdit分別是真的一個Windows「用戶」按鈕和編輯窗口類和樣式。隨着Windows的發展,這個「SDI」模型開始失寵。事實上,Windows本身開始對這種應用風格產生「敵意」。從Windows Vista開始,繼續到7,用戶外殼似乎不適用於使用停車窗口的應用程序。所以,我們着手在VCL中進行混洗,以消除停車窗口並將其功能移到主窗體中。這提出了幾個「雞和雞蛋」的問題,我們需要在應用程序初始化時足夠早地提供停放窗口,以便其他窗口可以「附加」到它,但主窗體本身可能不會很快構建。應用程序必須通過幾個環節才能實現這一目標,並且出現了一些引起問題的微妙邊緣案例,但大部分問題已經解決。但是,對於您前進的任何應用程序,它將繼續使用較舊的停車窗模型。

+3

+1互聯網。並被接受。 – 2010-02-06 03:56:52

+1

+1,因爲它是骯髒的。而添加到微軟窗口管理層的Windows XP黑客是這個系統死亡的一部分,因爲當你在XP上運行Delphi 7應用程序時,可怕的Z-Order錯誤開始出現。 – 2010-02-10 16:51:03

7

從看着forms.pas(德爾福2009)源,它似乎是在Win32 GUI應用創建一個「主」窗口允許

  • TApplication的電話。最小化
  • TApplication.Restore

看來,傳遞給Application.Handle消息轉發酌情向MainForm,如果它存在。如果主窗口尚未創建,這將允許應用程序響應最小化等。通過修改項目源代碼,您可以創建一個delphi應用程序而不需要一個主窗口。

在這種情況下,即使您尚未創建主窗口,TApplication方法仍然可以工作。不知道我是否抓住了所有的目的,但我沒有時間去瀏覽所有的TApplication代碼。

根據您的問題:

  • 它從何而來?它是在TApplication.Create

  • 創建的窗口句柄是什麼窗口句柄?每個GUI Delphi應用程序需要爲TApplication的抽象

  • 的一部分假的窗口是它appliation的主要形式的窗口句柄沒有

  • 如果它不是應用程序的MainForm中的手柄,然後什麼是嗎?見上面

  • 更重要的是:爲什麼它是每種形式的最終父母?假設你是對的,它的最終父母,我認爲它是如此,因爲它可以很容易地找到你的應用程序中的所有形式(列舉這個「主」形式的孩子)。

  • 和最重要的是:爲什麼一切就會失控,如果我嘗試有一個表格是unparented我想是因爲隱藏的「大師」的形式獲取系統信息,它應該傳給其子和/或者mainform,但是找不到未登錄的表單。

無論如何,這是我的承擔。您可以通過查看forms.pas中的TApplication聲明和代碼瞭解更多信息。我看到的底線是一個方便的抽象。

最好的問候,

+1

在Delphi 2007中,VCL更改爲默認爲沒有隱藏窗口,但如果有幫助,您也可以選擇舊的方式。隱藏的窗口阻止Windows 7預覽正常工作。 – mj2008 2010-02-05 09:00:37

+0

@ mj2008:你有鏈接瞭解更多關於這方面的信息嗎?我目前正在從C++ Builder 2006 - > C++ Builder 2009更新項目,我相信我看到我的Application-> Handle ptr爲NULL。現在在Builder 2009中是這種情況嗎?如果是這樣,將使用MainForm-> Handle是一個很好的替代品? – 2010-06-07 00:38:04

+0

@Rob這個Delphi控件是Application.MainFormOnTaskbar,但我不知道它是否適用於你。通常,升級後的應用程序沒有更改。 – mj2008 2010-06-09 10:32:58

11

所有VCL的應用程序有一個叫做應用程序 「隱藏」 的頂層窗口。這是在應用程序啓動時自動創建的。除此之外,它是VCL的主要窗口消息處理程序 - 因此是Application.ProcessMessages。

隱藏應用程序頂層窗口確實會導致一些奇怪的事情,顯然是任務欄中顯示的不完整系統菜單以及Vista中不正確的縮略圖窗口。 Delphi的更新版本糾正了這一點。

但是,並非所有的窗口都必須將其作爲父窗口,否則Windows會更好地工作。 但是,使用Application.CreateForm創建的任何表單都將其作爲父級,並且它也將由Application對象擁有。由於他們是擁有的,他們將被釋放,一旦應用程序被釋放。這發生在Forms.DoneApplication的幕後。

+3

應用程序的頂級表單沒有將其父屬性設置爲「應用程序」窗口!只有所有者被設置爲應用程序對象。 只是澄清:Application.ProcessMessages處理主線程(所有VCL窗口)中所有窗口的消息,它實際上是在所有Windows GUI應用程序中找到的正常消息處理循環中的一個步驟。 – 2010-02-05 07:06:18

+0

@Ritsaert Hornstra:我的應用程序的頂級表格有哪些處理**?還要注意,我創建的任何表單都具有'Application.Handle'作爲它們的父類。 – 2010-02-05 14:02:50

+0

所以這可能是爲什麼http://www.saphua.com/minime/minime.aspx與我的delphi(7)應用程序無法正常工作。 +1的信息的金塊。 – cmw 2010-02-05 14:17:03