如何让OpenDialog在选择文件时更改当前目录?

How to get OpenDialog to change the current directory when a file is selected?

提问人:Mark Di Val 提问时间:7/27/2022 更新时间:7/27/2022 访问量:335

问:

我已经移植了一个 C++Builder 6 应用程序以使用 C++Builder 11 进行编译。

我在测试中发现的一个问题是 TOpenDialog 在两个版本之间的行为不同。

C++Builder 6 版本在单击“打开”时更改当前目录,而 C++Builder 11 版本保持当前目录不变。

我尝试设置 OpenDialog 选项以确保它们不包括 ofNoChangeDir,但这没有区别。

C++ Builder 6 和 11 版本都在 Windows 10 上运行。

我想让 C++ Builder 11 版本更改 Open 上的当前目录,以便下游的所有内容都以相同的方式工作,但到目前为止,通过清除和设置选项,我没有运气。

我可以在 OpenDialog->Execute() 返回后更改当前目录,但是当有应该决定对话框行为的选项时,这似乎有点笨拙。

// Check the current directory before and after the OpenDialog executes ...
String CurrentDirectory = GetCurrentDir();

OpenDialog1->Options.Clear();
OpenDialog1->Options << ofHideReadOnly << ofEnableSizing;  // seems to be the default

if (OpenDialog1->Execute())
{
  // do whatever
}

CurrentDirectory = GetCurrentDir(); // no change!? :|
TopenDialog C++Builder-11-亚历山大

评论

0赞 Remy Lebeau 7/27/2022
与您的问题无关,但没有任何影响。您必须改用。然后,您可以将其与后续行合并到单个语句中:OpenDialog1->Options.Clear();OpenDialog1->Options = TOpenOptions();OpenDialog1->Options = TOpenOptions() << ofHideReadOnly << ofEnableSizing;
0赞 Mark Di Val 7/27/2022
嗨,雷米 - 我刚才尝试了这种语法,它没有区别。当前目录保持不变。我得到了OpenDialog->Options.Clear();此处的 Embarcadero 示例代码中的语法:docwiki.embarcadero.com/CodeExamples/Sydney/en/...
0赞 Remy Lebeau 7/27/2022
我没有说它会解决你的问题。我只是指出了您代码中的一个错误。Embarcadero 示例是错误的。调用时会将 读入一个临时对象,然后是临时对象,但不会将临时对象分配回 。顺便说一句,同上。修改代码只能使用赋值运算符完成。Options.Clear()OptionsClear()OptionsOptions << ofHideReadOnly << ...Options=

答:

1赞 Remy Lebeau 7/27/2022 #1

行为上的差异是因为这两个版本在后台使用不同的 Win32 API。

在 C++ Builder 6 中,使用 GetOpenFileNameA(),它有一个默认未启用的标志,因此除非在 .TOpenDialogOFN_NOCHANGEDIRofNoChangeDirOptions

而在 C++ Builder 11 中,在 Vista+ 上使用 IFileOpenDialog 1,它有一个默认启用的标志,因此工作目录不会更改。但是,如果未在 中指定,则禁用。不过,出于安全原因,对话框可能忽略了这一点。因此,在您的情况下,最好在退出后自行设置工作目录。阿拉伯数字TOpenDialogFOS_NOCHANGEDIRTOpenDialogFOS_NOCHANGEDIRofNoChangeDirOptionsTOpenDialog::Execute()

1:在 Vista 之前的系统上,或者在 VCL 不支持使用的某些配置下,将改用 - 但这只会在 Vista+ 内部使用。IFileOpenDialogTOpenDialogGetOpenFileNameW()IFileOpenDialog

2:你真的不应该一开始就依赖工作目录。还有其他因素可以在运行时更改工作目录。应始终仅使用绝对路径。

评论

0赞 Mark Di Val 7/27/2022
我同意应用程序通常最好不依赖当前工作目录来读取或写入文件。我对 BCB6 的这个端口的情况就是造成这种情况的一个典型例子。我移植的软件确实依赖于相对(当前目录)路径来读取和写入许多文件,因此我希望找到一种快速方法,使 CB11 中的 TOpenDialog 以相同的方式运行,并考虑在以后重新设计绝对路径。在这方面,手动设置TOpenDialog->Execute()之后的当前目录具有预期的效果。
0赞 Mark Di Val 7/27/2022
出于好奇,我花了一段时间查看 Vcl.Dialogs.pas、Vcl.Dialogs.hpp、ShObjIdl_core.h 和 System.UITypes.hpp,以了解引擎盖下的内容。我注意到,在过程TFileDialogWrapper.AssignOptions中,某些选项似乎是在数组中定义的,而其他选项则类似于占位符。难道这就是某些选项(如 fdoNoChangeDir)无法更改的原因吗?