//MixVolumeCtrl.h #pragma once #include <mmsystem.h> #pragma comment(lib, "winmm.lib") class CMixVolumeCtrl { HMIXER m_hMixer; DWORD dwMinVol, dwMaxVol; UINT nVolumeControlID; UINT nMuteControlID; //构析 public: CMixVolumeCtrl() { m_hMixer = NULL; dwMinVol = dwMaxVol = 0; nVolumeControlID = -1; nMuteControlID = -1; } ~CMixVolumeCtrl() { MixClose(); } //打开设备 //当调用的窗口句柄非0时,调用窗口可以加入MM_MIXM_CONTROL_CHANGE消息处理 //成功打开设备返回非0 BOOL MixOpen(DWORD dwType=MIXERLINE_COMPONENTTYPE_SRC_LINE, HWND hCallbackWnd=NULL) { BOOL bRet = FALSE; MixClose(); if( mixerGetNumDevs() > 0) { MMRESULT hr; DWORD fdwOpen = MIXER_OBJECTF_MIXER | (hCallbackWnd? CALLBACK_WINDOW:0); hr = mixerOpen(&m_hMixer, 0, (DWORD_PTR)hCallbackWnd, 0, fdwOpen); if (hr == MMSYSERR_NOERROR) { // get dwLineID MIXERLINE mxl = {0}; mxl.cbStruct = sizeof(MIXERLINE); mxl.dwComponentType = dwType; hr = mixerGetLineInfo((HMIXEROBJ)m_hMixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE); if (hr == MMSYSERR_NOERROR) { MIXERCONTROL mxc = {0}; MIXERLINECONTROLS mxlc = {0}; mxlc.cbStruct = sizeof(MIXERLINECONTROLS); mxlc.dwLineID = mxl.dwLineID; mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; mxlc.cControls = 1; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = &mxc; hr = mixerGetLineControls((HMIXEROBJ)m_hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); if (hr == MMSYSERR_NOERROR)// get volume ControlID { dwMinVol = mxc.Bounds.dwMinimum; dwMaxVol = mxc.Bounds.dwMaximum; nVolumeControlID = mxc.dwControlID; bRet |= 0x01; } mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; hr = mixerGetLineControls((HMIXEROBJ)m_hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); if (hr == MMSYSERR_NOERROR)// get mute ControlID { nMuteControlID = mxc.dwControlID; bRet |= 0x02; } /* mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_SIGNEDMETER; hr = mixerGetLineControls((HMIXEROBJ)m_hMixer, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); if(hr == MMSYSERR_NOERROR) { bRet |= 0x04; } */ } } } return bRet; } void MixClose() { if(m_hMixer) { mixerClose(m_hMixer); m_hMixer = NULL; } dwMinVol = dwMaxVol = 0; nVolumeControlID = -1; nMuteControlID = -1; } HMIXER Get_hMixer() const { return m_hMixer; } DWORD GetMinVolume() const { return dwMinVol; } DWORD GetMaxVolume() const { return dwMaxVol; } UINT GetVolumeControlID() const { return nVolumeControlID; } UINT GetMuteControlID() const { return nMuteControlID; } BOOL GetVolume(DWORD &Vol) { BOOL bRet = 0; if(m_hMixer && (nVolumeControlID != -1)) { MIXERCONTROLDETAILS_UNSIGNED mxcdVolume; MIXERCONTROLDETAILS mxcd = {0}; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = nVolumeControlID; mxcd.cChannels = 1; mxcd.cMultipleItems = 0; mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mxcd.paDetails = &mxcdVolume; if (::mixerGetControlDetails((HMIXEROBJ)m_hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) { Vol = mxcdVolume.dwValue; bRet = TRUE; } } return bRet; } BOOL SetVolume(DWORD Vol) { BOOL bRet = 0; if(m_hMixer && (nVolumeControlID != -1)) { if(Vol < dwMinVol) Vol = dwMinVol; if(Vol > dwMaxVol) Vol = dwMaxVol; MIXERCONTROLDETAILS_UNSIGNED mixVolume = { Vol }; MIXERCONTROLDETAILS mixLine = {0}; mixLine.cbStruct = sizeof(MIXERCONTROLDETAILS); mixLine.dwControlID = nVolumeControlID; mixLine.cChannels = 1; mixLine.cMultipleItems = 0; mixLine.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED); mixLine.paDetails = &mixVolume; if (mixerSetControlDetails((HMIXEROBJ)m_hMixer, &mixLine, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) { bRet = 1; } } return bRet; } BOOL IsMute(BOOL &bVal) { BOOL bRet = 0; if(m_hMixer && (nMuteControlID != -1)) { MIXERCONTROLDETAILS_BOOLEAN mixMute; MIXERCONTROLDETAILS mixd; mixd.cbStruct = sizeof(MIXERCONTROLDETAILS); mixd.dwControlID = nMuteControlID; mixd.cChannels = 1; mixd.cMultipleItems = 0; mixd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mixd.paDetails = &mixMute; if (mixerGetControlDetails((HMIXEROBJ)m_hMixer, &mixd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) { bVal = mixMute.fValue ? TRUE:FALSE; bRet = TRUE; } } return bRet; } BOOL SetMute(BOOL bMute) { BOOL bRet = 0; if(m_hMixer && (nMuteControlID!= -1)) { MIXERCONTROLDETAILS_BOOLEAN mixMute ={bMute}; MIXERCONTROLDETAILS mixd = {0}; mixd.cbStruct = sizeof(MIXERCONTROLDETAILS); mixd.dwControlID = nMuteControlID; mixd.cChannels = 1; mixd.cMultipleItems = 0; mixd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN); mixd.paDetails = &mixMute; if (mixerSetControlDetails((HMIXEROBJ)m_hMixer, &mixd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR) { bRet = TRUE; } } return bRet; } };
//测试Microphone 音量控制
//在一标准对话框程序上添加一个Slider控件 IDC_VOLUME_SLIDER, 用DDX_Control(pDX, IDC_VOLUME_SLIDER, m_SliderCtrl);关联控件
// MicVolumeControlDlg.h : 头文件 // #pragma once #include "MixVolumeCtrl.h" // CMicVolumeControlDlg 对话框 class CMicVolumeControlDlg : public CDialog { public: CMixVolumeCtrl m_MicrophonCtrl; CSliderCtrl m_SliderCtrl; protected: virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); virtual BOOL OnInitDialog(); //其它标准的部分就不再列出
// MicVolumeControlDlg.cpp : 实现文件 // #include "stdafx.h" #include "MicVolumeControlDlg.h" BOOL CMicVolumeControlDlg::OnInitDialog() { CDialog::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 SetIcon(m_hIcon, TRUE); // 设置大图标 SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 if(m_MicrophonCtrl.MixOpen(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, GetSafeHwnd())) { m_SliderCtrl.SetRange(m_MicrophonCtrl.GetMinVolume(), m_MicrophonCtrl.GetMaxVolume(), TRUE); m_SliderCtrl.SetTic(m_MicrophonCtrl.GetMaxVolume()); m_SliderCtrl.SetTicFreq(m_MicrophonCtrl.GetMaxVolume()/10); DWORD dwVolume ; if(m_MicrophonCtrl.GetVolume(dwVolume)) m_SliderCtrl.SetPos(dwVolume); } else { AfxMessageBox(_T("open MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE device failed")); } return TRUE; // 除非将焦点设置到控件,否则返回 TRUE } LRESULT CMicVolumeControlDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: 在此添加专用代码和/或调用基类 switch(message) { case(WM_HSCROLL): { if(lParam && ((HWND)lParam == m_SliderCtrl.m_hWnd)) { int nPos = m_SliderCtrl.GetPos(); if(nPos <=0) m_MicrophonCtrl.SetMute(TRUE); else { m_MicrophonCtrl.SetMute(FALSE); m_MicrophonCtrl.SetVolume(nPos); } } break; } case(MM_MIXM_CONTROL_CHANGE): { if(m_MicrophonCtrl.Get_hMixer() == (HMIXER)wParam && m_MicrophonCtrl.GetVolumeControlID() == (UINT)lParam) { DWORD dwVolume; if(m_MicrophonCtrl.GetVolume(dwVolume)) m_SliderCtrl.SetPos(dwVolume); } break; } } return CDialog::WindowProc(message, wParam, lParam); }