Search code examples
c++winapiopenfiledialogwchar-t

Replacing backslash with double backslash or forward slash in LPSTR filepath


I am trying to post a message to the WIN32 API to open a WAV File. I can do this by setting the LPARAM parameter to L"C:/path/file.wav" This works excelent! However, I have been trying to use a dialogbox to generate a string to a filepath. The OpenFileDialog function can return the selected filepath as a LPSTR datatype, which sounds perfect! However, this filepath is recognized as a windows filepath, thereby consisting of backslashes. Since these backslashes are not escaped or replaced for a forward slash, the compiler starts crying due to an incorrect formed universal character name. Therfore, it seems trivial to replace all the \ in the LPSTR filepath for \ or /. I have been trying to do this in several ways but nothing seems to work.

wchar_t* SelectAudioFile(HWND windowHandle) {
    OPENFILENAME ofn;      // common dialog box structure
    char szFile[260];      // buffer for file name

    // Initialize OPENFILENAME
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = windowHandle;
    ofn.lpstrFile = (LPWSTR)szFile;

    ofn.lpstrFile[0] = '\0';
    ofn.nMaxFile = sizeof(szFile);

    ofn.lpstrFilter = L"Waveform Audio File Format (*.wav)\0*.wav\0";

    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    // Display the Open dialog box.

    if (GetOpenFileName(&ofn)==TRUE) {
        CreateFile(ofn.lpstrFile,
            GENERIC_READ,
            0,
            (LPSECURITY_ATTRIBUTES) NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            (HANDLE) NULL);
        MessageBox(windowHandle,ofn.lpstrFile,0,0);
    }

     //Here the backslash should be escaped or replaced.

    const wchar_t * currentPath = ofn.lpstrFile; //This is a LPSTR 
    wchar_t * newPath;
    int filePathLength = sizeof(currentPath);

    for (int i=0; i < filePathLength; i++) {
        if (currentPath[i] == "\\") {
            newPath[i] = "\\\\";
        } else {
            newPath[i] = filePath[i];
        }
    }
    return newPath;


}

The following line would post a message telling it to open a certain file at a path

PostMessageW(hwnd, WMA_OPEN, 0, (LPARAM)SelectAudioFile(hwnd)); 

Thus replacing the LPARAM with a static filepath works!

How should I replace the backslashes in the filepath?

Thanks a million times!


Solution

  • There are several problems with your code:

    1. you are mixing Ansi and Unicode incorrectly.

    2. you are returning a pointer to a local buffer that you have not allocated any memory for.

    3. you are using PostMessage() to asynchronously post a local buffer that may go out of scope and become invalid before the message gets processed by the window.

    4. you are posting the message even if GetOpenFileName() fails or is canceled.

    Try this instead:

    bool SelectAudioFile(HWND windowHandle, wchar_t *audioFile, int maxAudioFile)
    {
        OPENFILENAMEW ofn = {0};
    
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = windowHandle;
        ofn.lpstrFile = audioFile;
        ofn.nMaxFile = maxAudioFile;
        ofn.lpstrFilter = L"Waveform Audio File Format (*.wav)\0*.wav\0";
        ofn.nFilterIndex = 1;
        ofn.lpstrFileTitle = NULL;
        ofn.nMaxFileTitle = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
    
        if (GetOpenFileNameW(&ofn))
        {
            MessageBoxW(windowHandle, audioFile, 0, 0);
            return true;
        }
    
        return false;
    }
    

    wchar_t szAudioFile[MAX_PATH+1] = {0};
    if (SelectAudioFile(hwnd, szAudioFile, MAX_PATH))
        SendMessageW(hwnd, WMA_OPEN, 0, (LPARAM)szAudioFile); 
    

    Alternatively:

    #include <string>
    
    std::wstring SelectAudioFile(HWND windowHandle)
    {
        OPENFILENAMEW ofn = {0};
        wchar_t szFile[MAX_PATH+1] = {0};
    
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = windowHandle;
        ofn.lpstrFile = szFile;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFilter = L"Waveform Audio File Format (*.wav)\0*.wav\0";
        ofn.nFilterIndex = 1;
        ofn.lpstrFileTitle = NULL;
        ofn.nMaxFileTitle = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
    
        if (GetOpenFileNameW(&ofn))
            MessageBoxW(windowHandle, szFile, 0, 0);
    
        return szFile;
    }
    

    std::wstring audioFile = SelectAudioFile(hwnd);
    if (audioFile.length() > 0)
        SendMessageW(hwnd, WMA_OPEN, 0, (LPARAM)audioFile.c_str());