Delphi: TOpenDialog + VCL Styles 损坏大量文件的文件名

Delphi: TOpenDialog + VCL Styles corrupts filenames with large amount of files

在 W7 x64 中使用 Delphi 西雅图。当使用自定义 VCL 样式并且您 select 大量文件(如 2-3k+)时,文件名已损坏。没有自定义样式,这不会发生。

program Project1;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Vcl.Themes,
  Vcl.Styles;

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  TStyleManager.TrySetStyle('Onyx Blue');
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


procedure TForm1.FormCreate(Sender: TObject);
Var s: string;
   ts: TStringList;
begin
  if OpenDialog1.Execute then begin
    ts := TStringList.Create;
    for s in OpenDialog1.Files do
     ts.Add(s);
  end else Exit;
  ts.SaveToFile('z:\files.txt');
  ts.Free;
end;

object OpenDialog1: TOpenDialog
  Filter = 'Pictures (jpg,png,bmp,gif)|*.jpg;*.png;*.bmp;*.gif|All Files|*.*'
  Options = [ofReadOnly, ofAllowMultiSelect, ofEnableSizing, ofForceShowHidden]
  Title = 'Select files to upload'
  Left = 201
  Top = 64
end

在我这边,此代码仅将 769 个文件写入 ~5000 个日志中,并且它们的初始路径 "z:" 被其他字符“?”

损坏

有什么办法可以解决这个问题?

注意:新的 TFileOpenDialog 似乎没有这个问题,但它确实带来了其他问题,如下所示:(除了 Vista+)


这似乎与 Delphi 无关。 Google 只需五秒钟,我们就有了这个:

"文件打开对话框不能return超过1000个文件"

http://answers.microsoft.com/en-us/windows/forum/windows_7-files/shameful-limitation-file-open-dialog-cannot-return/bfff43fc-0da5-48d6-8703-dc0eac3c7581?auth=1

您正在试验此行为,因为传递给 Classic Open Dialog Box to retrieve the results of the selected file(s), the buffer is represented by the lpstrFile element which is part of the OPENFILENAME 结构的缓冲区大小。当启用多 select 选项时,VCL 在内部将此缓冲区的大小设置为 High(Word) - 16 (65519) 字节,当单个文件 selection 时,缓冲区大小设置为 MAX_PATH已启用。

这是显示此内容的 VCL 代码 (Vcl.Dialogs) 的一部分

function TOpenDialog.DoExecute(Func: Pointer; ParentWnd: HWND): Bool;
const
  MultiSelectBufferSize = High(Word) - 16;
...
...
    if ofAllowMultiSelect in FOptions then
      nMaxFile := MultiSelectBufferSize else
      nMaxFile := MAX_PATH;
    SetLength(TempFilename, nMaxFile + 2);
    lpstrFile := PChar(TempFilename);
...
...

从 Windows Vista 开始并引入新对话框 (IFileOpenDialog), the selected files are returned by the IFileOpenDialog::GetResults method in a IShellItemArray,因此缓冲区限制不适用。

总之,此行为不是由 VCL 样式引起的。

最后,如果您想使用具有自定义样式的现代对话框,请尝试 VCL Styles Utils 项目。