Delphi 10.3 中带预览的文件打开对话框

File Open Dialog with Preview in Delphi 10.3

我针对 Delphi 10.3 进行了更改,其默认 TOpenDialog 包含一个预览窗格。我进行了一些搜索,找到了 Microsoft 提供的用于自定义标准 WinAPI 对话框的 IFileDialogCustomize 界面。我知道我必须使用 OnSelectionChange 事件处理程序来修改窗格的图片。对我来说最大的问题是:如何通过 IFileDialogCustomize 访问预览窗格图像?这个的 ItemID 是什么?我在网上找不到这个问题的任何答案。有人知道答案吗?然后请与我和社区分享! :)

为了简洁起见,我用 ... 替换了一些代码片段,因为这些是琐碎的或依赖于应用程序的部分。

procedure TMainWindow.OnSelectionChange( Sender : TObject );
var
  dc : HDC;
  aBMP : TBitmap;

  function isSelectedFilePreviewAble : boolean;
  begin
    result := ...;
  end;

  functon getPreviewPictureDC : HDC;
  var
    iCustomize : IFileDialogCustomize;
    h : THandle;
  begin
    if OpenDialog1.QueryInterface( IFileDialogCustomize, iCustomize ) = S_OK then
    begin
      h := iCustomize.??? this is the missing code fragment
      result := GetDC( h );
    end else
      result := 0;
  end;

  procedure generatePreviewPicture;  
  begin
    ...
  end;

begin
  dc := getPreviewPictureDC;
  if ( dc <> 0 ) then
  begin
    aBMP := TBitmap.Create;
    try
      if ( isSelectedFilePreviewAble ) then
        generatePreviewPicture;  
      StretchBlt( aBMP.Handle, ...);
    finally
      aBMP.Free;
      ReleaseDC( dc );
    end;    
  end;
end;

I made some searches and found the IFileDialogCustomize interface provided by Microsoft to customize standard WinAPI dialogs.

首先,IFileDialogCustomize不是"customize standard WinAPI dialogs"。它仅自定义 IFileOpenDialogIFileSaveDialog 对话框,不自定义其他对话框。

二、TOpenDialog primarily uses the legacy Win32 API GetOpenFileName()函数。在 Windows Vista+ 上,GetOpenFileName() 在内部使用 IFileOpenDialog 并启用了基本选项,因此旧版应用程序仍然可以拥有现代外观。

虽然,在以下条件下,TOpenDialog会直接使用IFileOpenDialog,而不是使用GetOpenFileName()

  • Win32MajorVersion 是 >= 6 (Vista+)
  • UseLatestCommonDialogs 为真
  • StyleServices.Enabled 为真
  • TOpenDialog.Template 为零
  • TOpenDialog.OnIncludeItemTOpenDialog.OnCloseTOpenDialog.OnShow 未分配。

但即便如此,TOpenDialog 仍然不允许您在使用时访问其内部 IFileOpenDialog 界面。

如果你真的想访问对话框的 IFileOpenDialog 并因此访问它的 IFileDialogCustomize,你需要使用 TFileOpenDialog 而不是 TOpenDialog(只知道对话框不会'不能在 XP 和更早的系统上工作,如果您仍然需要支持它们的话)。

The big question for me is : how can I access the preview pane image by IFileDialogCustomize?

你不知道。预览窗格不是对话框自定义,因此无法通过 IFileDialogCustomize 访问。即使您可以获得预览窗格的控件 ID(您不能),IFileDialogCustomize 也没有允许您访问预览窗格的 HWNDHDC 的功能,或以任何方式更改预览窗格的内容。对于支持预览的任何文件类型,预览窗格是 IFileDialog 不可或缺的 和私有 组件。它不是您可以直接访问和利用的东西。 IFileOpenDialog 当用户选择具有(或缺少)要显示的预览的文件时,它本身将根据需要更新预览窗格。

My boss want to show previews for our own file formats.

在 Vista+ 上正确的 处理方法是为您的自定义文件类型创建 Preview Handler。然后,任何 Shell 想要显示文件预览的组件,包括 IFileOpenDialog,都可以使用您的处理程序。