質問

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!

役に立ちましたか?

解決

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()); 

他のヒント

I would agree with Cody Gray that you need escape backlashes only for string literals and that you seem to be mixing Unicode and non-Unicode characters in your code; if your project uses the Unicode character set, you need to change the following:

  • szFile should be of type wchar_t (always watch out when you manually cast types!)
  • ofn.nMaxFile should be assigned _countof(szFile) instead of sizeof()
  • the call to CreateFile() seems to be unnecessary
  • filePathLength should be assigned strlen(currentPath) instead of sizeof(currentPath)
  • if you are returning the pointer to szFile[], szFile needs to be declared static or defined as a global variable outside the function

Replacing \ by /: newPath is a local pointer, you are not allocating memory for it and then returning this value, so even if you declared it as wchar_t newPath[_MAX_PATH], the memory address will be invalid when the function returns -- better to just replace the value of currentPath.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top