OpenFileName对话框返回亚洲字母而不是文件路径
OPENFILENAME dialog returns Asian letters instead of file path
我正在尝试创建一个函数,该函数从OpenFileName对话框中获取filepath。我的代码看起来像这样。
wstring src;
bool open()
{
const string title = "Select a File";
wchar_t filename[MAX_PATH];
OPENFILENAMEA ofn;
ZeroMemory(&filename, sizeof(filename));
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = "Music (.mp3) *.mp3 All *.* ";
ofn.lpstrFile = LPSTR(filename);
ofn.nMaxFile = MAX_PATH;
ofn.lpstrTitle = title.c_str();
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if (GetOpenFileNameA(&ofn))
{
src = filename; //<----------Save filepath in global variable
return true;
}
return false;
}
将断点放在评论的行上后,我可以检查" src"的价值以及"文件名",这对我来说,这是亚洲血统的不可识别的来信。为什么会发生这种情况?这是转换问题吗?
编辑:
多亏了快速答复和一些评论,该代码现在已完全函数。感谢Hans Passant提供了非常直接的解决方案,也要感谢Cody Gray重写该功能,解释了错误,并为我提供了应该如何处理的课程。由于我仍在采取第一步学习Winapi,因此这些信息将在以后的计划中为我提供良好的服务。
这是由混合ANSI和Unicode字符类型引起的经典错误。正如您所描述的那样
快速浏览您的代码,立即揭示了问题。您正在调用win32函数的ANSI版本(GetOpenFileNameA
),并使用数据结构的ANSI版本-OPENFILENAMEA
- yet您的filename
数组由宽字符组成(wchar_t
)。在Win32中,A
-填充类型始终是ANSI,需要使用1字节char
类型。W
-填充类型始终是Unicode,需要使用2字节wchar_t
类型。如果没有明确的转换,则无法使用MultiByteToWideChar
和/或WideCharToMultiByte
。进行混合。。
请注意,如果您没有使用明确的铸件将其关闭,则编译器会捕获此类型的不匹配错误。
在现代时代,您应该始终使用W
-Suffed API,因为您始终想支持Unicode。世界不是ASCII,当每个人都切换到Windows NT和Windows 98/Me已死并埋葬时,Windows ANSI编码变得过时了。
因此,请按以下方式重写您的代码(我也借此自由来更改其他一些习语并以其他方式清理代码,例如将C 语言构造用于零内存):
std::wstring src;
bool open()
{
const std::wstring title = L"Select a File";
std::wstring filename(MAX_PATH, L' ');
OPENFILENAMEW ofn = { };
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = L"Music (.mp3) *.mp3 All *.* ";
ofn.lpstrFile = &filename[0]; // use the std::wstring buffer directly
ofn.nMaxFile = MAX_PATH;
ofn.lpstrTitle = title.c_str();
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if (GetOpenFileNameW(&ofn))
{
src = filename; //<----------Save filepath in global variable
return true;
}
return false;
}
为了避免每次明确键入W
的需要,请确保UNICODE
和_UNICODE
均为您的项目定义。最好的方法是使用项目属性,您可以在其中预先定义这些符号。否则,您可以在预编译标头的顶部定义它们。这样可以确保即使省略后缀,始终使用的 W
-suffix suffix suffix变体始终使用。因此,您可以简单地说GetOpenFileName
和OPENFILENAME
。Windows标题文件中的宏处理分辨率。
这样的优点是,如果您忘记将L
前缀的宽串文字前缀前缀前缀,则会导致编译器产生类型的不匹配错误,如果您还没有这样做的习惯,这是一个常见的错误。(当然,这也假定您还摆脱了使用明确的演员来沉默编译器警告的坏习惯,因为您可以通过这样做来轻松击败此安全网。)
- 从函数角度看ID到文件路径的内部与外部映射
- 在C++中设置基于操作系统的文件路径
- Windows 非 ASCII 文件路径
- 非 ASCII 文件路径窗口
- C++和带有国家符号的文件路径(也许用 UTF8 编码)
- 如何为文件路径使用变量?
- 包括 VS Code 上的完整文件路径
- 如何使用提升获取当前文件路径?
- 如何在 c++ 中获取当前文件路径?
- 保存json文件后如何返回文件路径
- 从 C++ 中的文件路径中提取文件名
- 是否可以将文件路径传递给Qt中的setStyleSheet()
- 无法转换 .CATPart 文件.错误:输入文件路径似乎包含不支持的字符
- 在结构函数之间传递文件路径 C++ 编辑:修复LNK2019错误
- 提供依赖于输入的程序的文件路径
- 从 QFileSystemModel 中的文件路径和文件名获取 QModelIndex
- 如何更改变量文件名的文件路径?
- cmake:包括vs vs add_subDirectory:相对标头文件路径
- 在OSX中使用CGDisplayStream存储屏幕记录的特定文件路径
- 如何在另一个系统上启用文件路径