Delphi:TOpenDialog + VCL 样式会损坏包含大量文件的文件名

hik*_*ari 2 delphi vcl-styles

在 W7 x64 中使用 Delphi Seattle。使用自定义 VCL 样式并选择大量文件(如 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
Run Code Online (Sandbox Code Playgroud)

在我的最后,这段代码导致只有 769 个文件被写入到日志中,大约 5000 个,并且它们的初始路径“z:”被其他字符“?”破坏了。

有任何解决这个问题的方法吗?

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

在此处输入图片说明
在此处输入图片说明

RRU*_*RUZ 5

您正在试验此行为,因为缓冲区的大小传递给经典打开对话框以检索所选文件的结果,缓冲区由lpstrFile作为OPENFILENAME结构一部分的元素表示。High(Word) - 16当启用多选选项时,VCL 在内部将此缓冲区的大小设置为(65519) 字节,并在启用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);
...
...
Run Code Online (Sandbox Code Playgroud)

从 Windows Vista 和 New Dialogs ( IFileOpenDialog)的引入开始,所选文件由 a 中的IFileOpenDialog::GetResults方法返回 IShellItemArray,因此缓冲区限制不适用。

总之,这种行为不是由 VCL Styles 引起的

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

在此处输入图片说明