加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何让FindDialog保持最佳状态(Delphi)?

发布时间:2020-12-15 09:51:42 所属栏目:大数据 来源:网络整理
导读:在Delphi 2009中,我做了一个简单的事情: FindDialog.Execute; FindDialog窗口保持在程序主窗口的顶部. 但是,如果我在我自己的程序窗口中打开来自其他程序的另一个窗口,则FindDialog窗口仍然位于另一个窗口的顶部. 如果我使用其他程序(例如记事本)的FindDial
在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)非常混乱,并没有表明它应该这样做.

希望这个“修复”不会引起其他问题.

解决方法

查看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表单都可能导致find对话框出现这种行为.

更好的测试和看到比猜测.在启动“查找”对话框之前运行以下测试.这包含逻辑’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版本中,这种方法已被破坏而且无法完成其工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读