//========================================================================
//TITLE:
// WinCE系统音量的设置
//AUTHOR:
// norains
//DATE:
// Sunday 8-April-2007
//Environment:
// EVC4.0 + Standard SDK 4.2
// EVC4.0 + Standard SDK 5.0
//========================================================================
首先我们来看一段最简单的改变音量的代码:
DWORD dwVolume = 0xAAAAAAAA;
waveOutSetVolume(0,dwVolume);
waveOutSetVolume()的第一个参数是设备ID,因为需要更改的是整个系统音量,所以在这里直接取0值即可;第二个参数是需要设置的音量数值,范围是从 0x0 ~ 0xFFFFFFFF.
但这个函数的功能却也是非常有限的,也就是说,它只能更改系统的主音量;如果想修改屏幕点击声,则就无能为力.
有些细心的朋友会从"控制面板"的"声音"入手,发现每次在控制面板调节声音,相应的"ControlPanel/Volume"下的键值数值都会变更.但如果是直接修其下的改注册表,却是无论如何都达不到相应的功能的----因为没有通知系统,注册表已经被修改.
如果需要告知系统,注册表已经修改,并请系统依照修改的数值来更改音量,则需要调用微软一个未公开的函数:AudioUpdateFromRegistry().
这个函数在文档中是无法搜索到,如果需要调用这个函数,可以有两种方法.
一是直接包含"pwinuser.h"文件,然后直接调用.
二是调用coredll.dll库,引出该函数并使用.
这里展示一个调用的例子:
typedef void (WINAPI *DLL_AUDIOUPDATEFROMREGISTRY)();
DLL_AUDIOUPDATEFROMREGISTRY Dll_AudioUpdateFromRegistry = NULL;
HINSTANCE hCoreDll = LoadLibrary(TEXT("coredll.dll"));
if (hCoreDll)
...{
Dll_AudioUpdateFromRegistry = (DLL_AUDIOUPDATEFROMREGISTRY)GetProcAddress(hCoreDll, _T("AudioUpdateFromRegistry"));
if (Dll_AudioUpdateFromRegistry)
...{
(Dll_AudioUpdateFromRegistry)();
}
只要更新了注册表,然后调用该函数,则系统会根据键值来进行相应的调整.
那么现在让我们来看看位于"ControlPanel/Volume"注册表中各键值的意义:
Volume: 系统的主音量,范围是0x0 ~ 0xFFFFFFFF.
Screen: 屏幕敲击声. 当数值为0时即为无声,1为柔和,65538为洪亮
Key: 键盘敲击声,数值的意义和Screen相同.
Mute: 控制其它静音的选项. 置0x04位为1时允许事件声音,0x02允许应用程序声音,0x01允许警告声.需要注意的是,如果不允许应用程序声音,则警告声位也将被忽略.
如果每次更改音量都要改写注册表,调用动态链接库,会显得比较麻烦.为了写代码的便利,在此封装了这个声音的操作:
(注:CReg 请参见此篇文章:http://blog.csdn.net/norains/archive/2007/04/08/1556296.aspx)
/**///////////////////////////////////////////////////////////////////////
// SysVolume.h: interface for the CSysVolume class.
//
//Version:
// 1.0.0
//Date:
// 2007.04.08
/**///////////////////////////////////////////////////////////////////////
#ifndef SYSVOLUME_H
#define SYSVOLUME_H
#include "Reg.h"
//-------------------------------------------------------------------------
//Macro define
#define MIN_VOLUME 0
#define MAX_VOLUME 0xFFFFFFFF
//-------------------------------------------------------------------------
//Enum value
enum VolumeModeType
...{
VOL_SOFT,
VOL_LOUD,
VOL_MUTE
};
//------------------------------------------------------------------------
class CSysVolume
...{
public:
BOOL SetVolumeScreenTap(VolumeModeType volMode);
BOOL SetVolumeKeyClick(VolumeModeType volMode);
BOOL EnableSoundNotification(BOOL bEnable);
BOOL EnableSoundApplication(BOOL bEnable);
BOOL EnableSoundEvent(BOOL bEnable);
BOOL SetVolume(DWORD dwVol);
CSysVolume();
virtual ~CSysVolume();
protected:
BOOL Apply();
CReg m_Reg;
};
#endif //#ifndef SYSVOLUME_H
/**///////////////////////////////////////////////////////////////////////
// SysVolume.cpp: implementation of the CSysVolume class.
//
/**///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SysVolume.h"
//======================================================================
//Macro define
//Registry KEY
#define BASE_KEY HKEY_CURRENT_USER
#define SUB_KEY TEXT("ControlPanel/Volume")
#define VALUE_VOLUME TEXT("Volume")
#define VALUE_SCREEN TEXT("Screen")
#define VALUE_KEY TEXT("key")
#define VALUE_MUTE TEXT("Mute")
//For the screen tap and the key click
#define VOL_VALUE_MUTE 0
#define VOL_VALUE_LOUD 65538
#define VOL_VALUE_SOFT 1
//The bit for sound
#define BIT_EVENT 0x4
#define BIT_APPLICATION 0x2
#define BIT_NOTIFICATION 0x1
//======================================================================
/**///////////////////////////////////////////////////////////////////////
// Construction/Destruction
/**///////////////////////////////////////////////////////////////////////
CSysVolume::CSysVolume()
...{
m_Reg.Create(BASE_KEY, SUB_KEY);
}
CSysVolume::~CSysVolume()
...{
}
//---------------------------------------------------------------------
//Description:
// Apply the volume
//---------------------------------------------------------------------
BOOL CSysVolume::Apply()
...{
typedef void (WINAPI *DLL_AUDIOUPDATEFROMREGISTRY)();
DLL_AUDIOUPDATEFROMREGISTRY Dll_AudioUpdateFromRegistry = NULL;
HINSTANCE hCoreDll = LoadLibrary(TEXT("coredll.dll"));
if (hCoreDll)
...{
Dll_AudioUpdateFromRegistry = (DLL_AUDIOUPDATEFROMREGISTRY)GetProcAddress(hCoreDll, _T("AudioUpdateFromRegistry"));
if (Dll_AudioUpdateFromRegistry)
...{
(Dll_AudioUpdateFromRegistry)();
}
else
...{
return FALSE;
}
FreeLibrary(hCoreDll);
}
else
...{
return FALSE;
}
return TRUE;
}
//---------------------------------------------------------------------
//Description:
// Enable the sound for events
//---------------------------------------------------------------------
BOOL CSysVolume::EnableSoundEvent(BOOL bEnable)
...{
if(m_Reg.IsOK() != TRUE)
...{
return FALSE;
}
DWORD dwVal = m_Reg.GetValueDW(VALUE_MUTE);
if(bEnable == TRUE)
...{
dwVal |= BIT_EVENT;
}
else
...{
dwVal &= ~BIT_EVENT;
}
m_Reg.SetDW(VALUE_MUTE,dwVal);
return Apply();
}
//---------------------------------------------------------------------
//Description:
// Enable the sound for application
//---------------------------------------------------------------------
BOOL CSysVolume::EnableSoundApplication(BOOL bEnable)
...{
if(m_Reg.IsOK() != TRUE)
...{
return FALSE;
}
DWORD dwVal = m_Reg.GetValueDW(VALUE_MUTE);
if(bEnable == TRUE)
...{
dwVal |= BIT_APPLICATION;
}
else
...{
dwVal &= ~BIT_APPLICATION;
}
m_Reg.SetDW(VALUE_MUTE,dwVal);
return Apply();
}
//---------------------------------------------------------------------
//Description:
// Enable the sound for notifications. If the sound of application is
//mute, the sound of notification is mute too.
//---------------------------------------------------------------------
BOOL CSysVolume::EnableSoundNotification(BOOL bEnable)
...{
if(m_Reg.IsOK() != TRUE)
...{
return FALSE;
}
DWORD dwVal = m_Reg.GetValueDW(VALUE_MUTE);
if(bEnable == TRUE)
...{
dwVal |= BIT_NOTIFICATION;
}
else
...{
dwVal &= ~BIT_NOTIFICATION;
}
m_Reg.SetDW(VALUE_MUTE,dwVal);
return Apply();
}
//---------------------------------------------------------------------
//Description:
// Set the key click volume
//---------------------------------------------------------------------
BOOL CSysVolume::SetVolumeKeyClick(VolumeModeType volMode)
...{
DWORD dwVol = 0;
switch(volMode)
...{
case VOL_SOFT:
dwVol = VOL_VALUE_SOFT;
break;
case VOL_LOUD:
dwVol = VOL_VALUE_LOUD;
break;
case VOL_MUTE:
dwVol = VOL_VALUE_MUTE;
break;
}
if(m_Reg.IsOK() != TRUE)
...{
return FALSE;
}
m_Reg.SetDW(VALUE_KEY,dwVol);
return Apply();
}
//---------------------------------------------------------------------
//Description:
// Set the screen tap volume
//---------------------------------------------------------------------
BOOL CSysVolume::SetVolumeScreenTap(VolumeModeType volMode)
...{
DWORD dwVol = 0;
switch(volMode)
...{
case VOL_SOFT:
dwVol = VOL_VALUE_SOFT;
break;
case VOL_LOUD:
dwVol = VOL_VALUE_LOUD;
break;
case VOL_MUTE:
dwVol = VOL_VALUE_MUTE;
break;
}
if(m_Reg.IsOK() != TRUE)
...{
return FALSE;
}
m_Reg.SetDW(VALUE_SCREEN,dwVol);
return Apply();
}
//---------------------------------------------------------------------
//Description:
// Set the volume.
//
//Parameters:
// dwVol: The volume to set. And the range is MIN_VOLUME ~ MAX_VOLUME
//---------------------------------------------------------------------
BOOL CSysVolume::SetVolume(DWORD dwVol)
...{
if(dwVol < MIN_VOLUME || dwVol > MAX_VOLUME)
...{
return FALSE;
}
m_Reg.SetDW(VALUE_VOLUME,dwVol);
return Apply();
}
由于CSysVolume类将复杂的操作封装在内部,因此设置音量的非常简单.
以更改屏幕敲击声为洪亮为例:
CSysVolume sysVol;
sysVol.SetVolumeScreenTap(VOL_LOUD);
Mobile5.0/6.0下设置铃声音量
2008-09-23 15:04
//设置铃声大小 iVol: 0-5
void SetRingVol(int iVol)
{
int res;
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//SoundCategories//Ring//");
res = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey);
DWORD dwValue = iVol;
DWORD dwType = REG_DWORD;
DWORD dwcbData = sizeof(DWORD);
if(res != ERROR_SUCCESS)
return;
RegSetValueEx(hKey, _T("InitVol"), 0, dwType, (BYTE*)&dwValue, dwcbData);
RegCloseKey(hKey);
}
//获取铃声大小 iVol: 0-5
void GetRingVol(int *iVol)
{
int res;
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//SoundCategories//Ring//");
res = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey);
if(res != ERROR_SUCCESS)
return;
DWORD dwValue;
DWORD dwType = REG_DWORD;
DWORD dwcbData = sizeof(DWORD);
res = RegQueryValueEx(hKey, _T("InitVol"), 0, &dwType, (BYTE *)&dwValue, &dwcbData);
if(res == ERROR_SUCCESS)
*iVol = (int)dwValue;
RegCloseKey(hKey);
}
//获取显示状态 0:打开 1:振动 2:关闭
void GetMode(int *iMode)
{
int res;
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//Notifications//ShellOverrides//");
res = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey);
if(res != ERROR_SUCCESS)
return;
DWORD dwValue;
DWORD dwType = REG_DWORD;
DWORD dwcbData = sizeof(DWORD);
res = RegQueryValueEx(hKey, _T("Mode"), 0, &dwType, (BYTE *)&dwValue, &dwcbData);
if(res == ERROR_SUCCESS)
*iMode = (int)dwValue;
RegCloseKey(hKey);
}
//设置显示状态 0:打开 1:振动 2: 关闭
void SetMode(int iMod)
{
int res;
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//Notifications//ShellOverrides//");
res = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey);
if(res != ERROR_SUCCESS)
return;
DWORD dwValue = iMod;
DWORD dwType = REG_DWORD;
DWORD dwcbData = sizeof(DWORD);
res = RegSetValueEx(hKey, _T("Mode"), 0, dwType, (BYTE *)&dwValue, dwcbData);
RegCloseKey(hKey);
}
//设置铃声模式 0:铃声 1:振动 2:无
void SetSound(int iStatus)
{
int res;
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//Sounds//RingTone0//");
res = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey);
if(res != ERROR_SUCCESS)
return;
TCHAR szData[50];
DWORD dwType = REG_SZ;
DWORD dwcbData = sizeof(szData);
if(iStatus == 0)
{//响铃方式,则铃声为SavedSound下的铃声
RegQueryValueEx(hKey, _T("SavedSound"), 0, &dwType, (BYTE *)szData, &dwcbData);
}
else if(iStatus == 1)
{//振动方式
_tcscpy(szData, _T("*vibrate*"));
}
else if(iStatus == 2)
{//不响铃也不振动
_tcscpy(szData, _T("*none*"));
}
RegSetValueEx(hKey, _T("Sound"), 0, dwType, (BYTE *)szData, dwcbData);
RegCloseKey(hKey);
SetMode(iStatus);
}
//获取铃声模式 0:铃声 1:振动 2:无
int GetSound()
{
int res;
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//Sounds//RingTone0//");
res = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey);
if(res != ERROR_SUCCESS)
return FALSE;
TCHAR szData[50];
DWORD dwType = REG_SZ;
DWORD dwcbData = sizeof(szData);
RegQueryValueEx(hKey, _T("Sound"), 0, &dwType, (BYTE *)szData, &dwcbData);
if( _tcscmp(szData, _T("*vibrate*")) == 0) //振动
res = 1;
else if(_tcscmp(szData, _T("*none*")) == 0) //无
res = 2;
else
res = 0; //铃声
RegCloseKey(hKey);
return res;
}
//获取已保存的铃声音量 iSRVol : 0 ~ 5
int GetSavedRingVol()
{
int res;
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//Notifications//ShellOverrides//");
res = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey);
if(res != ERROR_SUCCESS)
return FALSE;
DWORD dwValue = 0;
DWORD dwType = REG_DWORD;
DWORD dwcbData = sizeof(DWORD);
res = RegQueryValueEx(hKey, _T("SavedRingerVolume"), 0, &dwType, (BYTE *)&dwValue, &dwcbData);
if(res == ERROR_SUCCESS)
{//转换为0~5
dwValue /= 0x33333333;
}
RegCloseKey(hKey);
return dwValue;
}
//保存Mobile系统主音量
void SaveSysVol(DWORD dwValue)
{
HKEY hKey;
TCHAR *szSubKey = _T("ControlPanel//Notifications//ShellOverrides//");
if(!RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_ALL_ACCESS, &hKey))
{
DWORD dwType = REG_DWORD;
DWORD dwcbData = sizeof(DWORD);
RegSetValueEx(hKey, _T("SavedVolume"), 0, dwType, (BYTE *)&dwValue, dwcbData);
RegCloseKey(hKey);
}
}
//这是一个示例,设置系统主音量
void SetVolume(DWORD dwVol)
{
int iSound = GetSound(); //获取先前铃声模式
if(iSound == 0) //先前为响钤方式,直接调音量
{
waveOutSetVolume(NULL, dwVol);
SaveSysVol(dwVol); //需要保存系统音量
}
else //先前为其它状态
{
waveOutSetVolume(NULL, dwVol);
SaveSysVol(dwVol); //设置完音量后保存
SetSound(0); //设置为响铃方式
SetMode(0); //显示为"打开"状态
int iRingVol = GetSavedRingVol(); //获取先前铃声音量
SetRingVol(iRingVol); //恢复铃声音量
}
}
Mobile5.0与Mobile6.0下调整响铃方式的区别之一
Mobile5.0时调整为振动或无方式时,系统主量必须调为0,而Mobile6.0则无此限制
WINCE中音量的调节
2008-09-22 17:17
声音设置都在注册表:HKEY_CURRENT_USER/ControlPanel/Volume下,里面的几个键值都是控制声音的。先解释如下:
Volume: 系统的主音量,范围是0x0 ~ 0xFFFFFFFF.
Screen: 屏幕敲击声. 当数值为0(或65536)无声,1为柔和,65538为洪亮
Key: 键盘敲击声,数值的意义和Screen相同.
Mute: 控制其它静音的选项. 置0x04位为1时允许事件声音,0x02允许应用程序声音,0x01允许警告声.需要注意的是,如果不允许应用程序声音,则警告声位也将被忽略.
知道各个键值的意义后,我从最主要的系统的主音量Volume说起。
一、对系统主音量Volume的操作
首先我们来看一段最简单的改变音量的代码:
DWORD dwVolume = 0xAAAAAAAA;
waveOutSetVolume(0,dwVolume);
waveOutSetVolume()的第一个参数是设备ID,因为需要更改的是整个系统音量,所以在这里直接取0值即可;第二个参数是需要设置的音量数值,范围是从 0x0 ~ 0xFFFFFFFF。
通过waveOutSetVolume()这个API,我们可以很容易的更改系统设备的音量,但这个时候,如果你去查看注册表的Volume的键值是没有变化的,因为它只修改了设备的音量,变化还没有这么快到达注册表。但你可以到“控制面板”中的“音量与声音”打开一下,注册表的值也随之改变。(反之,通过对注册表的单独操作对具体音量是起不到作用的)
所以,我对音量的操作,首先对注册表中的Volume进行操作,在用waveOutSetVolume()这个API具体改变音量,这样可以达到一致。具体操作代码如下:
DWORD dwVolume = 0;
CReg* pVolumeReg = NULL;
pVolumeReg = new CReg( HKEY_CURRENT_USER, TEXT("ControlPanel//Volume") );
dwVolume = pVolumeReg->ValueDW(TEXT("Volume"));
。。。。。。。。。。。。。。对音量的具体设置
if( waveOutSetVolume(NULL, dwVolume) != MMSYSERR_NOERROR ) 音量设置是否成功
{
DBGMSG(ZONE_1, (TEXT("waveOutSetVolume failed, [MainLayere.cpp, SetVolume]")));
}
pVolumeReg->SetDW(TEXT("Volume"),dwVolume); 设置注册表
delete pVolumeReg;
pVolumeReg = NULL;
上面用到的CReg是一个对注册表操作的类,是我们小组用的一个基类(Walzer注:在WINCE500目录下搜索CReg可以找到, 其实微软的人也很懒)。这样我们对主音量设置就很完善了。
二、对硬件按键声音(KEY键值)的设置
尽管waveOutSetVolume()这个API对主音量设置很好用,但这个函数的功能却也是非常有限的,也就是说,它只能更改系统的主音量;如果想修改硬件按键声音或屏幕敲击声,则就无能为力.
有些比较细心的朋友可能会从"控制面板"的"声音"入手,发现每次在控制面板调节声音,相应的"ControlPanel/Volume"下的键值数值都会变更.但如果是直接修其下的改注册表,却是无论如何都达不到相应的功能的----因为没有通知系统,注册表已经被修改.
如果需要告知系统,注册表已经修改,并请系统依照修改的数值来更改音量,则需要调用微软一个未公开的API:AudioUpdateFromRegistry().
这个API在文档中是无法搜索到,如果需要调用这个函数,可以有两种方法.
一是直接包含"pwinuser.h"文件,然后直接调用.
二是调用coredll.dll库,引出该函数并使用.
第一种方法比较不稳定,因为有一些人的sdk中没有这个pwinuser.h文件,所以程序找不到。我还是推荐用第二种方法,直接调用该API(就象我们组长说的暴力调用API,这个方法真的还是不错的。)
其具体代码如下:
typedef void (WINAPI *DLL_AUDIOUPDATEFROMREGISTRY)();定义一个新类型指针,指向WINAPI
DLL_AUDIOUPDATEFROMREGISTRY Dll_AudioUpdateFromRegistry = NULL;
HINSTANCE hCoreDll = LoadLibrary(TEXT("coredll.dll"));
if (hCoreDll)
{
Dll_AudioUpdateFromRegistry = (DLL_AUDIOUPDATEFROMREGISTRY)GetProcAddress(hCoreDll, _T("AudioUpdateFromRegistry")); 调用该API
if (Dll_AudioUpdateFromRegistry)
{
(Dll_AudioUpdateFromRegistry)();
}
else
{
return FALSE;
}
FreeLibrary(hCoreDll);
}
else
{
return FALSE;
}
return TRUE;
这样通过修改注册表Key键值,然后通过调用该方法就能实现对按键声音的设置。
对Screen和Mute的设置也可以用该方法,至此,对WINCE各种音量的设置就基本掌握了
from:http://blog.csdn.net/li_guotao/archive/2008/08/24/2824637.aspx