//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);
}