使用带有多选标志的GetOpenFileName()时如何获取所选文件的列表?

时间:2014-10-11 17:56:25

标签: c++ windows winapi visual-c++

我尝试使用Google搜索,但人们似乎遇到了同样的问题:我们无法获取所选文件的列表。

这是一段简单的工作代码,类似于我使用的代码:

OPENFILENAME ofn = { sizeof ofn };
wchar_t file[1024];
file[0] = '\0';
ofn.lpstrFile = file;
ofn.nMaxFile = 1024;
ofn.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
GetOpenFileName(&ofn);

如何实际获取我选择的文件名?目前我只能在没有OFN_ALLOWMULTISELECT标志的情况下使用它,因此它将一个选定的文件名返回到ofn.lpstrFile。我试图打印出该结构中的所有字符串变量,但什么也没找到。它仅显示所选文件的主文件夹。

5 个答案:

答案 0 :(得分:6)

看起来ofn.lpstrFile包含所有文件名,以NULL分隔并以另一个NULL结尾(实际上以空字符串结尾)。

  

如果设置了OFN_ALLOWMULTISELECT标志并且用户选择了多个文件,则缓冲区包含当前目录,后跟所选文件的文件名。对于资源管理器样式的对话框,目录和文件名字符串是NULL分隔的,在最后一个文件名后面有一个额外的NULL字符。对于旧式对话框,字符串是空格分隔的,函数使用短文件带空格的文件名的名称。您可以使用FindFirstFile函数在长文件名和短文件名之间进行转换。 如果用户只选择一个文件,则lpstrFile字符串在路径和文件名之间没有分隔符。

来自MSDN

解析内容的可能实现可以是;

wchar_t* str = ofn.lpstrFile;
std::wstring directory = str;
str += ( directory.length() + 1 );
while ( *str ) {
  std::wstring filename = str;
  str += ( filename.length() + 1 );
  // use the filename, e.g. add it to a vector
}

答案 1 :(得分:1)

检查nFileExtension可能不可靠,因为如果用户没有输入文件扩展名(但只是点,如“file。”),它也可能为0。 我认为要区分单文件和多文件选择,必须检查位置nFileOffset - 1是否有空字符(终止符)。

答案 2 :(得分:0)

试试这个:

wchar_t file[1025] = {0}; // room for an extra null terminator, just in case
...
ofn.nMaxFile = 1024;
...
wchar_t* ptr = ofn.lpstrFile;
ptr[ofn.nFileOffset-1] = 0;
std::wcout << L"Directory: " << ptr << std::endl;
ptr += ofn.nFileOffset;
while (*ptr)
{
    std::wcout << L"File: " << ptr << std::endl;
    ptr += (lstrlenW(ptr)+1);
}

答案 3 :(得分:0)

如果在使用OFN_ALLOWMULTISELECT时选择单个文件,则nFileExtension字段包含扩展的偏移量。如果选择多个文件,则nFileExtension字段包含0.

通过这种方式,您可以确定是否选择了单个文件,并且只读取/复制lpstrFile字段指向的缓冲区(这将是一个包含完整路径和文件名的单个空终止字符串,包括扩展名)

或者如果选择了多个文件,则解析lpstrFile字段指向的缓冲区,使用nFileOffset首先读取/复制文件夹(例如使用lstrcpyn并指定length作为nFileOffset值读取)然后读取/从nFileOffset复制到下一个null,即file1字符串,添加文件字符串长度+1以获取读取/复制下一个文件字符串等的下一个位置,直到找到以null开头的文件字符串 - 这是所有结尾的双重空值文件(作为空终止之前的最后一个字符串)

答案 4 :(得分:0)

这是Niall和Remy的答案的更完整版本。 vector &filePaths; 如果(GetOpenFileName(&ofn)== TRUE) {     wchar_t * p = ofn.lpstrFile;     wstring path = p;     p + = path.size()+ 1;     如果(* p == 0)     {         //只有一个字符串,是文件的完整路径         filePaths.push_back(ConvertWideCharToUtf8(path.c_str()));     }     其他     {         //多个文件跟随目录         为(; * p!= 0;)         {             wstring fileName = p;             filePaths.push_back(ConvertWideCharToUtf8((path + L“ \\” + fileName).c_str()));             p + = fileName.size()+ 1;         }     } } 我们还具有以下功能: 字符串ConvertWideCharToUtf8(const wchar_t * wideText) {     int len = WideCharToMultiByte(CP_UTF8,0,wideText,-1,NULL,0,NULL,NULL);     char * buffer =(char *)malloc(len);     WideCharToMultiByte(CP_UTF8,0,wideText,-1,buffer,len,NULL,NULL);     字符串s =缓冲区;     free(buffer);     返回s; }