diutil.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:11k
源码类别:

游戏

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // File: DIUtil.cpp
  3. //
  4. // Desc: DirectInput framework class using semantic mapping.  Feel free to use 
  5. //       this class as a starting point for adding extra functionality.
  6. //
  7. // Copyright (C) Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <basetsd.h>
  11. #include <tchar.h>
  12. #include <stdio.h>
  13. #include "DIUtil.h"
  14. #include "DXUtil.h"
  15.  
  16. //-----------------------------------------------------------------------------
  17. // Name: CInputDeviceManager()
  18. // Desc: Constructor 
  19. //-----------------------------------------------------------------------------
  20. CInputDeviceManager::CInputDeviceManager()
  21. {
  22.     HRESULT hr = CoInitialize(NULL);
  23.     m_bCleanupCOM = SUCCEEDED(hr);
  24.     m_dwNumDevices = 0;
  25.     m_dwMaxDevices = 10;
  26.     m_pDI          = NULL;
  27.     // Allocate DeviceInfo structs
  28.     m_pDevices = (DeviceInfo*) malloc( m_dwMaxDevices*sizeof(DeviceInfo) );
  29.     if( m_pDevices )
  30.         ZeroMemory( m_pDevices, m_dwMaxDevices*sizeof(DeviceInfo) );
  31. }
  32. //-----------------------------------------------------------------------------
  33. // Name: ~CInputDeviceManager()
  34. // Desc: Destructor
  35. //-----------------------------------------------------------------------------
  36. CInputDeviceManager::~CInputDeviceManager()
  37. {
  38.     if( m_pDevices )
  39.     {
  40.         // Release() all devices
  41.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  42.         {
  43.             if( m_pDevices[i].pdidDevice )
  44.                 m_pDevices[i].pdidDevice->Unacquire();
  45.             SAFE_RELEASE( m_pDevices[i].pdidDevice );
  46.         }
  47.         free( m_pDevices );
  48.     }
  49.     // Release() base object
  50.     SAFE_RELEASE( m_pDI );
  51.     if( m_bCleanupCOM )
  52.         CoUninitialize();
  53. }
  54. //-----------------------------------------------------------------------------
  55. // Name: GetDevices()
  56. // Desc: Get the DeviceInfo array and number of devices
  57. //-----------------------------------------------------------------------------
  58. HRESULT CInputDeviceManager::GetDevices( DeviceInfo** ppDeviceInfo, 
  59.                                          DWORD* pdwCount )
  60. {
  61.     if( NULL==ppDeviceInfo || NULL==pdwCount )
  62.         return E_INVALIDARG;
  63.     (*ppDeviceInfo) = m_pDevices;
  64.     (*pdwCount) = m_dwNumDevices;
  65.     return S_OK;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Name: AddDevice()
  69. // Desc: Add the provided device to the list and perform initialization
  70. //-----------------------------------------------------------------------------
  71. HRESULT CInputDeviceManager::AddDevice( const DIDEVICEINSTANCE* pdidi, 
  72.                                         const LPDIRECTINPUTDEVICE8 pdidDevice )
  73. {
  74.     HRESULT hr;
  75.     // Sanity check
  76.     if( NULL == pdidDevice )
  77.         return E_INVALIDARG;
  78.     pdidDevice->Unacquire();
  79.     // Set the device's coop level
  80.     hr = pdidDevice->SetCooperativeLevel( m_hWnd, DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  81.     if( FAILED(hr) )
  82.         return hr;
  83.     // Enlarge the array if needed
  84.     if( m_dwNumDevices >= m_dwMaxDevices )
  85.     {
  86.         // Attempt to reallocate memory
  87.         DWORD dwNewMax = m_dwMaxDevices + 10;
  88.         DeviceInfo* pNewDevices = (DeviceInfo*) realloc( m_pDevices, sizeof(DeviceInfo) * dwNewMax );
  89.         
  90.         // Check for out of memory condition
  91.         if( NULL == pNewDevices )
  92.             return E_OUTOFMEMORY;
  93.         // Initialize the new memory block
  94.         ZeroMemory( pNewDevices + m_dwMaxDevices, sizeof(DeviceInfo) * (dwNewMax - m_dwMaxDevices) );
  95.         // Copy the new pointer and update the max device count
  96.         m_pDevices = pNewDevices;
  97.         m_dwMaxDevices = dwNewMax;
  98.     }
  99.     // Add new device to the end of the list, but don't finalize addition until
  100.     // the end of the function. If the remaining initialization calls fail, this
  101.     // spot will be used by the next valid device.
  102.     m_pDevices[m_dwNumDevices].pdidDevice = pdidDevice;
  103.     // Build the action map
  104.     hr = m_pDevices[m_dwNumDevices].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  105.     if( FAILED(hr) )
  106.         return hr;
  107.     // Set the action map for the current device
  108.     hr = m_pDevices[m_dwNumDevices].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  109.     if( FAILED(hr) )
  110.         return hr;
  111.     // Callback into the app so it can adjust the device and set
  112.     // the m_pDevices[dwCurrentDevice].pParam field with a device state struct
  113.     if( m_AddDeviceCallback )
  114.     {
  115.         hr = m_AddDeviceCallback( &m_pDevices[m_dwNumDevices], pdidi, m_AddDeviceCallbackParam ); 
  116.         if( FAILED(hr) )    
  117.             return hr;
  118.     }
  119.     // Device addition succeeded. Increment reference and index.
  120.     m_pDevices[m_dwNumDevices].pdidDevice->AddRef();
  121.     m_dwNumDevices++;
  122.     // Continue enumerating suitable devices
  123.     return S_OK;
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Name: EnumSuitableDevicesCB()
  127. // Desc: Callback function for device enumeration. Adds all devices which
  128. //       met the search criteria
  129. //-----------------------------------------------------------------------------
  130. BOOL CALLBACK EnumSuitableDevicesCB( LPCDIDEVICEINSTANCE pdidi, 
  131.                                      LPDIRECTINPUTDEVICE8 pdidDevice, 
  132.                                      DWORD dwFlags, DWORD dwDeviceRemaining,
  133.                                      VOID* pContext )
  134. {
  135.     UNREFERENCED_PARAMETER( dwFlags );
  136.     UNREFERENCED_PARAMETER( dwDeviceRemaining );
  137.     
  138.     // Add the device to the device manager's internal list
  139.     ((CInputDeviceManager*)pContext)->AddDevice( pdidi, pdidDevice );
  140.     // Continue enumerating suitable devices
  141.     return DIENUM_CONTINUE;
  142. }
  143. //-----------------------------------------------------------------------------
  144. // Name: SetActionFormat()
  145. // Desc: Set the action format to the provided DIACTIONFORMAT structure, and
  146. //       destroy and recreate device list if flagged
  147. //-----------------------------------------------------------------------------
  148. HRESULT CInputDeviceManager::SetActionFormat( DIACTIONFORMAT& diaf, BOOL bReenumerate )
  149. {
  150.     HRESULT hr = S_OK;
  151.     // Store the new action format
  152.     m_diaf = diaf;
  153.     // Only destroy and re-enumerate devices if the caller explicitly wants to. The 
  154.     // device list may be used within a loop, and kicking off an enumeration while 
  155.     // the device array is in use would cause problems.
  156.     if( bReenumerate )
  157.     {
  158.         // Cleanup any previously enumerated devices
  159.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  160.         {
  161.             if( m_pDevices[i].pdidDevice )
  162.                 m_pDevices[i].pdidDevice->Unacquire();
  163.             SAFE_RELEASE( m_pDevices[i].pdidDevice );
  164.         }
  165.         m_dwNumDevices = 0;
  166.         // Enumerate suitable DirectInput devices
  167.         hr = m_pDI->EnumDevicesBySemantics( m_strUserName, &m_diaf, 
  168.                                             EnumSuitableDevicesCB, this, 0L );
  169.         if( FAILED(hr) )
  170.             return hr;
  171.     }
  172.     else // Just apply the new maps.
  173.     {
  174.         // Devices must be unacquired to have a new action map set.
  175.         UnacquireDevices();
  176.         // Apply the new action map to the current devices.
  177.         for( DWORD i=0; i<m_dwNumDevices; i++ )
  178.         {
  179.             hr = m_pDevices[i].pdidDevice->BuildActionMap( &m_diaf, m_strUserName, 0 );
  180.             if( FAILED(hr) )
  181.                 return hr;
  182.             hr = m_pDevices[i].pdidDevice->SetActionMap( &m_diaf, m_strUserName, 0 );
  183.             if( FAILED(hr) )
  184.                 return hr;
  185.         }
  186.     }
  187.     return S_OK;
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Name: Create()
  191. // Desc: Create DirectInput object and perform initialization
  192. //-----------------------------------------------------------------------------
  193. HRESULT CInputDeviceManager::Create( HWND hWnd, TCHAR* strUserName, 
  194.                                      DIACTIONFORMAT& diaf,
  195.                                      LPDIMANAGERCALLBACK AddDeviceCallback, 
  196.                                      LPVOID pCallbackParam )
  197. {
  198.     HRESULT hr;
  199.     // Store data
  200.     m_hWnd        = hWnd;
  201.     m_strUserName = strUserName;
  202.     m_AddDeviceCallback = AddDeviceCallback;
  203.     m_AddDeviceCallbackParam = pCallbackParam;
  204.     
  205.     // Create the base DirectInput object
  206.     hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  207.                               IID_IDirectInput8, (VOID**)&m_pDI, NULL );
  208.     if( FAILED(hr) )
  209.         return hr;
  210.     hr = SetActionFormat( diaf, TRUE );
  211.     if( FAILED(hr) )
  212.         return hr;
  213.     return S_OK;
  214. }
  215. //-----------------------------------------------------------------------------
  216. // Name: ConfigureDevices()
  217. // Desc: Pause input and display the device configuration UI
  218. //-----------------------------------------------------------------------------
  219. HRESULT CInputDeviceManager::ConfigureDevices( HWND hWnd, IUnknown* pSurface,
  220.                                                VOID* ConfigureDevicesCB,
  221.                                                DWORD dwFlags, LPVOID pvCBParam )
  222. {
  223.     HRESULT hr;
  224.     // Initialize all the colors here
  225.     DICOLORSET dics;
  226.     ZeroMemory(&dics, sizeof(DICOLORSET));
  227.     dics.dwSize = sizeof(DICOLORSET);
  228.     // Fill in all the params
  229.     DICONFIGUREDEVICESPARAMS dicdp;
  230.     ZeroMemory(&dicdp, sizeof(dicdp));
  231.     dicdp.dwSize = sizeof(dicdp);
  232.     dicdp.dwcFormats     = 1;
  233.     dicdp.lprgFormats    = &m_diaf;
  234.     dicdp.hwnd           = hWnd;
  235.     dicdp.lpUnkDDSTarget = pSurface;
  236.     if( m_strUserName )
  237.     {
  238.         dicdp.dwcUsers       = 1;
  239.         dicdp.lptszUserNames = m_strUserName;
  240.     }
  241.     // Unacquire the devices so that mouse doesn't control the game while in control panel
  242.     UnacquireDevices();
  243.     hr = m_pDI->ConfigureDevices( (LPDICONFIGUREDEVICESCALLBACK)ConfigureDevicesCB, 
  244.                                   &dicdp, dwFlags, pvCBParam );
  245.     if( FAILED(hr) )
  246.         return hr;
  247.     if( dwFlags & DICD_EDIT )
  248.     {
  249.         // Re-set up the devices
  250.         hr = SetActionFormat( m_diaf, TRUE );
  251.         if( FAILED(hr) )
  252.             return hr;
  253.     }
  254.     return S_OK;
  255. }
  256. //-----------------------------------------------------------------------------
  257. // Name: UnacquireDevices()
  258. // Desc: Unacquire all devices in the member list
  259. //-----------------------------------------------------------------------------
  260. VOID CInputDeviceManager::UnacquireDevices()
  261. {
  262.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  263.         m_pDevices[i].pdidDevice->Unacquire();
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Name: SetFocus()
  267. // Desc: Sets the DirectInput focus to a new HWND
  268. //-----------------------------------------------------------------------------
  269. VOID CInputDeviceManager::SetFocus( HWND hWnd ) 
  270. {
  271.     m_hWnd = hWnd;
  272.     UnacquireDevices();
  273.     for( DWORD i=0; i<m_dwNumDevices; i++ )
  274.     {
  275.         // Set the device's coop level
  276.         m_pDevices[i].pdidDevice->SetCooperativeLevel( m_hWnd, 
  277.                                         DISCL_NONEXCLUSIVE|DISCL_FOREGROUND );
  278.     }
  279. }