[英]Delphi, how to make independent windows
我有一個使用Chrome瀏覽器等標簽的應用程序。 現在我希望能夠打開更多表格而不僅限於一種表格。 這些表格應該是相同的,但如果我關閉主表格,所有表格都將被關閉。 如何使所有表格都相同,所以無論我關閉哪種表格,只關閉該表格而不是在所有表格關閉之前退出申請表? 有任何想法嗎?
親切的問候Roy M Klever
這樣做並不難,盡管它會根據你想要的完整程度而迅速變得復雜。 讓多個模態對話框獨立工作是一項艱巨的任務。
首先,您需要完全避免Application.MainForm。 始終使用Form := TMyForm.Create(Application)
而不是Application.CreateForm(TMyForm, Form)
。 后者設置了MainForm,你永遠不希望這種情況發生。
要使事情正常關閉,您需要在表單的OnClose
事件處理程序中執行以下操作:
if Screen.FormCount = 1 then
Application.Terminate;
CloseAction := caFree;
Application.Run
依賴於MainForm的分配,因此在你的DPR中用這個循環替換該行:
repeat
try
Application.HandleMessage;
except
Application.HandleException(Application);
end;
until Application.Terminated;
有幾種方法可以處理任務欄條目。
單個任務欄條目:設置Application.MainFormOnTaskbar := False;
並將使用隱藏的TApplication句柄。 單擊任務欄條目將使所有窗口都顯示在前面。 您需要覆蓋Application.OnMessage
或添加TApplicationEvents
組件,並使用Msg.Handle = Application.Handle`監視WM_CLOSE
。 在這種情況下,用戶右鍵單擊任務欄並選擇關閉 ,因此您應該關閉所有窗口。
多個任務欄條目:設置Application.MainFormOntaskbar := True
。 覆蓋表單的CreateParams
方法並設置Params.WndParent := 0;
。 每個任務欄條目都將控制該表單。
可能還有其他一些問題,但這是基礎知識。
正如我所說,使ShowModal
和TOpenDialog/TSaveDialog
獨立工作,因此它只影響其父窗體,因此可以同時打開多個對話框,這是TOpenDialog/TSaveDialog
工作,我不能真正推薦它。 如果你是一個受虐狂,這里是一般步驟:
用自定義版本替換TCustomForm.ShowModal
。 除此之外,該例程禁用了應用程序中的所有其他窗口,因此您需要使用EnableWindow(Owner.Handle, False/True)
替換DisableTaskWindows/EnableTaskWindows
調用以僅禁用父窗體。 此時,您可以打開多個對話框,但它們只能以后進先出順序關閉,因為調用最終是遞歸的。 如果沒關系,請停在這里。
有兩種方法可以解決這個問題:
不要使ShowModal
阻塞,而是讓StartModal
和EndModal
例程具有ShowModal代碼的第一位和最后一位,並在關閉對話框時調用OnShowModalDone
事件。 這是一種使用起來很痛苦,但相對容易編碼並且易於穩定。
使用Windows 光纖例程交換堆棧並啟動新的消息循環。 這種方法很容易使用,因為ShowModal
是阻塞的,所以你可以ShowModal
調用它。 這是我們在Beyond Compare中使用的方法。 不要這樣做。 這是復雜的寫, 會有 ,因為與第三方代碼不兼容的不平凡的應用程序(Windows全局消息鈎子,TWebBrowser,.NET在通過瀏覽對話框加載的外殼擴展,等等)的穩定性的問題,如果它是一個跨平台項目,Unix ucontext函數也不安全。
常見對話框(TOpenDialog,TColorDialog等)具有類似的限制。 要使它們只禁用父窗體,您需要覆蓋TCommonDialog.TaskModalDialog
並在DisableTaskWindows/EnableTaskWindows
替換DisableTaskWindows/EnableTaskWindows
調用。 它們不能像上面的常規Delphi對話那樣異步,因為它們阻止了Windows提供的功能( GetOpenFileName , ChooseColor等)。 允許那些以任何順序關閉的唯一方法是讓每個對話框在專用線程中運行。 只要您小心訪問VCL對象,Windows就可以處理大部分同步,但它基本上涉及重寫Dialogs.pas
。
如果你真的想要那個,
1)使用一個小的,可能是隱藏的MainForm,並在啟動時啟動第一個子窗體。
2)在同一進程中啟動單獨的應用程序而不是Windows。 這是Office后來使用的版本。
這是一個類似的StackOverflow問題: 多個應用程序窗口激活無法正常工作
在我的情況下,我不會像Craig描述的那樣避免使用MainForm。 相反,我隱藏了主窗口,我所有的真實窗口都是其他非模態窗體。 我對我的應用程序如何工作感到滿意,但Craig的方法可能更簡單。
請參閱我對上述問題的回答,查看我的方法的代碼示例以及一些具有良好背景信息的鏈接。
在Delphi應用程序中創建的第一個表單被視為主表單,當該表單關閉時應用程序終止。 顯而易見的解決方案是使第一個表單不是由用戶關閉的表單,而是用戶不可見的表單,並且僅在所有其他表單都已關閉時才關閉。
我沒試過這個,但它應該有效。
這已經來不及回答,但我遇到了同樣的問題。 我選擇的解決方案是提取Application.ExeName
並將其傳遞給createProcess
甚至shellExecute
類的函數。 所以,現在我在OS級別擁有獨立的應用程序。 我還需要不同實例的不同任務欄按鈕。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.