如上图所示,Windows7下有一个很有趣的功能,就是可以给单独的进程调节音量。出于好奇,在网上翻了下资料,原来这个功能要归功于Windows7上新的音频接口——Core Audio APIs。这套API是用COM写,各种接口也比较多。但是如果我们的目的只是控制单个进程的音量,那还是很简单的。接下来的代码就是控制进程音量的函数了。
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator); const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator); const IID IID_IAudioSessionManager2 = __uuidof(IAudioSessionManager2); const IID IID_IAudioSessionControl2 = __uuidof(IAudioSessionControl2); const IID IID_ISimpleAudioVolume = __uuidof(ISimpleAudioVolume);
BOOL SetProcessVolume(ULONG target_pid, float level) { CComPtr imm_dev_enumor;
HRESULT hr = imm_dev_enumor.CoCreateInstance( CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL);
if (FAILED(hr)) { return FALSE; }
CComPtr imm_dev; hr = imm_dev_enumor->GetDefaultAudioEndpoint(eRender, eMultimedia, &imm;_dev.p); if (FAILED(hr)) { return FALSE; }
CComPtr session_mgr2; hr = imm_dev->Activate(IID_IAudioSessionManager2, CLSCTX_ALL, NULL, (void **)&session;_mgr2.p); if (FAILED(hr)) { return FALSE; }
CComPtr session_enumor; hr = session_mgr2->GetSessionEnumerator(&session;_enumor.p); if (FAILED(hr)) { return FALSE; }
int count; if (FAILED(hr)) { return FALSE; }
hr = session_enumor->GetCount(&count;); for (int i = 0; i < count; i++) { CComPtr session_ctrl; hr = session_enumor->GetSession(i, &session;_ctrl.p); if (FAILED(hr)) { continue; }
CComPtr session_ctrl2; hr = session_ctrl->QueryInterface(IID_IAudioSessionControl2, (void **)&session;_ctrl2.p); if (FAILED(hr)) {
}
ULONG pid; hr = session_ctrl2->GetProcessId(&pid;); if (FAILED(hr)) { continue; }
if (pid != target_pid) { continue; }
CComPtr simple_vol; hr = session_ctrl2->QueryInterface(IID_ISimpleAudioVolume, (void **)&simple;_vol.p); if (FAILED(hr)) { continue; }
simple_vol->SetMasterVolume(level, NULL); }
return TRUE; }
|