允许多选的 TSaveDialog 选项在 W10 系统上不能正常工作

TSaveDialog Options ofAllowMultiSelect doesn't work properly on a W10 system

我有一个旧应用程序,很长一段时间都没有动过,它是用 C++ Builder 2009 构建的,但仍然可以正常工作。 也就是说 .. 今天我注意到一些 TSaveDialog->Options 在我的 Windows 10 系统上没有按预期工作。为了确保我不是在做梦,我在较旧的 Windows 版本(我试过 XP)上测试了相同的应用程序,并且它按预期运行得非常好。

TSaveDialog 实例在设计时设置 Options[ofHideReadOnly,ofAllowMultiSelect,ofEnableSizing]

我今天(在 Windows 10)注意到 ofAllowMultiSelect 不再工作了? 相反 ofOverwritePrompt 被(错误地)使用了! 换句话说,我不能再 select 两个或更多文件,当我 select 一个已经存在的文件时,我首先得到一个 'Confirm Save As' 对话框。

当我在我的 Windows 10 系统上再次编译时,使用 C++ Builder 2009,在调试模式下检查 Options,调试器似乎(仍然)正确地看到 ofHideReadOnlyofAllowMultiSelectofEnableSizing,但问题依然存在。所以好像这些值以某种方式改变了?

当我在 运行 尝试时:

SaveDialog->Options.Clear() ;
SaveDialog->Options << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect ;

问题依然存在!

当我删除 ofAllowMultiSelect 时(在 运行 时间或设计时) 'Confirm Save As' 不再显示在现有文件上(但我显然仍然不能 select多个文件)。

老实说,我对此感到震惊?不知道下一步该怎么做 ? 我没有选择测试更新的 c++ 版本,但我也很难理解编译器在这里如何负责。

感谢任何指导。
由于 C++ Builder 和 Delphi

之间的 VCL 重叠,添加了 Delphi 标签

在 Windows Vista 及更高版本上,当且仅当满足所有这些条件时:

  • 全局Dialogs::UseLatestCommonDialogs变量是true
  • TSaveDialog::Template 属性 是 NULL
  • 并且 TSaveDialog::OnIncludeItemTSaveDialog::OnCloseTSaveDialog::OnShow 事件没有分配处理程序

然后TSaveDialog将在内部使用Win32 IFileSaveDialog interface, where the ofAllowMultiSelect option will be mapped to that dialog's FOS_ALLOWMULTISELECT option, which is NOT SUPPORTED by IFileSaveDialog, only by IFileOpenDialog, per the documentation:

FOS_ALLOWMULTISELECT
Enables the user to select multiple items in the open dialog. Note that when this flag is set, the IFileOpenDialog interface must be used to retrieve those items.

如果不满足以上3个条件,则TSaveDialog将在内部使用Win32 GetSaveFileName()函数,其中ofAllowMultiSelect选项将映射到该对话框的[=31] =] 选项, GetSaveFileName() 1.

支持

这就是为什么您在 运行 您的应用程序在 Windows XP 与 Windows 10 上看到行为差异的原因。

因此,如果您想在较新的 Windows 版本上使用旧的 TSaveDialog 行为,则需要确保至少满足这 3 个条件中的 1 个。例如,通过在调用 SaveDialog->Execute() 之前设置 UseLatestCommonDialogs=false,或者将(空)事件处理程序分配给 OnIncludeItem/OnClose/OnShow 事件之一。

或者,您可以直接调用 GetSaveFileName(),而根本不使用 TSaveDialog

1:但是,请注意,在 Vista+ 上,GetSaveFileName() 只是 IFileSaveDialog 的包装器,仅用于向后兼容。因此,即使您确实在 Windows 10.

上使用了 GetSaveFileName(),您仍然 可能不会 获得您想要的确切行为

旁注:这段代码并不像您想象的那样工作:

SaveDialog->Options.Clear();
SaveDialog->Options << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect;

Options 属性 实际上没有更新!在这两个语句中,Options 属性 是 读取的,返回一个临时的 TOpenOptions,然后您正在修改它,而不是 分配回 Options 属性。 IOW,代码有效地执行以下操作:

TOpenOptions temp1 = SaveDialog->Options;
temp1.Clear();

TOpenOptions temp2 = SaveDialog->Options;
temp2 << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect;

因此,要正确更新 Options 属性,请改为使用:

SaveDialog->Options = TOpenOptions() << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect;