0

I would like to modernize the GUI of my Delphi 7 App, I have already .manifest file and it looks quite good, but the Fileopen dialogs are terrible. How the make them modern?

I am using this code at the moment. What would it require to use e.g. IFileOpenDialog instead, how to compile the header for that, or any tweaks to dialogs.pas ?

FileOpenDialog := TOpenDialog.create(parent);
FileOpenDialog.DefaultExt := '*.x';
FileOpenDialog.Filter := 'my|*.x|Text File (CSV)|*.csv'; 
FileOpenDialog.options := [ofHideReadOnly,ofFileMustExist  ,ofNoChangeDir,ofPathMustExist   ];
if FileOpenDialog.Execute then begin
    // do my tricks with FileOpenDialog.filename
    FormUpdate;
end;

The following example code of IFileDialog cannot be compiled with D7:

var
  FolderDialog : IFileDialog;
  hr: HRESULT;
  IResult: IShellItem;
  FileName: PChar;
  Settings: DWORD;
begin
  if Win32MajorVersion >= 6 then
    begin
      hr := CoCreateInstance(CLSID_FileOpenDialog,
                   nil,
                   CLSCTX_INPROC_SERVER,
                   IFileDialog,
                   FolderDialog);

      if hr = S_OK then
        begin
          FolderDialog.SetOkButtonLabel(PChar('Select'));
          FolderDialog.SetTitle(PChar('Select a Directory'));

          hr := FolderDialog.Show(Handle);
          if hr = S_OK then
            begin
              hr := FolderDialog.GetResult(IResult);

              if hr = S_OK then
                begin
                  IResult.GetDisplayName(SIGDN_FILESYSPATH,FileName);
                  ConfigPathEdit.Text := FileName;
                end;
            end;
        end;
    end;
