www.pudn.com > Win32DirectX9.rar > diutil.cpp


//----------------------------------------------------------------------------- 
// File: DIUtil.cpp 
// 
// Desc: DirectInput framework class using semantic mapping.  Feel free to use  
//       this class as a starting point for adding extra functionality. 
// 
// Copyright (C) 1995-2001 Microsoft Corporation. All Rights Reserved. 
//----------------------------------------------------------------------------- 
#define STRICT 
 
#include  
#include  
#include  
#include "DIUtil.h" 
#include "DXUtil.h" 
 
 
 
  
 
//----------------------------------------------------------------------------- 
// Name: CInputDeviceManager() 
// Desc: Constructor  
//----------------------------------------------------------------------------- 
CInputDeviceManager::CInputDeviceManager() 
{ 
    HRESULT hr = CoInitialize(NULL); 
    m_bCleanupCOM = SUCCEEDED(hr); 
 
    m_dwNumDevices = 0; 
    m_dwMaxDevices = 10; 
    m_pDI          = NULL; 
 
    // Allocate DeviceInfo structs 
    m_pDevices = (DeviceInfo*) malloc( m_dwMaxDevices*sizeof(DeviceInfo) ); 
    if( m_pDevices ) 
        ZeroMemory( m_pDevices, m_dwMaxDevices*sizeof(DeviceInfo) ); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: ~CInputDeviceManager() 
// Desc: Destructor 
//----------------------------------------------------------------------------- 
CInputDeviceManager::~CInputDeviceManager() 
{ 
    if( m_pDevices ) 
    { 
        // Release() all devices 
        for( DWORD i=0; iUnacquire(); 
 
            SAFE_RELEASE( m_pDevices[i].pdidDevice ); 
        } 
 
        free( m_pDevices ); 
    } 
 
    // Release() base object 
    SAFE_RELEASE( m_pDI ); 
 
    if( m_bCleanupCOM ) 
        CoUninitialize(); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: GetDevices() 
// Desc: Get the DeviceInfo array and number of devices 
//----------------------------------------------------------------------------- 
HRESULT CInputDeviceManager::GetDevices( DeviceInfo** ppDeviceInfo,  
                                         DWORD* pdwCount ) 
{ 
    if( NULL==ppDeviceInfo || NULL==pdwCount ) 
        return E_INVALIDARG; 
 
    (*ppDeviceInfo) = m_pDevices; 
    (*pdwCount) = m_dwNumDevices; 
 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: AddDevice() 
// Desc: Add the provided device to the list and perform initialization 
//----------------------------------------------------------------------------- 
HRESULT CInputDeviceManager::AddDevice( const DIDEVICEINSTANCE* pdidi,  
                                        const LPDIRECTINPUTDEVICE8 pdidDevice ) 
{ 
    HRESULT hr; 
 
    // Sanity check 
    if( NULL == pdidDevice ) 
        return E_INVALIDARG; 
 
    pdidDevice->Unacquire(); 
 
    // Set the device's coop level 
    hr = pdidDevice->SetCooperativeLevel( m_hWnd, DISCL_NONEXCLUSIVE|DISCL_FOREGROUND ); 
    if( FAILED(hr) ) 
        return hr; 
 
    // Enlarge the array if needed 
    if( m_dwNumDevices >= m_dwMaxDevices ) 
    { 
        // Attempt to reallocate memory 
        DWORD dwNewMax = m_dwMaxDevices + 10; 
        DeviceInfo* pNewDevices = (DeviceInfo*) realloc( m_pDevices, sizeof(DeviceInfo) * dwNewMax ); 
         
        // Check for out of memory condition 
        if( NULL == pNewDevices ) 
            return E_OUTOFMEMORY; 
 
        // Initialize the new memory block 
        ZeroMemory( pNewDevices + m_dwMaxDevices, sizeof(DeviceInfo) * (dwNewMax - m_dwMaxDevices) ); 
 
        // Copy the new pointer and update the max device count 
        m_pDevices = pNewDevices; 
        m_dwMaxDevices = dwNewMax; 
    } 
 
    // Add new device to the end of the list, but don't finalize addition until 
    // the end of the function. If the remaining initialization calls fail, this 
    // spot will be used by the next valid device. 
    m_pDevices[m_dwNumDevices].pdidDevice = pdidDevice; 
     
    // Callback into the app so it can adjust the device and set 
    // the m_pDevices[dwCurrentDevice].pParam field with a device state struct 
    if( m_AddDeviceCallback ) 
    { 
        hr = m_AddDeviceCallback( &m_pDevices[m_dwNumDevices], pdidi, m_AddDeviceCallbackParam );  
        if( FAILED(hr) )     
            return hr; 
    } 
 
    // Build the action map 
    hr = m_pDevices[m_dwNumDevices].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 ); 
    if( FAILED(hr) ) 
        return hr; 
 
    // Set the action map for the current device 
    hr = m_pDevices[m_dwNumDevices].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 ); 
    if( FAILED(hr) ) 
        return hr; 
 
    // Device addition succeeded. Increment reference and index. 
    m_pDevices[m_dwNumDevices].pdidDevice->AddRef(); 
    m_dwNumDevices++; 
 
    // Continue enumerating suitable devices 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: EnumSuitableDevicesCB() 
// Desc: Callback function for device enumeration. Adds all devices which 
//       met the search criteria 
//----------------------------------------------------------------------------- 
BOOL CALLBACK EnumSuitableDevicesCB( LPCDIDEVICEINSTANCE pdidi,  
                                     LPDIRECTINPUTDEVICE8 pdidDevice,  
                                     DWORD dwFlags, DWORD dwDeviceRemaining, 
                                     VOID* pContext ) 
{ 
    UNREFERENCED_PARAMETER( dwFlags ); 
    UNREFERENCED_PARAMETER( dwDeviceRemaining ); 
     
    // Add the device to the device manager's internal list 
    ((CInputDeviceManager*)pContext)->AddDevice( pdidi, pdidDevice ); 
 
    // Continue enumerating suitable devices 
    return DIENUM_CONTINUE; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: SetActionFormat() 
// Desc: Set the action format to the provided DIACTIONFORMAT structure, and 
//       destroy and recreate device list if flagged 
//----------------------------------------------------------------------------- 
HRESULT CInputDeviceManager::SetActionFormat( DIACTIONFORMAT& diaf, BOOL bReenumerate ) 
{ 
    HRESULT hr = S_OK; 
 
    // Store the new action format 
    m_diaf = diaf; 
 
    // Only destroy and re-enumerate devices if the caller explicitly wants to. The  
    // device list may be used within a loop, and kicking off an enumeration while  
    // the device array is in use would cause problems. 
    if( bReenumerate ) 
    { 
        // Cleanup any previously enumerated devices 
        for( DWORD i=0; iUnacquire(); 
 
            SAFE_RELEASE( m_pDevices[i].pdidDevice ); 
        } 
        m_dwNumDevices = 0; 
 
        // Enumerate suitable DirectInput devices 
        hr = m_pDI->EnumDevicesBySemantics( m_strUserName, &m_diaf,  
                                            EnumSuitableDevicesCB, this, 0L ); 
        if( FAILED(hr) ) 
            return hr; 
    } 
    else // Just apply the new maps. 
    { 
        // Devices must be unacquired to have a new action map set. 
        UnacquireDevices(); 
 
        // Apply the new action map to the current devices. 
        for( DWORD i=0; iBuildActionMap( &m_diaf, m_strUserName, 0 ); 
            if( FAILED(hr) ) 
                return hr; 
 
            hr = m_pDevices[i].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 ); 
            if( FAILED(hr) ) 
                return hr; 
        } 
    } 
 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: Create() 
// Desc: Create DirectInput object and perform initialization 
//----------------------------------------------------------------------------- 
HRESULT CInputDeviceManager::Create( HWND hWnd, TCHAR* strUserName,  
                                     DIACTIONFORMAT& diaf, 
                                     LPDIMANAGERCALLBACK AddDeviceCallback,  
                                     LPVOID pCallbackParam ) 
{ 
    HRESULT hr; 
 
    // Store data 
    m_hWnd        = hWnd; 
    m_strUserName = strUserName; 
    m_AddDeviceCallback = AddDeviceCallback; 
    m_AddDeviceCallbackParam = pCallbackParam; 
     
    // Create the base DirectInput object 
    hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,  
                              IID_IDirectInput8, (VOID**)&m_pDI, NULL ); 
    if( FAILED(hr) ) 
        return hr; 
 
    hr = SetActionFormat( diaf, TRUE ); 
    if( FAILED(hr) ) 
        return hr; 
 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: ConfigureDevices() 
// Desc: Pause input and display the device configuration UI 
//----------------------------------------------------------------------------- 
HRESULT CInputDeviceManager::ConfigureDevices( HWND hWnd, IUnknown* pSurface, 
                                               VOID* ConfigureDevicesCB, 
                                               DWORD dwFlags, LPVOID pvCBParam ) 
{ 
    HRESULT hr; 
 
    // Initialize all the colors here 
    DICOLORSET dics; 
    ZeroMemory(&dics, sizeof(DICOLORSET)); 
    dics.dwSize = sizeof(DICOLORSET); 
 
    // Fill in all the params 
    DICONFIGUREDEVICESPARAMS dicdp; 
    ZeroMemory(&dicdp, sizeof(dicdp)); 
    dicdp.dwSize = sizeof(dicdp); 
    dicdp.dwcFormats     = 1; 
    dicdp.lprgFormats    = &m_diaf; 
    dicdp.hwnd           = hWnd; 
    dicdp.lpUnkDDSTarget = pSurface; 
 
    if( m_strUserName ) 
    { 
        dicdp.dwcUsers       = 1; 
        dicdp.lptszUserNames = m_strUserName; 
    } 
 
    // Unacquire the devices so that mouse doesn't control the game while in control panel 
    UnacquireDevices(); 
 
    hr = m_pDI->ConfigureDevices( (LPDICONFIGUREDEVICESCALLBACK)ConfigureDevicesCB,  
                                  &dicdp, dwFlags, pvCBParam ); 
    if( FAILED(hr) ) 
        return hr; 
 
    if( dwFlags & DICD_EDIT ) 
    { 
        // Re-set up the devices 
        hr = SetActionFormat( m_diaf, TRUE ); 
        if( FAILED(hr) ) 
            return hr; 
    } 
 
    return S_OK; 
} 
 
 
 
//----------------------------------------------------------------------------- 
// Name: UnacquireDevices() 
// Desc: Unacquire all devices in the member list 
//----------------------------------------------------------------------------- 
VOID CInputDeviceManager::UnacquireDevices() 
{ 
    for( DWORD i=0; iUnacquire(); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: SetFocus() 
// Desc: Sets the DirectInput focus to a new HWND 
//----------------------------------------------------------------------------- 
VOID CInputDeviceManager::SetFocus( HWND hWnd )  
{ 
    m_hWnd = hWnd; 
 
    UnacquireDevices(); 
 
    for( DWORD i=0; iSetCooperativeLevel( m_hWnd,  
                                        DISCL_NONEXCLUSIVE|DISCL_FOREGROUND ); 
    } 
}