用 Windows API PlaySound 企图播放 资源文件里的 Wave 文件的时候,发现第二遍播放没有声音,于是写了段测试代码:
for( int i=0; i<10; i++ )
PlaySound( MAKEINTRESOURCE(IDR_WAVE1), NULL, SND_RESOURCE | SND_SYNC | SND_NODEFAULT );
然后就很意外的发现执行第二遍的时候,PlaySound 会导致一个非法操作,百思不得其解。猜想 PlaySound 对资源文件的内存管理有 BUG。
(NULL 换成 GetModuleHandle(NULL) 还是一样的。)
只能曲线救国了,从网络上找了个 PlayResource 的函数代码,是调用 sndPlaySound 的,结果同样会导致非法操作,貌似 资源的句柄被 sndPlaySound 内部释放了,狂晕。
最终解决方案,将资源加载到内存再播放:
BOOL PlayResource( LPCTSTR resID, HMODULE rhandle=NULL )
{
LPTSTR lpres;
HANDLE hres;
HRSRC hresinfo;
hresinfo= FindResource( rhandle, resID,_T("Wave") );
if(hresinfo == NULL) return FALSE;
DWORD size=SizeofResource( rhandle, hresinfo );
hres = LoadResource( rhandle,hresinfo);
if (hres == NULL) return FALSE;
lpres=(LPTSTR)LockResource(hres);
if(lpres==NULL) return FALSE;
HLOCAL hl=::LocalAlloc( GMEM_FIXED, size );
LPVOID p=LocalLock( hl );
CopyMemory( p, lpres, size );
BOOL ret=sndPlaySound( (LPCTSTR)p, SND_MEMORY | SND_SYNC);
::LocalUnlock( hl );
::LocalFree( hl );
return ret;
}
如果谁了解 PlaySound 播放资源中 Wave 的细节请告知
PS: 貌似只有我的系统有这个问题,看来是特定系统才有的 BUG。我的是 XP 系统,打了所有已知补丁,使用的编译器是 VS 2005 中文版。