WinCE系统音量的设置
2010-01-28 17:48

//========================================================================
//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

 
arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()