How to get list of selected files when using GetOpenFileName() with multiselect flag?

后端 未结 5 872
予麋鹿
予麋鹿 2021-01-15 19:20

I have tried googling, but people seem to have the same problem: we can\'t get a list of the selected files.

This is a simple piece of working code that is similar t

相关标签:
5条回答
  • 2021-01-15 19:43

    Try this:

    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);
    }
    
    0 讨论(0)
  • 2021-01-15 19:45

    It looks like the ofn.lpstrFile contains all the filenames, separated with a NULL and ending with another NULL (effectively ending with an empty string).

    If the OFN_ALLOWMULTISELECT flag is set and the user selects multiple files, the buffer contains the current directory followed by the file names of the selected files. For Explorer-style dialog boxes, the directory and file name strings are NULL separated, with an extra NULL character after the last file name. For old-style dialog boxes, the strings are space separated and the function uses short file names for file names with spaces. You can use the FindFirstFile function to convert between long and short file names. If the user selects only one file, the lpstrFile string does not have a separator between the path and file name.

    From MSDN.

    A possible implementation to parse the contents could be;

    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
    }
    
    0 讨论(0)
  • 2021-01-15 19:47

    If you select a single file when using OFN_ALLOWMULTISELECT, the nFileExtension field contains the offset to the extension. If you select multiple files, the nFileExtension field contains 0.

    This way you can determine if a single file was selected, and just read/copy the buffer pointed to by the lpstrFile field (which will be a single null terminated string containing the full path and filename including extension)

    or if multiple files where selected, then you parse the buffer pointed to by the lpstrFile field, using nFileOffset to read/copy the folder first (using lstrcpyn for example and specifying length to read as the nFileOffset value) and then read/copy from nFileOffset to next null which is file1 string, add the file string length +1 to get next position to read/copy next file string etc till you reach a file string that starts with null - which is the double null for end of all files (as the last string before this is null terminated)

    0 讨论(0)
  • 2021-01-15 19:51

    Checking nFileExtension may NOT be reliable because it can also be 0 if the user entered no file extension (but just the dot, like "file."). I think to distinguish between single and multi file selection one has to check if there is a null character (terminator) at position nFileOffset - 1.

    0 讨论(0)
  • 2021-01-15 19:55

    Here is a more complete version of the answers by Niall and Remy.

    vector<string> &filePaths;
    
    if ( GetOpenFileName( &ofn ) == TRUE )
    {
        wchar_t *p = ofn.lpstrFile;
        wstring path = p;
        p += path.size() + 1;
        if ( *p == 0 )
        {
            // there is only one string, being the full path to the file
            filePaths.push_back( ConvertWideCharToUtf8( path.c_str() ) );
        }
        else
        {
            // multiple files follow the directory
            for ( ; *p != 0 ; )
            {
                wstring fileName = p;
                filePaths.push_back( ConvertWideCharToUtf8( ( path + L"\\" + fileName ).c_str() ) );
                p += fileName.size() + 1;
            }
        }
    }
    

    Where we also have the function:

    string 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 );
        string s = buffer;
        free( buffer );
    
        return s;
    }
    
    0 讨论(0)
提交回复
热议问题