如何获取打开的窗口列表,包括Delphi应用程序中的DLL

时间:2014-02-03 09:16:12

标签: wpf delphi dll delphi-7 z-order

我的应用程序可以加载基本上包含另一个窗口应用程序的DLL。

它只能随时打开一个DLL窗口。

我遇到DLL窗口显示消息框和/或我的主应用程序显示消息框或模态窗体的情况,并通过停用应用程序(切换到另一个)然后激活它,移动所有窗口随机(?)z顺序,从而使DLL形式与它的消息框在主窗体后面。主表单消息框位于主表单后面。

这导致无响应的应用程序。不能点击任何东西,不能关闭,不能最小化。必须通过任务管理器杀死。

在Delphi中,我看到有Screen个对象,它有一个列表Forms。我检查了它,看到它包含我的应用程序当前打开的所有表单(即使是消息框,这是ShowMessage()的结果,它没有名称,但我可以看到ClassName)。

到目前为止它很好,我可以遍历表单并使用SetWindowPos告诉他们正确的z顺序,但是,我不能为DLL应用程序执行此操作。 Screen在列表中没有此表单。

如何控制DLL表单的z顺序?
这些DLL是使用Delphi,C ++,WPF构建的。

1 个答案:

答案 0 :(得分:4)

您必须按照OS的方式订购窗口(使用句柄)。 DLL的应用程序句柄默认为零,因此您需要在显示模式对话框时定义它。

根据文件Vcl.Forms.TApplication.Handle

  

注意:编写使用VCL表单的DLL时,请将主机EXE主窗口的窗口句柄指定给DLL的全局Application变量的Handle属性。这使得DLL的形式成为宿主应用程序的一部分。永远不要在EXE中分配Handle属性。

要保持dll模态形式的Z顺序,请按下面suggests下面的Peter:

// In the dll
var
  oldWnd: HWND;
begin
  oldWnd := Application.Handle;
  Application.Handle := HandleOfHostform; // <-- Pass the exe host form handle
  try
    .... create and show the DLL form
  finally
    Application.Handle := oldWnd;
  end;
end;

应该在没有所有者TMyDllForm.Create(nil)的情况下创建模态表单。


我不是100%确定Delphi-7正确地以这种方式解析DLL中的句柄。 另一种方法是覆盖表单对象的CreateParams,如建议here

procedure TMyDLLForm.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.WndParent := HandleOfHostForm;
end;