[英]How Can I Keep the FindDialog from Staying on Top (Delphi)?
在Delphi 2009中,我做了一個簡單的事情:
FindDialog.Execute;
FindDialog窗口保持在程序主窗口的頂部。
但是,如果我在我自己的程序窗口中打開來自其他程序的另一個窗口,則FindDialog窗口仍然位於另一個窗口的頂部。
如果我嘗試使用其他程序(例如記事本)的FindDialog,則不會發生這種情況。 在記事本和其FindDialog上打開另一個程序窗口將覆蓋Notepad和FindDialog窗口。 這似乎是正確和預期的行為。
這是我做錯了還是Delphi實現FindDialog的問題? 有什么我可以做到使記事本的方式工作?
謝謝大家的評論。 您無法重現我的問題的事實已經是一個線索,它是導致這種情況的其他原因。 這將有助於我追蹤它。 當我發現一些東西時,我會再研究一下並發布更多信息。
很有意思。 我的PrintDialog不會保持領先。 仍然不知道為什么我的FindDialog會這樣做。 還在研究......
我將調用更改為:FindDialog.Execute(Handle); 還是排在最前面。
我在我的主窗體中添加了另一個FindDialog(這次是FindDialog1),並在程序啟動時執行它。 它具有相同的保持最佳行為。 這至少表明它與我的FindDialog或我用它做的自定義沒有任何關系。 所以它必須是我主要形式的設置。
看起來我不是唯一一個遇到過這種情況的人。 請參閱: 資源調優器:版本歷史似乎是一個Delphi應用程序,在版本1.99下它指出:“修正:切換到另一個應用程序時,(搜索)對話框預覽窗口保持在頂部。” 我可能會嘗試聯系他們,看看他們是否記得他們的修復方法。
我在表單中添加了一些新的對話框,並將這些調用放在一個地方:
FindDialog1.Execute();
PrintDialog1.Execute();
ReplaceDialog1.Execute();
FontDialog1.Execute();
FindDialog和ReplaceDialog保持在其他窗口的頂部。 PrintDialog和FontDialog不會保持最佳狀態並且可以正常工作。
那么兩組對話框之間的區別是什么讓前兩個對話框出錯?
此外,這個問題發生在我的程序的舊版本,使用Delphi 4編譯
。哎呀。 現在我發現在我使用Delphi 4的舊版本中沒有發生這個問題。
並且是用戶報告了這個問題。 他使用的是Windows XP,而我正在開發Vista,所以它發生在不同的操作系統下。
確認:是的,我創建了一個新表單並在其上添加了FindDialog。 FindDialog沒有問題。 這表明我的程序中的某些東西導致FindDialog保持在最頂層。 現在,我必須找出那是什么。 還有什么想法嗎? 如果有人給我一個答案,甚至給我一個幫助我解決這個問題的線索,那么他們將得到接受的答案。
解決方案:Sertac對他的回答的編輯給了我解決方法:
Application.NormalizeTopMosts;
FindDialog.Execute();
Application.RestoreTopMosts;
這樣做可以防止FindDialog在應用程序不是TopMost時成為TopMost。
...但我仍然真的不理解這一點(Delphi幫助NormalizeTopMosts)非常混亂,並沒有表明它應該這樣做。
希望這個“修復”不會引起其他問題。
查看VCL代碼,查找對話框保持最佳狀態的唯一可能方式是,在調用“執行”時,已經存在最頂層的窗口。 這是它的編碼方式,對話框由'TRedirectorWindow'擁有,后者在應用程序中以z順序由頂部窗口擁有。 如果這個“頂部窗口”是最頂層的窗口,那么查找對話框也是。
procedure TForm1.Button1Click(Sender: TObject);
var
f: TForm;
begin
f := TForm.CreateNew(Self);
f.FormStyle := fsStayOnTop;
f.Show;
FindDialog1.Execute;
end;
要么,
procedure TForm1.Button1Click(Sender: TObject);
begin
FormStyle := fsStayOnTop;
FindDialog1.Execute;
FormStyle := fsNormal;
end;
上面的示例將創建一個最頂層的查找對話框。 但是一個保持頂級的形式可能不會被忽視,所以我想這不會是你的問題的根源。
在任何情況下,它或者你是以某種方式通過其他代碼片段改變對話框上的樣式。
順便說一句,不要費心測試將各種句柄傳遞給FindDialog1.Execute()
,它不會有效果,請看我對你的問題的評論。
編輯:
這個怎么樣:
procedure TForm1.Button4Click(Sender: TObject);
var
f: TForm;
begin
f := TForm.CreateNew(Self);
f.FormStyle := fsStayOnTop;
f.Show;
f.Hide;
FindDialog1.Execute;
end;
關鍵是, EnumThreadWindows
枚舉的窗口不一定是可見的。 因此,任何現有的stay-on-top表單都可能導致查找對話框顯示此行為。
更好的測試和看到比猜測。 在啟動“查找”對話框之前運行以下測試。 這包含邏輯'dialogs.pas'執行以查找對話框作為基礎,並且如果對話框將最頂層,則會引發異常。
function EnumThreadWndProc(hwnd: HWND; var lParam: LPARAM): Bool; stdcall;
var
Window: TWinControl;
begin
Result := True;
Window := FindControl(hwnd);
if Assigned(Window) and (Window is TForm) then begin
Result := False;
lParam := Longint(Window);
end;
end;
procedure TForm1.Button6Click(Sender: TObject);
var
OnTopForm: Longint;
begin
OnTopForm := 0;
EnumThreadWindows(GetCurrentThreadId, @EnumThreadWndProc, LPARAM(@OnTopForm));
// if (OnTopForm <> 0) and (TForm(OnTopForm).FormStyle = fsStayOnTop) then
if (OnTopForm <> 0) and (GetWindowLong(TForm(OnTopForm).Handle,
GWL_EXSTYLE) and WS_EX_TOPMOST = WS_EX_TOPMOST) then
raise Exception.Create('darn! got one: ' + TForm(OnTopForm).Name);
end;
另一個測試可能是在啟動對話框之前調用應用程序的NormalizeTopMosts
,但我知道在某些Delphi版本中,這種方法已被破壞而且無法正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.