C++ ( MS V S ) 获取OpenFileName

Posted

技术标签:

【中文标题】C++ ( MS V S ) 获取OpenFileName【英文标题】:C++ ( MS V S ) GetOpenFileName 【发布时间】:2017-09-27 13:12:35 【问题描述】:

我的程序旨在让用户打开 2 个文件,然后以特定方式比较它们。我正在使用 Visual Studio 在 C++ 中使用 GUI 创建它(如果这不是最好的方法,请纠正我,我只知道如何在 Linux 上编写 C 代码):

OPENFILENAME open;
ZeroMemory(&open, sizeof(open));

open.lStructSize = sizeof(LPOPENFILENAMEA);
open.lpstrFilter = "Files\0*.csv;*.xls\0\0";
open.nFileOffset = 1;
open.lpstrFile[0] = '\0';
open.nMaxFile = 2048;
open.lpstrTitle = "Title here.";
open.Flags = OFN_ALLOWMULTISELECT | OFN_FILEMUSTEXIST;
BOOL selected = GetOpenFileName(&open);

我收到以下编译器错误:

E0513“const char *”类型的值不能分配给“LPCWSTR”类型的实体 错误 C2440 '=':无法从 'const char [39]' 转换为 'LPCWSTR' NewTry

filtertitle 行上。

【问题讨论】:

让我猜猜,你是在启用 Unicode 的情况下构建的(即定义了 UNICODE 宏)?这意味着几乎所有字符串都需要是宽字符串。这是T 宏的原因之一。修改您的字符串文字,例如T("Title here.") 不,不要使用 TCHAR 宏。使用L 前缀@Someprogrammerdude @DavidHeffernan 虽然启用 Unicode 应该是默认的 IMO,但通过硬编码宽字符文字,如果代码用于 UNICODE 的构建或项目中,则会遇到与此相反的问题没有定义的。或者对于可能跨平台使用的代码。我和其他人一样不喜欢使用 T 宏,但在旧的非 Unicode 接口被删除之前,不幸的是,我认为这是最好的折衷方案。 这段代码不能跨平台使用,现在支持Windows 95也没意义了。现在是 2017 年。是时候继续前进了。 @Someprogrammerdude 你记得部分正确。 C 运行时使用_TCHAR_T()(和其他下划线前缀的宏/定义)和_UNICODE。 Win32 API 使用TCHARLP(C)TSTRTEXT()UNICODE 【参考方案1】:

由于 Windows 95/98/ME 已经长期死了,目前的建议是使用 Windows NT 系列操作系统的原生 Unicode 支持。

显然,您已经完成了该设置,因为错误消息告诉我们GetOpenFileName 被定义为GetOpenFileNameW。在 WIndows 95 上,它被定义为 GetOpenFileNameAA 变体意味着它采用 const char* 参数,W 变体采用 const wchar_t*

您使用L 前缀定义wchar_t 宽字符串文字,即L"Files..."。你也可以使用std::wstring,它的c_str()方法返回一个空终止的const wchar_t*

【讨论】:

我已经尝试了 L 前缀,它会导致我在上面的 cmets 中提到更多的错误。 @C.Edelweiss:我认为您的意思是在回答 Sean 的帖子时(上面和下面可能会有所不同,因为答案被赞成)。但那些未解析的符号意味着您的代码编译。它稍后在链接中失败。这意味着这里的编译问题已经解决。至于链接器错误,那当然是添加使用的库的问题了。 @C.Edelweiss 你似乎已经放弃了。您只是在尝试从答案中获得建议,当您遇到后续不相关的失败时,请返回此处获取更多信息。试着思考和思考你在做什么,并理解它。你问的问题已经回答了。你现在有一个新问题。不要问新问题,关于您的新问题,已有数千个问题被问到。确实有数千人被问及这个问题中的问题。将来您应该尝试阅读错误消息,并进行一些独立的研究。不要只是放弃! 我现在正在研究它们,似乎有很多可能性,当我在 Linux 上做 C 语言时,要进入这个环境并不容易,谢谢你的信息。 @C.Edelweiss:嗯,链接中的未定义符号在 C for Linux 中几乎相同。实际上可能不会被命名为LNK2019,但概念是相同的。 LNK2019 很容易在 *** 上搜索。【参考方案2】:

看起来您正在执行 unicode 构建。

如果您查看字符串结构成员上的 one 的定义,例如 lpstrFilter,您会发现它被定义为 LPTSTR。第一个 T 表示文本类型是 ASCII 或 Unicode,具体取决于您的构建方式。

要处理这两种情况,请在输入字符串文字时使用 _T 宏:

open.lpstrFilter = _T("Files\0*.csv;*.xls\0\0");

这将为您提供非 Unicode 版本的 ASCII 字符串,以及 Unicode 版本的 Unicode 字符串。

如果您只希望以 Unicode 为目标,那么您可以通过在字符串前面加上 L 来显式获取 Unicode 字符串:

open.lpstrFilter = L"Files\0*.csv;*.xls\0\0";

Microsoft 如何在他们的Unicode Programming Summary 页面上提供详细信息。

【讨论】:

这两种方法都给了我 17 个新错误,指向第 1 行,即 #include ,大多数是严重代码描述项目文件行抑制状态错误 LNK2019 未解析的外部符号 __imp__CreateSolidBrush@4 引用于function _WinMain@16 NewTry C:\Users\Robert\source\repos\NewTry\NewTry\NewTry.obj 1 严重性代码描述项目文件行抑制状态错误 LNK2019 未解析的外部符号 _wWinMain@16 在函数“int __cdecl invoke_main(void) " (?invoke_main@@YAHXZ) NewTry //LIBCMTD.lib(exe_wwinmain.obj) 很难找到建议支持 Windows 95 的答案。 @C.Edelweiss - 这些是链接器错误。您需要确保链接到正确的库。 @DavidHeffernan - 大量 MSDN 仍然使用这些宏,因此在示例中提及它们并非不合理。 那些 MSDN 示例设置了非常差的领先优势。不要跟随他们。不要让这种可怕的 TCHAR 混乱持续下去。

以上是关于C++ ( MS V S ) 获取OpenFileName的主要内容,如果未能解决你的问题,请参考以下文章

leetcode680 C++ 124ms 删掉一个字符后能否构成回文

C++ new & delete

leetcode387 C++ 84ms 字符串中的第一个唯一字符

如何在 MS 编译器中使用数组初始化 C++ 向量/集?

C++ 运行时库设置为 /MT,但仍然缺少 api-ms-win*.dll

c++ 如何把一个int转为char*