在Delphi 2009中,我做了一个简单的事情:
FindDialog.Execute;
FindDialog窗口保持在程序主窗口的顶部。
但是,如果我在我自己的程序窗口中打开其他程序的另一个窗口,则FindDialog窗口会保留在另一个窗口的顶部。
如果我使用其他程序(例如记事本)的FindDialog尝试此操作,则不会发生这种情况。在记事本和其FindDialog上打开另一个程序窗口将覆盖Notepad和FindDialog窗口。这似乎是正确和预期的行为。
这是我做错了还是Delphi实现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不会保持最佳状态并按预期工作。
那么前两个对话框之间有什么不同呢?
另外,这个问题发生在我用Delphi 4编译的程序的旧版本中。哎呀。现在我发现在我使用Delphi 4的旧版本中没有发生这个问题。
是用户报告了这个问题。他使用的是Windows XP,我正在开发Vista,所以它发生在不同的操作系统下。
确认:是的,我创建了一个新表单并在其上添加了FindDialog。 FindDialog没有问题。这表明我的程序中的某些东西导致FindDialog保持在最顶层。现在,我必须找出那是什么。还有什么想法吗?如果有人给我一个答案,甚至给我一个帮助我解决这个问题的线索,那么他们就会得到接受的答案。
解决方案:Sertac对他的回答的编辑给了我解决方法:
Application.NormalizeTopMosts;
FindDialog.Execute();
Application.RestoreTopMosts;
执行此操作可防止FindDialog在应用程序不是TopMost时成为TopMost。
...但我仍然不明白这一点(Delphi对NormalizeTopMosts的帮助)非常混乱,并没有表明它应该这样做。
希望这个“修复”不会引起其他问题。
答案 0 :(得分:3)
查看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版本中,这种方法已被破坏而且无法正常工作。