2011-03-21 85 views
6

德爾福2009年,我做了一個簡單:如何讓FindDialog保持最佳狀態(Delphi)?

FindDialog.Execute; 

的FindDialog的窗口上我的程序的主窗口頂部停留,因爲它應該。

但是,如果我通過自己的程序窗口從其他程序打開另一個窗口,則FindDialog窗口將保留在另一個窗口的頂部。

如果我用另一個程序(例如記事本)中的FindDialog試試這個,這不會發生。在記事本和FindDialog上打開另一個程序的窗口將覆蓋記事本和FindDialog窗口。這似乎是正確和預期的行爲。

這是我做錯了什麼,或者這是一個問題,德爾福實施FindDialog的方式?有什麼我可以做,使其工作記事本的方式?


謝謝大家的意見。你不能再現我的問題的事實已經是一個線索,這是其他事情造成的。這將幫助我追蹤它。我會研究多一點,並在發現一些事情時在此發佈更多信息。


非常有趣。我的PrintDialog不能保持在最前面。仍然不知道爲什麼我的FindDialog。仍在研究...


我將調用改爲:FindDialog.Execute(Handle);仍然在最上面。


我添加了另一個FindDialog(這次FindDialog1)到我的主窗體中,並在我的程序啓動時執行它。它具有相同的頂級行爲。這至少表明這與我的FindDialog或我所做的自定義無關。所以它一定是我的主要形式。


它看起來不像我是唯一遇到過這種情況的人。請參閱:Resource Tuner: Version History它似乎是一個Delphi應用程序,其版本1.99中指出:「修正:當切換到另一個應用程序時,(搜索)對話框預覽窗口保持最前端。」我可能會嘗試與他們聯繫,看看他們是否會記住他們的修補程序。


我增加一些新的對話,以我的形式,把這些電話在一個地方:

FindDialog1.Execute(); 
PrintDialog1.Execute(); 
ReplaceDialog1.Execute(); 
FontDialog1.Execute(); 

的FindDialog的和ReplaceDialog留在上面的其他窗口的前面。 PrintDialog和FontDialog不會保持最佳狀態並按照他們應該的方式工作。

那麼這兩組對話框之間有什麼不同,使前兩個對話框做錯了?


而且,這個問題發生在舊版本我的程序,將其與德爾福4 哎呦編譯。現在我發現這個問題在使用Delphi 4的舊版本中沒有發生。

而且是一位報告此問題的用戶。他使用Windows XP,而且我正在開發Vista,所以它發生在不同的操作系統下。


確認:是的,我創建一個新窗體並在其上添加一個FindDialog。 FindDialog沒有問題。這表明我的程序中的某些內容導致FindDialog保持最佳狀態。現在,我只需要知道那是什麼。還有什麼想法?如果有人給我一個答案,甚至給我一個線索來幫助我解決這個問題,那麼他們會得到接受的答案。


解決方案:Sertac的編輯給他的回答給我的解決方法:

Application.NormalizeTopMosts; 
    FindDialog.Execute(); 
    Application.RestoreTopMosts; 

這樣做可以防止FindDialog的被最頂層的應用程序時,不在最上方。

...但我仍然真的不明白這一點(在NormalizeTopMosts德爾福的幫助)是非常混亂,並不表示它應該這樣做。

希望這個「修復」不會導致其他問題。

+4

無法重現此(D2009完全更新)。同時使用'FindDialog1.Execute;'和'FindDialog1.Execute();'這應該導致沒有傳入的句柄。當我打開查找對話框,然後打開一些其他應用程序(記事本在我的情況),並將其移過我的帶有對話框的Delphi應用程序,其主窗口和查找對話框都被記事本窗口覆蓋。 – 2011-03-21 07:44:20

+1

我可能在這裏誤解了一些東西,但我無法在Delphi XE中重現。 – 2011-03-21 07:46:38

+2

FWIW我無法在D2010中重現此行爲。你是否將HWND傳遞給Execute方法?如果不嘗試傳遞主窗體的句柄,看看是否有幫助。 – 2011-03-21 07:53:40

回答

3

查看VCL代碼時,查找對話框保持最前面的唯一可能方式是,調用「執行」時已經有最頂層的窗口。這是如何編碼的,對話由'TRedirectorWindow'擁有,'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枚舉。因此,任何現有的頂級窗體都可能導致查找對話框出現此行爲。

更好的測試,看看比猜。在啓動查找對話框之前運行下面的測試。這包含了邏輯'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,但我知道一些德爾福版本的這種方法被打破,並沒有做自己的工作。

+0

嗯。我確實有3種FormStyle形式:= fsStayOnTop,但是這些都是特殊功能形式(如我的關於框),當發生此問題時,它們還未打開。雖然你的回答讓我思考。謝謝。 – lkessler 2011-03-22 03:23:43

+0

+1發現不錯:) – jachguate 2011-03-22 18:24:06

+0

NormalizeTopMosts似乎爲我解決它。看到我編輯的答案。感謝塞爾特克! – lkessler 2011-03-23 05:04:21

相關問題