您的位置:首页 > 其它

mfc使用Slider控件控制系统的音量

2012-04-03 08:49 260 查看
mfc使用Slider控件控制系统的音量

文章转载自:/article/11014534.html

===================================================================

之前想实现这个功能,找了很多资料,全都不给力,最后发现Microsoft给的那才是可以用的,总的来说就是使用mixer api来打开混音器设备、获得音频线路信息、然后设定属性。实现这个之后,就可以用在你写的程序比如播放器上面啦。

总共就下面几个函数:

通过这9个API,我们就可以来控制音频的输入和输出设备了,其实有关这几个函数的定义你可以在C:/Program Files/Microsoft Visual Studio/VC98/Include/mmsystem.h文件中找到。下面我简单介绍一下这几个函数,详细地介绍你可以参见msdn。

  mixerOpen和mixerClose函数用来打开和关闭混音器设备

  mixerGetNumDevs可以确定系统中有多少混音器设备

  mixerGetDevCaps函数可以确定混音器设备的能力

  mixerGetLineInfo可以检索指定音频线路的信息

  mixerGetLineControls用于检索一个或者多个与音频线路相关的控制的通用信息

  mixerGetControlDetails用于检索与某个音频线路相关的一个控制的属性

  mixerSetControlDetails用于设置制定控制的属性。

对话框工程(工程->设置->链接 添加winmm.lib,头文件包含mmsystem.h),添加一个slider控件,关联control变量m_volume

我把那个滑块设为了垂直样式,仿右下角那个小喇叭的风格:)

但是这样一来我发现一个问题,垂直样式默认刻度是上边小下边大,而我想实现的是下边为0刻度,上面为最大值,google一下无解决方案。

csdn就是智慧无穷,我被鄙视了。。。kemee童鞋说“..... 我是自己再做个运算的....比如0~100,不管什么数据要在控件上显示了,就和100先做个运算,再设置,这样0就显示100,100的时候就显示0了。。”,就是这么无须解释,我承认我脑袋很锈

给CSliderDlg添加成员变量:

MIXERCONTROLDETAILS_SIGNED volStruct;

MIXERCONTROLDETAILS mxcd;

MIXERLINECONTROLS mxlc;

MIXERLINE mxl;

MIXERCONTROL mxc;

HMIXER m_hmx;

在OnInitDialog中添加一下代码

[cpp]
view plaincopyprint?

// TODO: Add extra initialization here
unsigned long err;
CString str;
err = mixerOpen(&m_hmx,0,0,0,0);
if(err)
{
MessageBox("ERROR:Can't open Mixer Device!");
}
//初始化MIXERLINE结构体
ZeroMemory(&mxl,sizeof(mxl));
mxl.cbStruct = sizeof(mxl);
// 指出需要获取的通道,扬声器用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
if(mixerGetLineInfo((HMIXEROBJ)m_hmx,&mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE))
{
MessageBox("Couldn't get the mixer line!");
}
// 取得控制器.
ZeroMemory(&mxlc, sizeof(mxlc));
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;

mxlc.cControls =1;
mxlc.cbmxctrl = sizeof(mxc);
mxlc.pamxctrl = &mxc;
ZeroMemory(&mxc, sizeof(mxc));
mxc.cbStruct = sizeof(mxc);
if(mixerGetLineControls((HMIXEROBJ)m_hmx,&mxlc,
MIXER_GETLINECONTROLSF_ONEBYTYPE))
{
MessageBox("取得控制器失败!");
}
// 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.

// 初始化MIXERCONTROLDETAILS结构体
ZeroMemory(&mxcd, sizeof(mxcd));
mxcd.cbStruct = sizeof(mxcd);
mxcd.cbDetails = sizeof(volStruct);
mxcd.dwControlID = mxc.dwControlID;
mxcd.paDetails = &volStruct;
mxcd.cChannels = 1;

// 获得音量值
if(mixerGetControlDetails((HMIXEROBJ)m_hmx, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE))
{
MessageBox("无法获得音量");
}
//str.Format("%d %d %d",mxc.Bounds.dwMinimum,mxc.Bounds.dwMaximum,volStruct.lValue);
//MessageBox(str);
/*unsigned long mixerID;
err = mixerGetID((struct HMIXEROBJ__ *)m_hmx, (unsigned int *)&mixerID, MIXER_OBJECTF_HMIXER);
if (err)
{
MessageBox("ERROR: Can't get Mixer Device ID!");
}
else

{
str.Format("Mixer Device ID = %d/n", mixerID);
MessageBox(str);
}

MIXERCAPS mixcaps;
unsigned long iNumDevs, i;
// 获取系统中混音器设备个数
iNumDevs = mixerGetNumDevs();
// 遍历所有的混音器并显示它们的ID和名称
for (i = 0; i < iNumDevs; i++)
{
// 获取下一个混音器设备的信息

if (!mixerGetDevCaps(i, &mixcaps, sizeof(MIXERCAPS)))
{

// 显示ID和名称
str.Format("Device ID #%u: %s/r/n", i, mixcaps.szPname);
MessageBox(str);
}

}*/
m_volume.SetRange(mxc.Bounds.dwMinimum,mxc.Bounds.dwMaximum);
m_volume.SetPos(mxc.Bounds.dwMaximum - volStruct.lValue);

[cpp]
view plaincopyprint?

