How can I keep FindDialog from staying on top (Delphi)?

In Delphi 2009, I do simply:

FindDialog.Execute; 

The FindDialog window remains on top of the main window of my program, as it should be.

However, if I open another window from any other program in my own program window, the FindDialog window will remain on top of the other window.

If I try this using FindDialog from another program (for example, Notepad), this will not happen. Opening another program window above Notepad and its FindDialog will span the Notepad and FindDialog windows. This is apparently the correct and expected behavior.

Am I doing something wrong or is it a problem with how Delphi implemented FindDialog? Is there something I can do to make it work with Notepad?


Thanks everyone for the comments. The fact that you cannot reproduce my problem is already the key to the fact that something else is causing this. This will help me track it. I will study a little more and post additional information here when I find out something.


Very interesting. My PrintDialog does not stay on top. Still don't know why my FindDialog. Another study ...


I changed the call to: FindDialog.Execute (Handle); Still on top.


I added another FindDialog (this time FindDialog1) to my main form, and I run it when my program starts. He has the same behavior in place. This, at least, indicates that it had nothing to do with my FindDialog or the settings I made for this. So this should be a setup in my main form.


It doesn't seem like I'm the only one that came across this. See: Resource Tuner: Version history , which appears to be a Delphi application, which says in version 1.99: “Bugfix: preview (search)" the window remained at the top when switching to another application. "I can try to contact them and see whether they can remember what to fix them.


I add a few new dialogs to my form and put these calls in one place:

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

FindDialog and ReplaceDialog remain on top of other windows. PrintDialog and FontDialog do not stay on top and work as they should.

So what is the difference between the two sets of dialogs that make the first two wrong?


In addition, this problem occurs in the old version of my program, which was compiled using Delphi 4. Oops. Now I see that this problem did not occur in my old version that used Delphi 4.

And it was the user who reported this problem. It uses Windows XP, and I am developing in Vista, so this happens under different OSs.


Confirmation: Yes, I create a new form and add FindDialog. FindDialog does not have this problem. This indicates that what happens in my program is that FindDialog stays on top. Now, I just have to figure out what it is. Any other ideas? If someone gives me an answer that even gives me a key to help me solve this, then they will get the accepted answer.


Solution: Sertac, editing his answer, gave me a workaround:

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

Doing this prevents FindDialog from being TopMost when the application is not TopMost.

... But I still really don't understand this (Delphi help on NormalizeTopMosts) is very confusing and does not indicate that it should do this.

I hope this "fix" does not cause other problems.

+6
delphi dialog stayontop
source share
1 answer

Looking at the VCL code, the only possible way to find the Find dialog box is at the top; there is already the topmost window when Run is called. This is how it is encoded, the dialog becomes owned by "TRedirectorWindow", which gets the belonging to the top window in z-order in the application. If this "top window" is the topmost window, then there is also a search dialog.

 procedure TForm1.Button1Click(Sender: TObject); var f: TForm; begin f := TForm.CreateNew(Self); f.FormStyle := fsStayOnTop; f.Show; FindDialog1.Execute; end; 

or,

 procedure TForm1.Button1Click(Sender: TObject); begin FormStyle := fsStayOnTop; FindDialog1.Execute; FormStyle := fsNormal; end; 


The above examples will create the highest search dialog. But the form of staying on top might not go unnoticed, so I think that would not be the source of your problem.

In any case, this is either that, or you somehow change the styles in the dialog with some other part of the code.


By the way, do not bother checking the passage of various descriptors to FindDialog1.Execute() , this will not affect my comments on your question.

change

How about this:

 procedure TForm1.Button4Click(Sender: TObject); var f: TForm; begin f := TForm.CreateNew(Self); f.FormStyle := fsStayOnTop; f.Show; f.Hide; FindDialog1.Execute; end; 

The fact is that the window must not be visible in order to get the EnumThreadWindows enumeration. Thus, any existing breakpoint at the top can trigger a search dialog that demonstrates this behavior.

Better to check and see than to guess. Run the test below before starting the search dialog. This includes the logic "dialogs.pas" to find the base dialog box, and will throw an exception if the dialog is the largest.

 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; 


Another test may be to call the application's NormalizeTopMosts before starting a dialog, but I know that with some versions of Delphi this method is broken and does not do its job.

+3
source share

All Articles