将现代 IFileDialog Open/Save 对话框与 Delphi 7 个应用程序一起使用 Win10/11

Using Modern IFileDialog Open/Save dialog with Delphi 7 apps under Win10/11

我想对我的 Delphi 7 应用程序的 GUI 进行现代化改造,我已经有了 .manifest 文件,它看起来很不错,但是 Fileopen 对话框很糟糕。如何让它们变得现代?

我现在正在使用这段代码。 使用 e.g. 需要什么?相反,IFileOpenDialog,如何为此编译 header,或对 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;

IFileDialog 的以下示例代码不能用 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;

这个我用过,我用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;

除了使用 IFileDialog 界面之外,您还可以只修改 Delphi 的 7 Dialogs.pas 文件以显示“现代”对话框。 首先备份Delphi安装目录下Source\VCL文件夹中的Dialogs.pas文件。然后在文件中搜索术语 OFN_ENABLEHOOK。完整的行应该是 Flags := OFN_ENABLEHOOK;。注释掉该行。在下面直接添加新行 Flags := 0;。 现在搜索术语 OFN_ENABLETEMPLATE。上面两行应该是 if Template <> nil then 语句。注释掉此语句和所有后续语句,包括 hWndOwner := Application.Handle; 并添加行 hWndOwner := Screen.ActiveForm.Handle;.

现在确保将Delphi安装目录下LibSLib目录中的预编译单元Dialogs.dcu替换为新编译的Dialogs.dcu包含变化。在 Lib 目录中,您存储一个没有调试信息的版本,而 SLib 目录包含一个带有调试信息的版本。在替换文件之前制作文件的备份副本。

请注意,上面给出的说明仅适用于 Delphi7。此外,代码禁用了通用对话框组件的事件处理。