2013-07-24 9 views
0

Я пытаюсь опубликовать сообщение в API WIN32, чтобы открыть файл WAV. Я могу сделать это, установив параметр LPARAM в L "C: /path/file.wav" Это работает отлично! Тем не менее, я пытаюсь использовать диалоговое окно для создания строки в пути к файлу. Функция OpenFileDialog может возвращать выбранный путь к файлу как тип данных LPSTR, который звучит идеально! Однако этот путь к файлу распознается как путь к файлу Windows, который состоит из обратных косых черт. Поскольку эти обратные косые черты не экранируются или не заменяются для косой черты, компилятор начинает плакать из-за неправильного сформированного универсального символьного имени. Следовательно, кажется тривиальным заменить все \ в пути к файлу LPSTR для \ или /. Я пытался сделать это несколькими способами, но ничего не работает.Замена обратной косой черты двойной обратной косой чертой или косой чертой в пути к файлу LPSTR

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; 


} 

Следующая строка будет опубликовать сообщение о том, чтобы открыть определенный файл на пути

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

Таким образом, заменив LPARAM со статическим Filepath работает!

Как заменить обратную косую черту в пути к файлу?

Спасибо миллион раз!

+1

Эта проблема для меня не имеет большого значения. Вам не нужно избегать задержек в строках, возвращаемых функциями API. Это требуется только для строк * литералов *. Строка, возвращаемая в 'OPENFILENAME.lpstrFile' с помощью' GetOpenFileName', может использоваться напрямую, без изменений. Он гарантированно является допустимым путем к файлу. Скорее, сообщения об ошибках компилятора являются результатом несоответствия между широкими и узкими типами символов. Вы уверены, что 'UNICODE' и' _UNICODE' определены для вашей сборки? Я замечаю, что вы вызываете 'W' версию * некоторых * API, но не * всех * из них –

+0

Когда я напрямую использую возвращаемую строку, консоль не дает никаких ошибок. Но wav-файл не воспроизводится! Однако, когда я даю ввести путь к файлу вручную с помощью косой черты, он начинает играть. Таким образом, вы бы подумали: функция не возвращает строку !? Этот аргумент недействителен, когда я печатаю его в окне сообщений. Однако, когда я решил распечатать его в консоли с помощью wcout << L ", путь будет« << returnLPWSTR << L »\ n"; путь пуст. –

+0

Возможно, изменение с LPWSTR на LPCWSTR выполнит эту работу !? Но как это можно сделать? –

ответ

1

Есть несколько проблем с кодом:

  1. вы смесительные Ansi и Unicode неверно.

  2. Вы возвращаете указатель на локальный буфер, для которого вы не выделили какую-либо память.

  3. Вы используете PostMessage() для асинхронного размещения локального буфера, который может выйти из области действия и стать недействительным до того, как сообщение будет обработано в окне.

  4. Вы отправляете сообщение, даже если GetOpenFileName() не работает или отменен.

Попробуйте вместо этого:

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

В качестве альтернативы:

#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()); 
+0

в альтернативном решении: не следует ли 'szFile' объявлять' static'? –

+0

@Edward Нет, содержимое локального буфера szFile будет автоматически скопировано в объект 'std :: wstring'. В этом весь смысл использования строкового класса C++: вам больше не нужно управлять ручным управлением памятью. –

+0

@CodyGray: вы правы, я пропустил возвращаемый тип функции - спасибо! –

0

Я согласен с Коди Грей, что вам нужны обратные зазоры только для строковых литералов и что вы, кажется, смешиваете символы Unicode и Unicode в коде; если ваш проект использует набор символов Unicode, необходимо изменить следующие параметры:

  • szFile должен быть типа wchar_t (всегда смотреть, когда вы вручную отливать типов!)
  • ofn.nMaxFile должен быть назначен _countof(szFile) вместо sizeof()
  • вызов CreateFile() представляется излишним
  • filePathLength должен быть назначен strlen(currentPath) вместо sizeof(currentPath)
  • если вы возвращаете указатель на szFile[], szFile должен быть объявлен статическим или определена как глобальная переменная вне функции

Заменив \ на /: newPath является локальным указателем, вы не выделять для него память и затем возвратить это значение, поэтому, даже если вы объявили его wchar_t newPath[_MAX_PATH], адрес памяти будет недействительным, когда функция вернется - лучше просто заменить значение currentPath.

Смежные вопросы