Tom
  • 6,725
  • 24
  • 95
  • 159
  • Delphi 7 doesn't support the new dialogs out of the box. If you don't find any 3rd party controls you are probably on your own implementing all what it needs. You may consider upgrading your Delphi version. – Uwe Raabe Feb 04 '22 at 08:31
  • Here's a great place to start: https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ifiledialog – Andreas Rejbrand Feb 04 '22 at 08:31
  • It's quite easy to patch the VCL so that the new dialogs are shown, even with the GetOpenFileName based wrappers. However, it's better to use IFileDialog because it supports arbitrary length multi select dialogs. – David Heffernan Feb 04 '22 at 08:39
  • I gave up with the Windows dialogue and ended up doing my own, in a form, where I can have user-configurable shortcut buttons and autocomplete recursive search. It's not difficult to do. – MyICQ Feb 04 '22 at 11:29
  • Is there any example how to use iFileDialog with Delphi7 ? – Tom Feb 04 '22 at 11:34
  • @Tom Sure. Welcome to StackOverflow - it also supports [searching for i.e. `iFileDialog [Delphi]`](https://stackoverflow.com/search?q=iFileDialog+%5BDelphi%5D), which then has [this answer](https://stackoverflow.com/a/11260116/4299358) as one of its results. – AmigoJack Feb 04 '22 at 11:44
  • @AmigoJack: But of course, `IFileDialog` isn't defined in the Delphi 7's Win32 units. – Andreas Rejbrand Feb 04 '22 at 11:58
  • Thanks I was looking for it earlier but failed to compile; How can I define IFileDialog I am getting [Error] Undeclared identifier: 'IFileDialog' – Tom Feb 04 '22 at 12:02
  • `IFileDialog` is an interface that modern Delphi versions define in `Winapi.ShlObj` unit. Dehlpi 7 does not have such unit. But as far as I remember all Win API function relate to Shell in Delphi 7 are declared in `Shell32.pas` unit or something similar. So I recommend you start looking there. – SilverWarior Feb 04 '22 at 12:37
  • Correction the unit you need to be looking into is `ShellAPI.pas` – SilverWarior Feb 04 '22 at 12:51
  • You may also want to check [Delphi 7 and Vista/Windows 7 common dialogs - events do not work](https://stackoverflow.com/q/1894318/3636228) which has several answers on how to access modern open dialogs from Delphi 7. I haven't tested any of them so they might or may not work. – SilverWarior Feb 04 '22 at 12:56
  • 1
    @SilverWarior: The OP probably won't find `IFileDialog` in their `ShellAPI.pas`. `IFileDialog` was introduced in Windows Vista, IIRC, in 2007. Interface declarations introduced in 2007 are rarely available in Delphi 7 from 2002. – Andreas Rejbrand Feb 04 '22 at 13:29

2 Answers2

1

I used this one, I tested it with D7.

// uses commdlg
function OpenSaveFileDialog(      Parent: TWinControl;
                            const DefExt,Filter,InitialDir,Title: string;
                              var FileName: string;
                                  MustExist,OverwritePrompt,NoChangeDir,DoOpen: Boolean): Boolean;
     var ofn: TOpenFileName;
         szFile: array[0..MAX_PATH] of Char;
   begin
         Result := False;
         FillChar(ofn, SizeOf(TOpenFileName), 0);
         with ofn do
           begin
           lStructSize := SizeOf(TOpenFileName);
           hwndOwner := Parent.Handle;
           lpstrFile := szFile;
           nMaxFile := SizeOf(szFile);

           if (Title <> '') then
              lpstrTitle := PChar(Title);

           if (InitialDir <> '') then
              lpstrInitialDir := PChar(InitialDir);

           StrPCopy(lpstrFile, FileName);
           lpstrFilter := PChar(StringReplace(Filter, '|', #0,[rfReplaceAll, rfIgnoreCase])+#0#0);

           if DefExt <> '' then
              lpstrDefExt := PChar(DefExt);
           end;

         if MustExist then
            ofn.Flags := ofn.Flags or OFN_FILEMUSTEXIST;

         if OverwritePrompt then
            ofn.Flags := ofn.Flags or OFN_OVERWRITEPROMPT;

         if NoChangeDir then
            ofn.Flags := ofn.Flags or OFN_NOCHANGEDIR;

         if DoOpen
            then begin
                 if GetOpenFileName(ofn) then
                    begin
                    Result := True;
                    FileName := StrPas(szFile);
                    end;
                 end
            else begin
                 if GetSaveFileName(ofn) then
                    begin
                    Result := True;
                    FileName := StrPas(szFile);
                    end;
                 end;
    end;

procedure TForm1.Button1Click(Sender: TObject);
      VAR FilSelez : String;
    begin
          If OpenSaveFileDialog(Form1,'','*.*','c:\windows','',FilSelez,False,False,True,True) Then
             Edit1.Text := FilSelez;
    end;
mino
  • 69
  • 1
  • 4
  • The OP specifically asks how to use the Vista+ file dialogs, but this answer explains a way to use the old, pre-Vista, file dialogs. **Update:** I suppose the system will display a Vista dialog box even though you use the old API, right? If so, you may want to make that explicit in this (almost code-only) answer. – Andreas Rejbrand Feb 04 '22 at 13:32
  • Yes, the most recent dialog is displayed, with D7 it can be seen using the "OpenDialog" component at the same time – mino Feb 04 '22 at 14:48
  • Excellent working code without questions asked why don't you upgrade your D7 :D – Tom Feb 14 '22 at 11:37
1

Instead of using the IFileDialog interface you can also just modify Delphi's 7 Dialogs.pas file to display the "modern" dialogs. First make a backup copy of the Dialogs.pas file in the Source\VCL folder under the Delphi installation directory. Then search the file for the term OFN_ENABLEHOOK. The complete line should be Flags := OFN_ENABLEHOOK;. Comment out the line. Add a new line Flags := 0; directly below. Now search for the term OFN_ENABLETEMPLATE. Two lines above this should be an if Template <> nil then statement. Comment out this statement and all following ones up to and including hWndOwner := Application.Handle; and add the line hWndOwner := Screen.ActiveForm.Handle;.

Now make sure to replace the precompiled units Dialogs.dcu in the Lib and SLib directory under the Delphi installation directory with newly compiled Dialogs.dcu containing the changes. In the Lib directory you store a version without debug information, while the SLib directory contains a version with debug information. Make backup copies of the files before replacing them.

Please take note that the instructions given above only apply to Delphi 7. Furthermore, the code disables event handling for the common dialog components.

Olaf Hess
  • 1,453
  • 11
  • 18