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

标签 wpf delphi dll delphi-7 z-order

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

同一时刻只能打开一个DLL窗口。

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

这会导致应用程序无响应。无法单击任何内容,无法关闭,无法最小化。必须通过任务管理器杀死。

在Delphi中,我看到有Screen对象,它有一个列表Forms。我检查了它,发现它保存了我的应用程序当前打开的所有表单(甚至是 ShowMessage() 的结果消息框,它没有名称,但我可以看到 类名)。

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

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

最佳答案

您必须遵循操作系统对窗口进行排序的方式(使用句柄)。默认情况下,DLL 的应用程序句柄为零,因此您需要在显示模式对话框时定义它。

根据文档Vcl.Forms.TApplication.Handle :

Note: When writing a DLL that uses VCL forms, assign the window handle of the host EXE's main window to the Handle property of the DLL's global Application variable. This makes the DLL's form part of the host application. Never assign to the Handle property in an EXE.

要维护 dll 模态形式的 Z 顺序,请按照 Peter Below suggests 进行操作:

// 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;

关于wpf - 如何获取打开的窗口列表,包括 Delphi 应用程序中的 DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21523410/

相关文章:

sql - 数据库结果的可变结构

windows - 在 Windows 上重命名 DLL

c# - .dll 文件不可访问

c++ - 在 linux 中使用为 windows 编写的软件库(使用 dll)

c# - 配置 Caliburn 以自动附加 Loaded、Unloaded 事件

c# - 以编程方式设置 WPF 中 ContentControl 的内容

c# - WPF:网格中的 ScrollViewer

c# - 调试期间不显示图像

delphi - 如何以编程方式找出BDE共享存储区的实际位置和大小?

delphi - ARC : is there a memory leak in TNetEncoding. 获取Base64Encoding?