首页 > 解决方案 > Delphi文件目录选择(来自DLL)在当前应用程序前面带来了其他窗口?

问题描述

我是维护 Delphi 6 旧版软件,它使用 Delphi 2009 DLL 中的以下文件目录选择功能:

function _SelectDirectory(ADirPath: ShortString): ShortString;
var OpenDlg: TFileOpenDialog;
begin
  Result:='';
  OpenDlg:=TFileOpenDialog.Create(nil);
  try
    OpenDlg.Options:=OpenDlg.Options+[fdoPickFolders];
    if DirectoryExists(ADirPath) then
      OpenDlg.DefaultFolder:=ADirPath;
    if OpenDlg.Execute then begin
      Result:=OpenDlg.FileName;
    end;
  finally
    OpenDlg.Free;
  end;
end;

我不能使用Delphi 6的文件目录选择功能,因为Delphi 6没有这个功能,如果有的话,它已经过时且无法使用。所以 - 我正在使用 DLL 中的函数。但在调用此函数后,另一个窗口(可能是 Windows 资源管理器或其他应用程序)变为活动状态并停留在我当前调用目录选择功能的 Delphi 6 应用程序前面。发生了什么以及如何避免这种情况?

当我从 Delphi 2009 应用程序(而不是从 DLL)调用我的 _SelectDirectory 函数时,一切正常,当前应用程序仍然是活动的。因此,使用 DLL 会导致问题。我使用动态加载我的 DLL:

ImpLib:=LoadLibrary(LibraryName);
@TmpSelectDirectory:=GetProcAddress(ImpLib, '_SelectDirectory');
TmpSelectDirectory(ADirPath);

也许我可以通过这种方式将 Delphi 2009 DLL 加载到 Delphi 6 应用程序中,以使当前的 Delphi 6 应用程序在调用 DLL 函数后仍然保持活动状态。

标签: delphidlldirectorydelphi-7

解决方案


我不能使用文件目录选择 Delphi 6 功能,因为 Delphi 6 没有这个功能

是的,它确实:FileCtrl.SelectDirectory(). 请务必使用具有Root参数的第二个重载版本。SHBrowseForFolder()该重载使用 Win32函数显示一个现代系统对话框。另一个重载改为显示较旧的 Win3.1 样式的 VCL 对话框。

或者,TFileOpenDialog.Execute()有一个可选HWND参数来指定对话框的所有者窗口。让您的调用 D6 代码在该TForm.Handle窗口的活动中传递。

function _SelectDirectory(Owner: HWND; ADirPath: ShortString): ShortString;
var
  ...
begin
  ...
  if OpenDlg.Execute(Owner) then
  ... 
end;
ImpLib := LoadLibrary(LibraryName);
@TmpSelectDirectory := GetProcAddress(ImpLib, '_SelectDirectory');
TmpSelectDirectory(MyForm.Handle, ADirPath);

当我从 Delphi 2009 应用程序(而不是从 DLL)调用我的 _SelectDirectory 函数时,一切正常,当前应用程序仍然是活动的。

在这种情况下,TFileOpenDialog可以访问应用程序TApplication和活动对象,并且可以从它们之间TForm选择一个默认所有者。HWND但是当您TFileOpenDialog从 DLL 内部调用时,它不能再这样做了,因此您必须更明确地确定HWND要使用哪个所有者。


推荐阅读