Я пытаюсь отправить сообщение в WIN32 API, чтобы открыть файл WAV. Я могу сделать это, установив для параметра LPARAM значение L «C: /path/file.wav». Это работает отлично! Тем не менее, я пытался использовать диалоговое окно для генерации строки в путь к файлу. Функция OpenFileDialog может возвращать выбранный путь к файлу как тип данных LPSTR, что звучит идеально! Однако этот путь к файлу распознается как путь к файлу Windows и состоит из обратной косой черты. Поскольку эти обратные косые черты не экранированы и не заменены на прямую косую черту, компилятор начинает плакать из-за неверно сформированного универсального имени символа. Поэтому кажется тривиальным заменить все \ в пути к файлу 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 на статический путь к файлу работает!
Как мне заменить обратную косую черту в пути к файлу?
Спасибо миллион раз!
Есть несколько проблем с вашим кодом:
Вы смешиваете Ansi и Unicode неправильно.
вы возвращаете указатель на локальный буфер, для которого у вас нет выделенной памяти.
ты используешь PostMessage()
асинхронно размещать локальный буфер, который может выйти за пределы области и стать недействительным до того, как окно будет обработано сообщением.
Вы публикуете сообщение, даже если 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());
Я согласен с Коди Греем в том, что вам нужны экранирующие экраны только для строковых литералов и что вы, похоже, смешиваете символы 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
,