Is there anyway to make SOMETHING automatically add selected file extension to filename, when OPENFILENAME struct and GetSaveFileName() are used?

StackOverflow https://stackoverflow.com/questions/20310173

Question

I have this function:

void PickupFileAndSave(std::vector<unsigned char> file_data, int *error_code, char *file_mask = "All files (*.*)\0*.*\0\0")
{
    OPENFILENAMEA ofn;       // common dialog box structure
    char szFile[MAX_PATH];   // buffer for file name
    char initial_dir[MAX_PATH] = { 0 };
    GetStartupPath(initial_dir);

    // Initialize OPENFILENAME
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = GetActiveWindow();
    ofn.lpstrFile = szFile;
    // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
    // use the contents of szFile to initialize itself.
    ofn.lpstrFile[0] = '\0';
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = file_mask;
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = initial_dir;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_EXPLORER;

    if (!GetSaveFileNameA(&ofn))
    {
        *error_code = GetLastError();
        return;
    }

    char err_msg[1024] = { 0 };
    std::string file_name = ofn.lpstrFile; //this stores path to file without extension
    file_name.append(".");
    file_name.append(ofn.lpstrDefExt); //this is NULL and fails to copy too
    WriteAllBytes(file_name.c_str(), &file_data[0], file_data.size(), &err_msg[0]);

    if (strlen(err_msg) > 0)
    {
        *error_code = GetLastError();
        return;
    }       
}

I call it that way:

int write_error = 0;
PickupFileAndSave(compressed, &write_error, "RLE compressed files (*.rle)\0*.rle\0\0");

When I choose file it shows in the filter needed extension, but do not add it to lpstrFile.

Any ideas why and how to fix it?

Was it helpful?

Solution

You did not assign lpstrDefExt so the system will not add the extension in case you omit it. So you simply need to initialise the field before you show the dialog:

lpstrDefExt = "rle";

The documentation explains this:

lpstrDefExt

The default extension. GetOpenFileName and GetSaveFileName append this extension to the file name if the user fails to type an extension. This string can be any length, but only the first three characters are appended. The string should not contain a period (.). If this member is NULL and the user fails to type an extension, no extension is appended.


It's not clear from the code in the question but you want to handle the case where there are multiple filters and you wish to append the extension of the selected filter.

The system won't do that for you so you will have to. Read nFilterIndex after you have shown the dialog. That tells you which filter the user selected. Then parse the filter string to obtain the chosen extension, and append it to the filename if it has no extension.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top