Search code examples
delphidlldirectorydelphi-7

Delphi file directory selection (from DLL) brings other window in front of the current application?


I am maintainig Delphi 6 legacy software and it uses the following file directory selection function from the 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;

I can not use file directory selection Delphi 6 function because Delphi 6 has not such function of if it has, it is greatly outdated and unusable. So - I am using function from the DLL. But after call of this function, the other window (it may be Windows Explorer or other application) becomes active and stays in front of my current Delphi 6 application from which I call directory selection function. What's going on and how to avoid that?

When I call my _SelectDirectory function from Delphi 2009 application (and not from DLL), then all is OK, the current application remains the active one. So, the use of DLL causes the problem. I use dynamic loading of my DLL:

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

Maybe I can fine to the loading of Delphi 2009 DLL into Delphi 6 application in such way, that the current Delphi 6 application remains the active one even aftar call of DLL function.


Solution

  • I can not use file directory selection Delphi 6 function because Delphi 6 has not such function

    Yes, it does: FileCtrl.SelectDirectory(). Just be sure to use the 2nd overloaded version that has a Root parameter. That overload displays a modern system dialog using the Win32 SHBrowseForFolder() function. The other overload displays an older Win3.1-style VCL dialog instead.

    Alternatively, TFileOpenDialog.Execute() has an optional HWND parameter to specify the owner window for the dialog. Have your calling D6 code pass in the active TForm.Handle for that window.

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

    When I call my _SelectDirectory function from Delphi 2009 application (and not from DLL), then all is OK, the current application remains the active one.

    In that situation, TFileOpenDialog has access to the app's TApplication and active TForm objects and can pick a default owner HWND from between them. But when you call TFileOpenDialog from inside a DLL, it can't do that anymore, so you have to be more explicit about which owner HWND to use.