void CSliderDlg::OnVScroll(UINT nSBCode,UINT
nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if((CWnd*)pScrollBar == (CWnd*)&m_volume)
{
int pos = mxc.Bounds.dwMaximum - m_volume.GetPos();
CString str;
str.Format("%d",pos);
//MessageBox(str);
volStruct.lValue = pos; //想要设置的值
mixerSetControlDetails((HMIXEROBJ)m_hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
}
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CSliderDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
if((CWnd*)pScrollBar == (CWnd*)&m_volume)
{
int pos = mxc.Bounds.dwMaximum - m_volume.GetPos();
CString str;
str.Format("%d",pos);
//MessageBox(str);
volStruct.lValue = pos; //想要设置的值
mixerSetControlDetails((HMIXEROBJ)m_hmx, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
}
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
}


成功,运行试一下吧!

下面文章内容来自:http://dev.21tx.com/2005/11/17/14840_2.html

=================================================================

3、下面演示一下如何设置Volume设备的静音

  这里提供了两个函数,GetMute用来获取系统设置中是否对某个音频线路进行了静音操作,SetMute是用来对系统的某个音频线路进行静音操作。

BOOL CMixer::SetMute(DWORD dwSrcType, BOOL bValue)

{

 MIXERLINE mxl;

 if (! GetLineInfo(&mxl, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, dwSrcType))

  return FALSE;

 MIXERCONTROL mxc;

 if (! GetLineControl(&mxc, &mxl, MIXERCONTROL_CONTROLTYPE_MUTE))

  return FALSE;

 MIXERCONTROLDETAILS mxcd;

 MIXERCONTROLDETAILS_BOOLEAN mxcd_f;

 mxcd.cbStruct = sizeof(mxcd);

 mxcd.dwControlID = mxc.dwControlID;

 mxcd.cChannels = 1;

 mxcd.cMultipleItems = 0;

 mxcd.cbDetails = sizeof(mxcd_f);

 mxcd.paDetails = &mxcd_f;

 

 mxcd_f.fValue = bValue;

 if (! SetControlDetails(&mxcd, MIXER_OBJECTF_MIXER))

  return FALSE;

 return TRUE;

}

BOOL CMixer::GetMute(DWORD dwSrcType, BOOL*
PBValue)

{

 MIXERLINE mxl;

 if (! GetLineInfo(&mxl, MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, dwSrcType))

  return FALSE;

 MIXERCONTROL mxc;

 if (! GetLineControl(&mxc, &mxl, MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT ))

  return FALSE;

 MIXERCONTROLDETAILS mxcd;

 MIXERCONTROLDETAILS_BOOLEAN mxcd_f;

 mxcd.cbStruct = sizeof(mxcd);

 mxcd.dwControlID = mxc.dwControlID;

 mxcd.cChannels = 1;

 mxcd.cMultipleItems = 0;

 mxcd.cbDetails = sizeof(mxcd_f);

 mxcd.paDetails = &mxcd_f;

 if (! GetControlDetails(&mxcd, MIXER_GETCONTROLDETAILSF_VALUE))

  return FALSE;

 *pbValue = mxcd_f.fValue;

 return TRUE;

}
  如果用这两个函数呢,下面我演示了如何设置和获取Volume音频线路的静音操作。

BOOL bValue = TRUE;

SetMute(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, bValue);

GetMute(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, &bValue);
  4、下面看看当系统的设置改变时,mixer是如何通知我们的吧。

  还记得我前面讲过的,当我们调用mixeropen时可以传递一个窗口的句柄作为回调窗口,当系统的设置改变,比如音量改变,某个音频线路被静音时,mixer都会给我们的回调窗口发送消息的。

  一般只有两个消息,如下

afx_msg void OnMLChange(WPARAM wParam, LPARAM lParam);

afx_msg void OnMCChange(WPARAM wParam, LPARAM lParam);

ON_MESSAGE(MM_MIXM_LINE_CHANGE, OnMLChange)

ON_MESSAGE(MM_MIXM_CONTROL_CHANGE, OnMCChange)
  其中MM_MIXM_CONTROL_CHANGE 消息中,发送消息的两个参数代表的意思如下

wParam = (WPARAM) hMixer

lParam = (LPARAM) dwControlID
  在MM_MIXM_LINE_CHANGE 消息中,发送消息的参数代表的意思如下

wParam = (WPARAM) hMixer

lParam = (LPARAM) dwLineID
  在我们的应用程序中,我们可以在这两个消息处理函数中调整我们的设置,以对应于系统的改变,比如你的代码可以这样写:

void CMixerControlDlg::OnMCChange(WPARAM wParam, LPARAM lParam)

{

 DWORD dwLValue;

 DWORD dwRValue;

 GetVolume(MIXERLINE_COMPONENTTYPE_DST_SPEAKERS, &dwLValue,&dwRValue);

 //GetVolume函数的定义见下面,然后根据返回的值调整滑动条的位置

 m_SliderVolR.SetPos(MAX_VOL_VALUE - dwLValue);

 m_SliderVolL.SetPos(MAX_VOL_VALUE - dwRValue);

 //你也可以在这里调用GetMute查看Volume是否被静音,

}
  如此你的程序就可以自动的响应系统设置的改变了。

  关于mixer API的应用开发就介绍到这里,记着最后要关闭mixer如此:mixerClose(m_hmx);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: