FindDialog如何保持在顶部(Delphi)? [英] How Can I Keep the FindDialog from Staying on Top (Delphi)?

查看:241
本文介绍了FindDialog如何保持在顶部(Delphi)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Delphi 2009中,我做了一个简单的例子:

In Delphi 2009, I do a simple:

FindDialog.Execute;

FindDialog窗口保持在程序主窗口的顶部,因为它应该。

The FindDialog window stays on top of my program's main window as it should.

但是,如果我通过我自己的程序的窗口从其他程序打开另一个窗口,FindDialog窗口将保持在另一个窗口的顶部。

However, if I open another window from some other program over my own program's window, the FindDialog window remains on top of the other window.

如果我用另一个程序(例如记事本)的FindDialog来尝试这个,那不会发生。在记事本上打开另一个程序的窗口,其FindDialog将覆盖记事本和FindDialog窗口。这似乎是正确的和预期的行为。

If I try this with a FindDialog from another program (e.g. Notepad), this does not happen. Opening another program's window over Notepad and its FindDialog will cover both the Notepad and FindDialog windows. This seems to be the correct and expected behavior.

这是我做错了,这是Delphi实现FindDialog的方式的问题吗?有没有什么可以做的,使其工作的记事本方式?

Is this something I'm doing wrong or is this a problem with the way Delphi has implemented the FindDialog? Is there something I can do to make it work the Notepad way?

感谢大家的评论。事实上,你无法重现我的问题已经是一个线索,这是其他的造成这个。这将有助于我跟踪它。我会研究一点,并发现其他信息,当我发现一些东西。

Thank you all for the comments. The fact that you cannot reproduce my problem is already a clue that it is something else causing this. This will help me track it down. I'll research a little more and post additional info here when I find out something.

非常有趣。我的PrintDialog不会保持在顶部。仍然不知道为什么我的FindDialog。仍在研究...

Very interesting. My PrintDialog doesn't stay on top. Still don't know why my FindDialog does. Still researching...

我将调用更改为:FindDialog.Execute(Handle);仍然在上面。

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

我添加了另一个FindDialog(这次FindDialog1)到我的主窗体,我在启动时执行我的程序它具有相同的待机行为。这至少表明它与我所做的FindDialog或自定义设置无关。所以它必须是我的主要形式的设置。

I added another FindDialog (this time FindDialog1) to my main form and I execute it at startup of my program. It has the same stay-on-top behavior. That at least indicates it wasn't anything to do with my FindDialog or customizations I made to do with it. So it must be a setting in my main form.

看起来不像我是唯一一个遇到这个请参阅:资源调优器:版本历史,它似乎是Delphi应用程序,其中版本1.99它说:修复:切换到另一个应用程序时,(搜索)对话框预览窗口保持在顶部。我可能会尝试联系他们,看看他们是否可以记住他们的修复程序。

It doesn't look like I'm the only one who's encountered this. See: Resource Tuner: Version History which appears to be a Delphi application, where under Version 1.99 it states: "Bugfix: The (search) dialog preview window stayed on top when switching to another application." I might try contacting them and see if they might remember what their fix was.

我向我的表单添加了一些新的对话框并将这些电话放在一个地方:

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

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

FindDialog和ReplaceDialog保留在其他窗口的前面。
PrintDialog和FontDialog不要保持在顶部并且按照他们的方式工作。

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

那么两组对话框之间有什么区别呢?它是错的?

So what is different between the two sets of dialogs that make the first two do it wrong?

此外,这个问题发生在我的程序的旧版本,它是用Delphi 4编译的不好意思。现在我看到这个问题没有发生在我使用Delphi 4的旧版本中。

Also, this problem happens in an old version of my program that was compiled with Delphi 4. Whoops. Now I see this problem did not happen in my old version that used Delphi 4.

而且这是一个报告了这个问题的用户。他使用Windows XP,而且我正在Vista上开发,所以它发生在不同的操作系统之下。

And it was a user who reported this problem. He uses Windows XP, and I'm developing on Vista, so it happens under different OS's.

确认:是的,我创建一个新表单并添加一个FindDialog。 FindDialog没有问题。这表明我的程序中的东西导致FindDialog保持在顶部。现在,我刚刚找出是什么。还有什么想法?如果有人给我一个答案,甚至给我一个线索来帮助我解决这个问题,那么他们会得到接受的答案。

Confirmation: Yes, I create a new form and add a FindDialog on it. The FindDialog does NOT have the problem. This indicates something in my program is causing the FindDialog to stay on top. Now, I've just got to find out what that is. Any more ideas? If someone gives me an answer that even gives me a clue to help me solve this, then they'll get the accepted answer.

解决方案:Sertac对他的答案的编辑给了我解决方法:

Solution: Sertac's edit to his answer gave me the workaround:

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

当应用程序不是TopMost时,这样做可以防止FindDialog成为TopMost。

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

...但是我仍然不明白(Delphi对NormalizeTopMosts的帮助)非常混乱,并不表示应该这样做。

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

希望这个修复不会引起其他问题。

Hopefully this "fix" won't cause other problems.

推荐答案

查看VCL代码, 查找对话框唯一可能的方法是在执行被调用时已经是最顶层的窗口。这是如何被编码的,对话框由一个TRedirectorWindow所拥有,它被应用程序中z顺序的顶层窗口所拥有。如果这个顶级窗口是最顶层的窗口,那么查找对话框也是。

Looking at the VCL code, the only possible way a Find Dialog Box stays on top is, there's already a top-most window when 'Execute' is called. This is how it is coded, the dialog gets owned by a 'TRedirectorWindow' which gets owned by the top window in z-order in the application. If this 'top window' is a top-most window then the find dialog also is.

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;


上述示例将创建最顶尖的查找对话框。但是,一个顶级的表单可能不会被忽视,所以我想这不会是你的问题的根源。


The above samples will create a top-most find dialog. But a stay-on-top form possibly wouldn't go unnoticed, so I guess this wouldn't be the source of your problem.

无论如何,它是或者你以某种方式通过其他代码片段更改对话框中的样式。

In any case, it is either that or you're somehow changing the styles on the dialog by some other code piece.


BTW,不要打扰测试传递各种句柄到code> FindDialog1.Execute(),它不会有效果,请查看我对您的问题的评论。


BTW, do not bother testing passing various handles to FindDialog1.Execute(), it won't have an effect, see my comment to your question.

编辑:

这一个如何:

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



< http://msdn.microsoft.com/en-us/library/ms633495%28v=vs.85%29.aspxrel =nofollow> EnumThreadWindows 。所以任何现有的留在页面上的表单都可能导致查找对话框显示这种行为。

The point is, a window does not have to be visible to get enumerated by EnumThreadWindows. So any existing stay-on-top form could cause the find dialog to exhibit this behavior.

更好的测试和看到比猜测。在启动查找对话框之前,运行以下测试。这包含逻辑dialogs.pas执行以找到对话框的基础,如果该对话框最顶层,将引发异常。

Better test and see than to guess. Run the below test just before you launch your Find Dialog. This incorporates the logic 'dialogs.pas' performs to find the dialog a base, and would raise an exception if the dialog would go top-most.

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版本的这个方法是坏的,不做它的工作。


One other test could be to call NormalizeTopMosts of the Application before launching the dialog, but I know with some Delphi versions this method is broken and does not do its job.

这篇关于FindDialog如何保持在顶部(Delphi)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