rt,找到答案马上给分

解决方案 »

  1.   

    应该到处都有例子,可能msdn sdk中就有例子,可惜我手上没有。帮你up
      

  2.   

    // VolumeOutWave.cpp : Module interface implementation.
    // Developer : Alex Chmut
    // Created : 8/11/98
    #include "StdAfx.h"
    #include "VolumeOutWave.h"/////////////////////////////////////////////////////////////////////////////
    //  Defines
    #define BAD_DWORD (DWORD)-1
    #define WND_CLASS_NAME "Wave Output Volume Msg Wnd Class"
    #define WND_NAME "Wave Output Volume Msg Wnd"/////////////////////////////////////////////////////////////////////////////
    //  Globals
    PCVolumeOutWave g_pThis = NULL;//////////////////////////////////////////////////////////////{{{ Audio specific functions
    #define AUDFREQ 22050 // Frequency
    #define AUDCHANNELS 1 // Number of channels
    #define AUDBITSMPL 16 // Number of bits per sample
    inline
    void SetDeviceType( WAVEFORMATEX* pwfe )
    {
    memset( pwfe, 0, sizeof(WAVEFORMATEX) );
    WORD  nBlockAlign = (AUDCHANNELS*AUDBITSMPL)/8;
    DWORD nSamplesPerSec = AUDFREQ;
    pwfe->wFormatTag = WAVE_FORMAT_PCM;
    pwfe->nChannels = AUDCHANNELS;
    pwfe->nBlockAlign = nBlockAlign;
    pwfe->nSamplesPerSec = nSamplesPerSec;
    pwfe->wBitsPerSample = AUDBITSMPL;
    pwfe->nAvgBytesPerSec = nSamplesPerSec*nBlockAlign;
    }
    //}}} Audio specific functions/////////////////////////////////////////////////////////////////////////////
    //  Implementation
    //////////////
    CVolumeOutWave::CVolumeOutWave()
    : m_bOK(false),
    m_bInitialized(false),
    m_bAvailable(false), m_uMixerID(0L),
    m_dwMixerHandle(0L),
    m_hWnd(NULL), m_dwMinimalVolume(BAD_DWORD),
    m_dwMaximalVolume(BAD_DWORD), m_pfUserSink(NULL),
    m_dwUserValue(0L)
    {
    if ( m_bOK = Init() )
    {
    g_pThis = this;
    if ( !Initialize() )
    {
    Done();
    g_pThis = NULL;
    }
    }
    }
    //////////////
    CVolumeOutWave::~CVolumeOutWave()
    {
    if ( m_bOK )
    Done();
    g_pThis = NULL;
    }
    //////////////
    bool CVolumeOutWave::Init()
    {
    if ( !mixerGetNumDevs() )
    return false;
    // Getting Mixer ID
    HWAVEOUT hwaveOut;
    MMRESULT mmResult;
    WAVEFORMATEX WaveFmt;
    SetDeviceType( &WaveFmt );
    mmResult = waveOutOpen( &hwaveOut, WAVE_MAPPER, &WaveFmt, 0L, 0L, CALLBACK_NULL );
    if ( mmResult != MMSYSERR_NOERROR )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not open WaveOut Mapper. mmResult=%d\n", mmResult );
    return false;
    } else {
    mmResult = mixerGetID( (HMIXEROBJ)hwaveOut, &m_uMixerID, MIXER_OBJECTF_HWAVEOUT );
    waveOutClose( hwaveOut );
    if ( mmResult != MMSYSERR_NOERROR )
    {
    TRACE(".WaveOutputVolume: FAILURE: WaveOut Mapper in Mixer is not available. mmResult=%d\n", mmResult );
    return false;
    }
    }
    // Exposing Window to Mixer
    WNDCLASSEX wcx;
    memset( &wcx, 0, sizeof(WNDCLASSEX) );
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.lpszClassName = WND_CLASS_NAME;
    wcx.lpfnWndProc = (WNDPROC)MixerWndProc;
    ::RegisterClassEx(&wcx);
    m_hWnd = CreateWindow( WND_CLASS_NAME,
    WND_NAME,
    WS_POPUP | WS_DISABLED,
    0, 0, 0, 0,
    NULL, NULL, NULL, NULL );
    if ( !m_hWnd )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not create internal window.\n" );
    return false;
    }
    ::ShowWindow(m_hWnd, SW_HIDE);
    mmResult = mixerOpen( (LPHMIXER)&m_dwMixerHandle, m_uMixerID, (DWORD)m_hWnd, 0L, CALLBACK_WINDOW );
    if ( mmResult != MMSYSERR_NOERROR )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not open Mixer. mmResult=%d\n", mmResult );
    ::DestroyWindow( m_hWnd );
    return false;
    }
    return true;
    }
    //////////////
    void CVolumeOutWave::Done()
    {
    if ( mixerClose( (HMIXER)m_dwMixerHandle ) != MMSYSERR_NOERROR )
    {
    TRACE(".WaveOutputVolume: WARNING: Could not close Mixer.\n" );
    }
    ::DestroyWindow( m_hWnd );
    m_bInitialized = false;
    m_bOK = false;
    }
    //////////////
    void CVolumeOutWave::OnControlChanged( DWORD dwControlID )
    {
    if ( m_dwVolumeControlID == dwControlID )
    {
    DWORD dwVolume = GetCurrentVolume();
    if ( (dwVolume!=BAD_DWORD) && (m_pfUserSink) )
    {
    (*m_pfUserSink)( dwVolume, m_dwUserValue );
    }
    }
    }
    //////////////
    bool CVolumeOutWave::Initialize()
    {
    MMRESULT mmResult;
    if ( !m_bOK )
    return false;
    TRACE(".WaveOutputVolume: Initializing for Source WaveOut Line ..\n" );
    MIXERLINE MixerLine;
    memset( &MixerLine, 0, sizeof(MIXERLINE) );
    MixerLine.cbStruct = sizeof(MIXERLINE);
    MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
    mmResult = mixerGetLineInfo( (HMIXEROBJ)m_dwMixerHandle, &MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE );
    if ( mmResult != MMSYSERR_NOERROR )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not get WaveOut Destionation Line for the WaveOut Source Line while initilaizing. mmResult=%d\n", mmResult );
    return false;
    } MIXERCONTROL Control;
    memset( &Control, 0, sizeof(MIXERCONTROL) );
    Control.cbStruct = sizeof(MIXERCONTROL); MIXERLINECONTROLS LineControls;
    memset( &LineControls, 0, sizeof(MIXERLINECONTROLS) );
    LineControls.cbStruct = sizeof(MIXERLINECONTROLS); LineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
    LineControls.dwLineID = MixerLine.dwLineID;
    LineControls.cControls = 1;
    LineControls.cbmxctrl = sizeof(MIXERCONTROL);
    LineControls.pamxctrl = &Control;
    mmResult = mixerGetLineControls( (HMIXEROBJ)m_dwMixerHandle, &LineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE );
    if ( mmResult == MMSYSERR_NOERROR )
    {
    if ( !(Control.fdwControl & MIXERCONTROL_CONTROLF_DISABLED) )
    {
    m_bAvailable = true;
    TRACE(".WaveOutputVolume: \"%s\" Volume control for the WaveOut Source Line adopted.\n", Control.szShortName );
    } else {
    TRACE(".WaveOutputVolume: WARNING: The Volume Control is disabled.\n" );
    }
    } else {
    TRACE(".WaveOutputVolume: WARNING: Could not get the WaveOut Source line Volume Control while initilaizing. mmResult=%d\n", mmResult );
    }

    m_nChannelCount = MixerLine.cChannels;
    m_dwLineID = LineControls.dwLineID;
    m_dwVolumeControlID = Control.dwControlID;
    m_dwMinimalVolume = Control.Bounds.dwMinimum;
    m_dwMaximalVolume = Control.Bounds.dwMaximum;
    m_dwVolumeStep = Control.Metrics.cSteps; m_bInitialized = true;
    return true;
    }
    //////////////
      

  3.   

    void CVolumeOutWave::EnableLine( bool bEnable )
    {
    if ( !m_bInitialized )
    return;
    bool bAnyEnabled = false;
    MMRESULT mmResult; MIXERLINE lineDestination;
    memset( &lineDestination, 0, sizeof(MIXERLINE) );
    lineDestination.cbStruct = sizeof(MIXERLINE);
    lineDestination.dwLineID = m_dwLineID;
    mmResult = mixerGetLineInfo( (HMIXEROBJ)m_dwMixerHandle, &lineDestination, MIXER_GETLINEINFOF_LINEID );
    if ( mmResult != MMSYSERR_NOERROR )
    {
    if ( bEnable )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not get the WaveOut Destination Line while enabling. mmResult=%d\n", mmResult );
    } else {
    TRACE(".WaveOutputVolume: FAILURE: Could not get the WaveOut Destination Line while disabling. mmResult=%d\n", mmResult );
    }
    return;
    }
    // Getting all line's controls
    int nControlCount = lineDestination.cControls;
    int nChannelCount = lineDestination.cChannels;
    MIXERLINECONTROLS LineControls;
    memset( &LineControls, 0, sizeof(MIXERLINECONTROLS) );
    MIXERCONTROL* aControls = (MIXERCONTROL*)malloc( nControlCount * sizeof(MIXERCONTROL) );
    if ( !aControls )
    {
    if ( bEnable )
    {
    TRACE(".WaveOutputVolume: FAILURE: Out of memory while enabling the line.\n" );
    } else {
    TRACE(".WaveOutputVolume: FAILURE: Out of memory while disabling the line.\n" );
    }
    return;
    }
    memset( &aControls[0], 0, sizeof(nControlCount * sizeof(MIXERCONTROL)) );
    for ( int i = 0; i < nControlCount; i++ )
    {
    aControls[i].cbStruct = sizeof(MIXERCONTROL);
    }
    LineControls.cbStruct = sizeof(MIXERLINECONTROLS);
    LineControls.dwLineID = lineDestination.dwLineID;
    LineControls.cControls = nControlCount;
    LineControls.cbmxctrl = sizeof(MIXERCONTROL);
    LineControls.pamxctrl = &aControls[0];
    mmResult = mixerGetLineControls( (HMIXEROBJ)m_dwMixerHandle, &LineControls, MIXER_GETLINECONTROLSF_ALL );
    if ( mmResult == MMSYSERR_NOERROR )
    {
    for ( i = 0; i < nControlCount; i++ )
    {
    LONG lValue;
    bool bReadyToSet = false;
    switch (aControls[i].dwControlType)
    {
    case MIXERCONTROL_CONTROLTYPE_MUTE:
    lValue = (BOOL)!bEnable;
    bReadyToSet = true;
    break;
    case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
    lValue = (BOOL)bEnable;
    bReadyToSet = true;
    break;
    case MIXERCONTROL_CONTROLTYPE_MUX:
    lValue = (BOOL)bEnable;
    bReadyToSet = true;
    break;
    case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
    lValue = (BOOL)bEnable;
    bReadyToSet = true;
    break;
    case MIXERCONTROL_CONTROLTYPE_MIXER:
    lValue = (BOOL)bEnable;
    bReadyToSet = true;
    break;
    }
    if ( bReadyToSet )
    {
    MIXERCONTROLDETAILS_BOOLEAN* aDetails = NULL;
    int nMultipleItems = aControls[i].cMultipleItems;
    int nChannels = nChannelCount;
    // MIXERCONTROLDETAILS
    MIXERCONTROLDETAILS ControlDetails;
    memset( &ControlDetails, 0, sizeof(MIXERCONTROLDETAILS) );
    ControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
    ControlDetails.dwControlID = aControls[i].dwControlID;
    if ( aControls[i].fdwControl & MIXERCONTROL_CONTROLF_UNIFORM )
    {
    nChannels = 1;
    }
    if ( aControls[i].fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE )
    {
    nMultipleItems = aControls[i].cMultipleItems;
    aDetails = (MIXERCONTROLDETAILS_BOOLEAN*)malloc(nMultipleItems*nChannels*sizeof(MIXERCONTROLDETAILS_BOOLEAN));
    if ( !aDetails )
    {
    TRACE(".WaveOutputVolume: FAILURE: Out of memory while enabling the line.\n" );
    continue;
    }
    for ( int nItem = 0; nItem < nMultipleItems; nItem++ )
    {
    for ( int nChannel = 0; nChannel < nChannels; nChannel++ )
    {
    aDetails[nItem+nChannel].fValue = lValue;
    }
    }
    } else {
    nMultipleItems = 0;
    aDetails = (MIXERCONTROLDETAILS_BOOLEAN*)malloc(nChannels*sizeof(MIXERCONTROLDETAILS_BOOLEAN));
    if ( !aDetails )
    {
    if ( bEnable )
    {
    TRACE(".WaveOutputVolume: FAILURE: Out of memory while enabling the line.\n" );
    } else {
    TRACE(".WaveOutputVolume: FAILURE: Out of memory while disabling the line.\n" );
    }
    continue;
    }
    for ( int nChannel = 0; nChannel < nChannels; nChannel++ )
    {
    aDetails[nChannel].fValue = (LONG)lValue;
    }
    }
    ControlDetails.cChannels = nChannels;
    ControlDetails.cMultipleItems = nMultipleItems;
    ControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
    ControlDetails.paDetails = &aDetails[0];
    mmResult = mixerSetControlDetails( (HMIXEROBJ)m_dwMixerHandle, &ControlDetails, 0L );
    if ( mmResult == MMSYSERR_NOERROR )
    {
    if ( bEnable )
    {
    TRACE(".WaveOutputVolume: Enabling Line: WaveOut Line control \"%s\"(0x%X) has been set to %d.\n", aControls[i].szShortName, aControls[i].dwControlType, lValue );
    } else {
    TRACE(".WaveOutputVolume: Disabling Line: WaveOut Line control \"%s\"(0x%X) has been set to %d.\n", aControls[i].szShortName, aControls[i].dwControlType, lValue );
    }
    bAnyEnabled = true;
    }
    free( aDetails );
    }
    }
    } else {
    if ( bEnable )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not get the line controls while enabling. mmResult=%d\n", mmResult );
    } else {
    TRACE(".WaveOutputVolume: FAILURE: Could not get the line controls while disabling. mmResult=%d\n", mmResult );
    }
    }
    free( aControls );
    if ( !bAnyEnabled )
    {
    if ( bEnable )
    {
    TRACE(".WaveOutputVolume: WARNING: No controls were found for enabling the line.\n" );
    } else {
    TRACE(".WaveOutputVolume: WARNING: No controls were found for disabling the line.\n" );
    }
    }
    }
      

  4.   

    //////////////////////////////////////////////
    // IVolume interface
    //////////////
    bool CVolumeOutWave::IsAvailable()
    {
    return m_bAvailable;
    }
    //////////////
    void CVolumeOutWave::Enable()
    {
    EnableLine( true );
    }
    //////////////
    void CVolumeOutWave::Disable()
    {
    EnableLine( false );
    }
    //////////////
    DWORD CVolumeOutWave::GetVolumeMetric()
    {
    if ( !m_bAvailable )
    return BAD_DWORD;
    return m_dwVolumeStep;
    }
    //////////////
    DWORD CVolumeOutWave::GetMinimalVolume()
    {
    if ( !m_bAvailable )
    return BAD_DWORD;
    return m_dwMinimalVolume;
    }
    //////////////
    DWORD CVolumeOutWave::GetMaximalVolume()
    {
    if ( !m_bAvailable )
    return BAD_DWORD;
    return m_dwMaximalVolume;
    }
    //////////////
    DWORD CVolumeOutWave::GetCurrentVolume()
    {
    if ( !m_bAvailable )
    return BAD_DWORD;
    MIXERCONTROLDETAILS_UNSIGNED* aDetails = (MIXERCONTROLDETAILS_UNSIGNED*)malloc(m_nChannelCount*sizeof(MIXERCONTROLDETAILS_UNSIGNED));
    if ( !aDetails )
    return BAD_DWORD;
    MIXERCONTROLDETAILS ControlDetails;
    memset( &ControlDetails, 0, sizeof(MIXERCONTROLDETAILS) );
    ControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
    ControlDetails.dwControlID = m_dwVolumeControlID;
    ControlDetails.cChannels = m_nChannelCount;
    ControlDetails.cMultipleItems = 0;
    ControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
    ControlDetails.paDetails = &aDetails[0];
    MMRESULT mmResult = mixerGetControlDetails( (HMIXEROBJ)m_dwMixerHandle, &ControlDetails, MIXER_GETCONTROLDETAILSF_VALUE );
    DWORD dw = aDetails[0].dwValue;
    free( aDetails );
    if ( mmResult != MMSYSERR_NOERROR )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not get volume. mmResult=%d\n", mmResult );
    return BAD_DWORD;
    }
    return dw;
    }
    //////////////
    void CVolumeOutWave::SetCurrentVolume( DWORD dwValue )
    {
    if ( !m_bAvailable || (dwValue<m_dwMinimalVolume) || (dwValue>m_dwMaximalVolume) )
    return;
    MIXERCONTROLDETAILS_UNSIGNED* aDetails = (MIXERCONTROLDETAILS_UNSIGNED*)malloc(m_nChannelCount*sizeof(MIXERCONTROLDETAILS_UNSIGNED));
    if ( !aDetails )
    return;
    for ( int i = 0; i < m_nChannelCount; i++ )
    {
    aDetails[i].dwValue = dwValue;
    }
    MIXERCONTROLDETAILS ControlDetails;
    memset( &ControlDetails, 0, sizeof(MIXERCONTROLDETAILS) );
    ControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
    ControlDetails.dwControlID = m_dwVolumeControlID;
    ControlDetails.cChannels = m_nChannelCount;
    ControlDetails.cMultipleItems = 0;
    ControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
    ControlDetails.paDetails = &aDetails[0];
    MMRESULT mmResult = mixerSetControlDetails( (HMIXEROBJ)m_dwMixerHandle, &ControlDetails, MIXER_SETCONTROLDETAILSF_VALUE );
    free( aDetails );
    if ( mmResult != MMSYSERR_NOERROR )
    {
    TRACE(".WaveOutputVolume: FAILURE: Could not set volume(%d) mmResult=%d\n", dwValue, mmResult );
    }
    }
    //////////////
    void CVolumeOutWave::RegisterNotificationSink( PONMICVOULUMECHANGE pfUserSink, DWORD dwUserValue )
    {
    m_pfUserSink = pfUserSink;
    m_dwUserValue = dwUserValue;
    }
    ////////////////////////////////////////////////////////////////////////
    LRESULT CALLBACK CVolumeOutWave::MixerWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    {
    if ( uMsg == MM_MIXM_CONTROL_CHANGE )
    {
    if ( g_pThis )
    {
    g_pThis->OnControlChanged( (DWORD)lParam );
    }
    }
    return ::DefWindowProc( hwnd, uMsg, wParam, lParam);
    }
      

  5.   

    这么长,还有没有发到我信箱吧,[email protected]