You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ Win32 API调用PlaySound播放音频时触发Windows默认错误音

问题根因

核心错误为ANSI字符串与宽字符串的错误强制转换:

  • 全链路文件路径存储使用单字节ANSI编码:调用GetOpenFileNameA读取文件路径存入char数组,通过ANSI版本消息向列表框写入、读取路径,最终传入playAudio的参数是const char*类型的ANSI字符串。
  • 调用PlaySound时错误将const char*强转为LPCWSTR(即const wchar_t*宽字符指针),该强转不会做任何编码转换,只会让PlaySound将单字节序列按双字节宽字符规则解析,最终得到乱码路径,无法定位到目标音频文件时,系统就会播放默认错误提示音。
  • 额外隐患:路径存储数组长度仅设为100,未使用系统定义的MAX_PATH宏,长路径场景下会出现截断、内存越界问题;调用PlaySound未加异步标志,播放时会阻塞UI线程导致窗口无响应;窗口过程使用DefWindowProcW宽字符版本,但消息发送混用ANSI接口,存在兼容风险。
修复方案

方案1:快速适配(无需改动现有链路逻辑)

直接调用ANSI版本的PlaySoundA接口,删除错误的强转,补充异步播放标志即可:

void AudioPlayer::playAudio(const char* audioLocation) {
    PlaySoundA(audioLocation, NULL, SND_FILENAME | SND_ASYNC);
}

该方案改动量最小,可立即解决播放错误提示音的问题。

方案2:全链路统一宽字符(推荐,符合现代Windows开发规范)

将所有字符串逻辑统一为Windows原生推荐的宽字符编码,彻底杜绝编码混用隐患:

  1. 修改文件选择逻辑,使用宽字符版本API:
// oshyClientAudioQueue.cpp
void AudioQueue::addNewAudioToQueue(HWND hWnd) {
    OPENFILENAMEW file;
    wchar_t fileName[MAX_PATH] = {0}; // 用MAX_PATH定义数组长度,避免路径截断

    ZeroMemory(&file, sizeof(OPENFILENAMEW));
    file.lStructSize = sizeof(OPENFILENAMEW);
    file.hwndOwner = hWnd;
    file.lpstrFile = fileName;
    file.nMaxFile = MAX_PATH;
    file.lpstrFilter = L"All Files\0*.*\0";
    file.nFilterIndex = 1;

    if (GetOpenFileNameW(&file)) {
        SendMessageW(hAudioQueue, LB_ADDSTRING, 0, (LPARAM)file.lpstrFile);
    }
}
  1. 修改播放按钮触发逻辑,用宽字符数组读取列表框路径:
case BUTTON_PLAY:
    wchar_t text[MAX_PATH];
    SendMessageW(queue.hAudioQueue, LB_GETTEXT, 0, (LPARAM)text);
    audio.playAudio(text);
    break;
  1. 修改playAudio函数签名与实现,匹配宽字符参数:
// 对应头文件中需同步将playAudio参数改为const wchar_t*类型
void AudioPlayer::playAudio(const wchar_t* audioLocation) {
    PlaySoundW(audioLocation, NULL, SND_FILENAME | SND_ASYNC);
}

内容的提问来源于stack exchange,提问作者nekloc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:30:52