我的应用程序可以加载基本上包含另一个窗口应用程序的 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/