【问题标题】:Delphi: TOpenDialog + VCL Styles corrupts filenames with large amount of filesDelphi:TOpenDialog + VCL Styles 损坏包含大量文件的文件名
【发布时间】:2016-04-21 12:25:49
【问题描述】:

在 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

就我而言,这段代码仅导致大约 5000 个文件写入日志中的 769 个,并且它们的初始路径“z:”被其他字符“?”损坏

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

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


【问题讨论】:

  • 如果您不使用自定义 VCL 样式 - 会有所不同吗?
  • 没有自定义样式也能正常工作。
  • 我敢打赌,如果没有自定义样式,对话框将进入标准的 Windows Vista+ API 调用路径,并且像 TFileOpenDialog 一样设法做到这一点。但是对于非标准的 VCL 样式,它必须覆盖默认的 Windows 样式并落入有限的 pre-Vista 模式。尝试安装 Windows 2000/XP 并尝试那里的程序,即使没有样式。无论如何它可能只适用于 Vista+,所以你没有理由避免使用TFileOpenDialog
  • 没有自定义样式也能正常工作 - 显然不是,根据@Arioch'The 在下面的答案中发布的 MS 链接。
  • 在我的测试中确实如此,也许自该报告以来已修复? (将近 6 岁)

标签: delphi vcl-styles


【解决方案1】:

您正在试验此行为,因为传递给Classic Open Dialog Box 以检索所选文件的结果的缓冲区大小由lpstrFile 元素表示,该元素是OPENFILENAME 的一部分结构体。当启用多选选项时,VCL 在内部将此缓冲区的大小设置为High(Word) - 16 (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);
...
...

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

总而言之,这种行为不是由 VCL 样式引起的

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

【讨论】:

  • 你似乎喜欢风格。您可以为虚拟树视图维护它们吗?
  • 谢谢,您的修复程序适用于新对话框,否则它们都搞砸了。旧的问题不是由 VCL 直接引起的,但它确实发生在问题中,在这种情况下,由于某种原因,缓冲区在这种情况下提前耗尽了。
【解决方案2】:

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

“文件打开对话框不能返回超过 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

【讨论】:

  • 如果没有自定义 VCL 样式就不会发生这种情况,那时我可以选择甚至超过 5K。也许自从那份约 6 年的旧报告以来,它就已经修复了。
  • 你没有提到你的操作系统。我仍然认为您应该在win2000和xp中尝试一下。否则你应该切换到 vista+ 对话框
  • VCL 样式的 Vista+ 对话框虽然混乱,但请查看屏幕截图。
  • @hikari,VCL Styles Utils 在自定义样式处于活动状态时添加了对现代对话框的支持。
  • @RRUZ 太棒了,谢谢!新对话框现在工作得很好。将此作为答案发布,我会接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-07
  • 2013-12-04
  • 1970-01-01
相关资源
最近更新 更多