【发布时间】:2017-03-29 22:45:34
【问题描述】:
我正在尝试向我的项目添加一个选择文件对话框,该对话框现在只能接受用户输入的文件名。
我做了一些搜索,似乎带有 GetOpenFileName 函数的 windows API 是我最简单的方法。但是,当我从 MSDN 或其他网站复制和粘贴示例代码时,我遇到了一些构建错误。
我使用的是visual studio 2017。我使用的示例代码来自http://www.cplusplus.com/forum/windows/169960/:
#include <iostream>
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
int main()
{
char filename[ MAX_PATH ];
OPENFILENAME ofn;
ZeroMemory( &filename, sizeof( filename ) );
ZeroMemory( &ofn, sizeof( ofn ) );
ofn.lStructSize = sizeof( ofn );
ofn.hwndOwner = NULL; // If you have a window to center over, put its HANDLE here
ofn.lpstrFilter = "Text Files\0*.txt\0Any File\0*.*\0";
ofn.lpstrFile = filename;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrTitle = "Select a File, yo!";
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if (GetOpenFileNameA( &ofn ))
{
std::cout << "You chose the file \"" << filename << "\"\n";
}
else
{
// All this stuff below is to tell you exactly how you messed up above.
// Once you've got that fixed, you can often (not always!) reduce it to a 'user cancelled' assumption.
switch (CommDlgExtendedError())
{
case CDERR_DIALOGFAILURE : std::cout << "CDERR_DIALOGFAILURE\n"; break;
case CDERR_FINDRESFAILURE : std::cout << "CDERR_FINDRESFAILURE\n"; break;
case CDERR_INITIALIZATION : std::cout << "CDERR_INITIALIZATION\n"; break;
case CDERR_LOADRESFAILURE : std::cout << "CDERR_LOADRESFAILURE\n"; break;
case CDERR_LOADSTRFAILURE : std::cout << "CDERR_LOADSTRFAILURE\n"; break;
case CDERR_LOCKRESFAILURE : std::cout << "CDERR_LOCKRESFAILURE\n"; break;
case CDERR_MEMALLOCFAILURE : std::cout << "CDERR_MEMALLOCFAILURE\n"; break;
case CDERR_MEMLOCKFAILURE : std::cout << "CDERR_MEMLOCKFAILURE\n"; break;
case CDERR_NOHINSTANCE : std::cout << "CDERR_NOHINSTANCE\n"; break;
case CDERR_NOHOOK : std::cout << "CDERR_NOHOOK\n"; break;
case CDERR_NOTEMPLATE : std::cout << "CDERR_NOTEMPLATE\n"; break;
case CDERR_STRUCTSIZE : std::cout << "CDERR_STRUCTSIZE\n"; break;
case FNERR_BUFFERTOOSMALL : std::cout << "FNERR_BUFFERTOOSMALL\n"; break;
case FNERR_INVALIDFILENAME : std::cout << "FNERR_INVALIDFILENAME\n"; break;
case FNERR_SUBCLASSFAILURE : std::cout << "FNERR_SUBCLASSFAILURE\n"; break;
default : std::cout << "You cancelled.\n";
}
}
}
当我复制并粘贴到 vs 时,它显示以下内容:
Severity Code Description Project File Line Suppression State
Error C2440 '=': cannot convert from 'char [260]' to 'LPWSTR' ConsoleApplication1 c:\users\xfan0\documents\visual studio 2017\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp 18
Severity Code Description Project File Line Suppression State
Error C2440 '=': cannot convert from 'const char [19]' to 'LPCWSTR' ConsoleApplication1 c:\users\xfan0\documents\visual studio 2017\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp 20
Severity Code Description Project File Line Suppression State
Error C2664 'BOOL GetOpenFileNameA(LPOPENFILENAMEA)': cannot convert argument 1 from 'OPENFILENAME *' to 'LPOPENFILENAMEA' ConsoleApplication1 c:\users\xfan0\documents\visual studio 2017\projects\consoleapplication1\consoleapplication1\consoleapplication1.cpp 23
Severity Code Description Project File Line Suppression State
Error (active) E0167 argument of type "OPENFILENAME *" is incompatible with parameter of type "LPOPENFILENAMEA" ConsoleApplication1 c:\Users\XFAN0\Documents\Visual Studio 2017\Projects\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.cpp 23
试图搜索但没有找到我的运气:(
【问题讨论】:
-
您的构建默认需要宽字符串,但您使用的是 MBCS 字符串。您可以在调用 Windows API 时更改代码以使用宽字符串,也可以更改项目的设置(项目属性 -> 常规 -> 字符集 -> 使用多字节字符集)。
-
在某些地方,您抓取的示例代码明确调用 MBCS 版本(例如,
GetOpenFileNameA),但它并没有始终如一地这样做(例如,OPENFILENAME默认为OPENFILENAMEW而不是OPENFILENAMEA)。在现代 Windows 程序中,首选使用 API 的宽字符串版本。 MBCS 功能主要是为了向后兼容,它有局限性。 -
酷。实际上,我尝试了该设置,但是当我测试另一个示例时,它不起作用大声笑。
-
不太清楚你的第二点,但是……我猜还有很多东西要研究。还是谢谢你。
-
使用
OPENFILENAMEA而不是OPENFILENAME
标签: c++ user-interface visual-studio-2017 windows-api-code-pack getopenfilename