home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Game Programming for Teens / VBGPFT.cdr / DirectX8 / dx8a_sdk.exe / samples / multimedia / directinput / readffe / readffe.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-04  |  13.0 KB  |  400 lines

  1. //-----------------------------------------------------------------------------
  2. // File: ReadFFE.cpp
  3. //
  4. // Desc: DirectInput support to enumerate and play all effects in stored in a 
  5. //       DirectInput effects file.
  6. //
  7. // Copyright (c) 1998-2000 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <tchar.h>
  11. #include <windows.h>
  12. #include <basetsd.h>
  13. #include <commdlg.h>
  14. #include <dinput.h>
  15. #include "DXUtil.h"
  16. #include "resource.h"
  17.  
  18.  
  19.  
  20.  
  21. //-----------------------------------------------------------------------------
  22. // Defines, constants, and global variables
  23. //-----------------------------------------------------------------------------
  24. struct EFFECTS_NODE
  25. {
  26.     LPDIRECTINPUTEFFECT pDIEffect;
  27.     DWORD               dwPlayRepeatCount;
  28.     EFFECTS_NODE*       pNext;
  29. };
  30.  
  31. LPDIRECTINPUT8        g_pDI       = NULL;         
  32. LPDIRECTINPUTDEVICE8  g_pFFDevice = NULL;
  33. EFFECTS_NODE          g_EffectsList;
  34.  
  35.  
  36.  
  37.  
  38. //-----------------------------------------------------------------------------
  39. // Function-prototypes
  40. //-----------------------------------------------------------------------------
  41. INT_PTR CALLBACK MainDialogProc( HWND, UINT, WPARAM, LPARAM );
  42. BOOL CALLBACK EnumFFDevicesCallback( LPCDIDEVICEINSTANCE pDDI, VOID* pvRef );
  43. BOOL CALLBACK EnumAndCreateEffectsCallback( LPCDIFILEEFFECT pDIFileEffect, VOID* pvRef );
  44.  
  45. HRESULT InitDirectInput( HWND hDlg );
  46. HRESULT FreeDirectInput();
  47. VOID    EmptyEffectList();
  48. HRESULT OnReadFile( HWND hDlg );
  49. HRESULT OnPlayEffects( HWND hDlg );
  50.  
  51.  
  52.  
  53.  
  54. //-----------------------------------------------------------------------------
  55. // Name: WinMain()
  56. // Desc: Entry point for the application.
  57. //-----------------------------------------------------------------------------
  58. int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
  59. {
  60.     // Display the main dialog box.
  61.     DialogBox( hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDialogProc );
  62.  
  63.     return TRUE;
  64. }
  65.  
  66.  
  67.  
  68.  
  69. //-----------------------------------------------------------------------------
  70. // Name: MainDialogProc
  71. // Desc: Handles dialog messages
  72. //-----------------------------------------------------------------------------
  73. INT_PTR CALLBACK MainDialogProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  74. {
  75.     HRESULT hr;
  76.  
  77.     switch( msg ) 
  78.     {
  79.         case WM_INITDIALOG:
  80.         {
  81.             // Set the icon for this dialog.
  82.             HICON hIcon = LoadIcon( (HINSTANCE)GetModuleHandle(NULL), 
  83.                                     MAKEINTRESOURCE( IDI_ICON ) );
  84.             PostMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM)hIcon );  // Set big icon
  85.             PostMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon );  // Set small icon
  86.  
  87.             EnableWindow( GetDlgItem( hDlg, IDC_PLAY_EFFECTS ), FALSE );
  88.  
  89.             hr = InitDirectInput( hDlg );
  90.             if( FAILED(hr) )
  91.             {
  92.                 MessageBox( NULL, _T("Error Initializing DirectInput. ")
  93.                                   _T("The sample will now exit."),
  94.                                   _T("ReadFFE"), MB_ICONERROR | MB_OK );                
  95.                 EndDialog( hDlg, TRUE );
  96.             }
  97.             return TRUE;
  98.         }
  99.  
  100.         case WM_COMMAND:
  101.             switch( LOWORD(wParam) )
  102.             {
  103.                 case IDCANCEL:
  104.                     EndDialog( hDlg, FALSE ); 
  105.                     return TRUE;
  106.  
  107.                 case IDC_READ_FILE:
  108.                     if( FAILED( hr = OnReadFile( hDlg ) ) )
  109.                     {
  110.                         MessageBox( NULL, _T("Error reading effects file."),
  111.                                           _T("ReadFFE"), MB_ICONERROR | MB_OK );
  112.                         EnableWindow( GetDlgItem( hDlg, IDC_PLAY_EFFECTS ), FALSE );
  113.                     }
  114.                     return TRUE;
  115.  
  116.                 case IDC_PLAY_EFFECTS:
  117.                     if( FAILED( hr = OnPlayEffects( hDlg ) ) )
  118.                     {
  119.                         MessageBox( NULL, _T("Error playing DirectInput effects. ")
  120.                                           _T("The sample will now exit."), 
  121.                                           _T("ReadFFE"), MB_ICONERROR | MB_OK );
  122.                         EndDialog( hDlg, 1 );
  123.                     }
  124.                     return TRUE;
  125.             }
  126.             break;
  127.  
  128.         case WM_DESTROY:
  129.             FreeDirectInput();   
  130.             return TRUE;
  131.     }
  132.  
  133.     return FALSE;
  134. }
  135.  
  136.  
  137.  
  138.  
  139. //-----------------------------------------------------------------------------
  140. // Name: InitDirectInput()
  141. // Desc: Initialize the DirectInput variables.
  142. //-----------------------------------------------------------------------------
  143. HRESULT InitDirectInput( HWND hDlg )
  144. {
  145.     HRESULT hr;
  146.  
  147.     // Setup the g_EffectsList circular linked list
  148.     ZeroMemory( &g_EffectsList, sizeof( EFFECTS_NODE ) );
  149.     g_EffectsList.pNext = &g_EffectsList;
  150.  
  151.     // Create a DInput object
  152.     if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, 
  153.                                          IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) )
  154.         return hr;
  155.  
  156.     // Get the first enumerated force feedback device
  157.     if( FAILED( hr = g_pDI->EnumDevices( 0, EnumFFDevicesCallback, 0, 
  158.                                          DIEDFL_ATTACHEDONLY | 
  159.                                          DIEDFL_FORCEFEEDBACK ) ) )
  160.         return hr;
  161.     
  162.     if( g_pFFDevice == NULL )
  163.     {
  164.         MessageBox( hDlg, _T("No force feedback device found.  ")
  165.                           _T("The sample will now exit."), 
  166.                           _T("ReadFFE"), MB_ICONERROR | MB_OK );
  167.         EndDialog( hDlg, 0 );
  168.         return S_OK;
  169.     }
  170.  
  171.     // Set the data format
  172.     if( FAILED( hr = g_pFFDevice->SetDataFormat( &c_dfDIJoystick ) ) )
  173.         return hr;
  174.  
  175.     // Set the coop level
  176.     if( FAILED( hr = g_pFFDevice->SetCooperativeLevel( hDlg, DISCL_EXCLUSIVE | 
  177.                                                              DISCL_BACKGROUND ) ) )
  178.         return hr;
  179.  
  180.     // Disable auto-centering spring
  181.     DIPROPDWORD dipdw;
  182.     dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
  183.     dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  184.     dipdw.diph.dwObj        = 0;
  185.     dipdw.diph.dwHow        = DIPH_DEVICE;
  186.     dipdw.dwData            = FALSE;
  187.  
  188.     if( FAILED( hr = g_pFFDevice->SetProperty( DIPROP_AUTOCENTER, &dipdw.diph ) ) )
  189.         return hr;
  190.  
  191.     // Acquire the device
  192.     if( FAILED( hr = g_pFFDevice->Acquire() ) )
  193.         return hr;
  194.  
  195.     return S_OK;
  196. }
  197.  
  198.  
  199.  
  200.  
  201. //-----------------------------------------------------------------------------
  202. // Name: EnumFFDevicesCallback()
  203. // Desc: Get the first enumerated force feedback device
  204. //-----------------------------------------------------------------------------
  205. BOOL CALLBACK EnumFFDevicesCallback( LPCDIDEVICEINSTANCE pDDI, VOID* pvRef )
  206. {
  207.     if( FAILED( g_pDI->CreateDevice( pDDI->guidInstance, &g_pFFDevice, NULL ) ) )
  208.         return DIENUM_CONTINUE; // If failed, try again
  209.  
  210.     // Stop when a device was successfully found
  211.     return DIENUM_STOP;
  212. }
  213.  
  214.  
  215.  
  216.  
  217. //-----------------------------------------------------------------------------
  218. // Name: FreeDirectInput()
  219. // Desc: Initialize the DirectInput variables.
  220. //-----------------------------------------------------------------------------
  221. HRESULT FreeDirectInput()
  222. {
  223.     // Release any DirectInputEffect objects.
  224.     if( g_pFFDevice ) 
  225.     {
  226.         EmptyEffectList();
  227.         g_pFFDevice->Unacquire();
  228.         SAFE_RELEASE( g_pFFDevice );
  229.     }
  230.  
  231.     // Release any DirectInput objects.
  232.     SAFE_RELEASE( g_pDI );
  233.  
  234.     return S_OK;
  235. }
  236.  
  237.  
  238.  
  239.  
  240. //-----------------------------------------------------------------------------
  241. // Name: EmptyEffectList()
  242. // Desc: Goes through the circular linked list and releases the effects, 
  243. //       and deletes the nodes
  244. //-----------------------------------------------------------------------------
  245. VOID EmptyEffectList()
  246. {
  247.     EFFECTS_NODE* pEffectNode = g_EffectsList.pNext;
  248.     EFFECTS_NODE* pEffectDelete;
  249.  
  250.     while ( pEffectNode != &g_EffectsList )
  251.     {
  252.         pEffectDelete = pEffectNode;       
  253.         pEffectNode = pEffectNode->pNext;
  254.  
  255.         SAFE_RELEASE( pEffectDelete->pDIEffect );
  256.         SAFE_DELETE( pEffectDelete );
  257.     }
  258.  
  259.     g_EffectsList.pNext = &g_EffectsList;
  260. }
  261.  
  262.  
  263.  
  264.  
  265. //-----------------------------------------------------------------------------
  266. // Name: OnReadFile()
  267. // Desc: Reads a file contain a collection of DirectInput force feedback 
  268. //       effects.  It creates each of effect read in and stores it 
  269. //       in the linked list, g_EffectsList.
  270. //-----------------------------------------------------------------------------
  271. HRESULT OnReadFile( HWND hDlg )
  272. {
  273.     HRESULT hr;
  274.  
  275.     static TCHAR strFileName[MAX_PATH] = TEXT("");
  276.     static TCHAR strPath[MAX_PATH] = TEXT("");
  277.  
  278.     // Setup the OPENFILENAME structure
  279.     OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL,
  280.                          TEXT("FEdit Files\0*.ffe\0All Files\0*.*\0\0"), NULL,
  281.                          0, 1, strFileName, MAX_PATH, NULL, 0, strPath,
  282.                          TEXT("Open FEdit File"),
  283.                          OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0,
  284.                          TEXT(".ffe"), 0, NULL, NULL };
  285.  
  286.     // Get the default media path (something like C:\MSSDK\SAMPLES\MULTIMEDIA\DINPUT\MEDIA)
  287.     if( '\0' == strPath[0] )
  288.         _tcscpy( strPath, DXUtil_GetDXSDKMediaPath() );
  289.  
  290.     // Display the OpenFileName dialog. Then, try to load the specified file
  291.     if( FALSE == GetOpenFileName( &ofn ) )
  292.         return S_OK;
  293.  
  294.     EmptyEffectList();
  295.  
  296.     // Enumerate the effects in the file selected, and create them in the callback
  297.     if( FAILED( hr = g_pFFDevice->EnumEffectsInFile( strFileName, 
  298.                                                      EnumAndCreateEffectsCallback, 
  299.                                                      NULL, 0 ) ) )
  300.         return hr;
  301.  
  302.     // Remember the path for next time
  303.     strcpy( strPath, strFileName );
  304.     char* strLastSlash = strrchr( strPath, '\\' );
  305.     strLastSlash[0] = '\0';
  306.  
  307.     // If list of effects is empty, then we haven't been able to create any effects
  308.     if( g_EffectsList.pNext == &g_EffectsList )
  309.     {
  310.         // Pop up a box informing the user
  311.         MessageBox( hDlg, _T("Unable to create any effects."),
  312.                           _T("ReadFFE"), MB_ICONEXCLAMATION | MB_OK );
  313.         EnableWindow( GetDlgItem( hDlg, IDC_PLAY_EFFECTS ), FALSE );
  314.     }
  315.     else
  316.     {
  317.         // We have effects so enable the 'play effects' button
  318.         EnableWindow( GetDlgItem( hDlg, IDC_PLAY_EFFECTS ), TRUE );
  319.     }
  320.  
  321.     return S_OK;
  322. }
  323.  
  324.  
  325.  
  326.  
  327. //-----------------------------------------------------------------------------
  328. // Name: EnumAndCreateEffectsCallback()
  329. // Desc: Create the effects as they are enumerated and add them to the 
  330. //       linked list, g_EffectsList
  331. //-----------------------------------------------------------------------------
  332. BOOL CALLBACK EnumAndCreateEffectsCallback( LPCDIFILEEFFECT pDIFileEffect, VOID* pvRef )
  333. {   
  334.     HRESULT hr;
  335.     LPDIRECTINPUTEFFECT pDIEffect = NULL;
  336.  
  337.     // Create the file effect
  338.     if( FAILED( hr = g_pFFDevice->CreateEffect( pDIFileEffect->GuidEffect, 
  339.                                                 pDIFileEffect->lpDiEffect, 
  340.                                                 &pDIEffect, NULL ) ) )
  341.     {
  342.         OutputDebugString( "Could not create force feedback effect on this device.\n" );
  343.         return DIENUM_CONTINUE;
  344.     }
  345.  
  346.     // Create a new effect node
  347.     EFFECTS_NODE* pEffectNode = new EFFECTS_NODE;
  348.     if( NULL == pEffectNode )
  349.         return DIENUM_STOP;
  350.  
  351.     // Fill the pEffectNode up
  352.     ZeroMemory( pEffectNode, sizeof( EFFECTS_NODE ) );
  353.     pEffectNode->pDIEffect         = pDIEffect;
  354.     pEffectNode->dwPlayRepeatCount = 1;
  355.  
  356.     // Add pEffectNode to the circular linked list, g_EffectsList
  357.     pEffectNode->pNext  = g_EffectsList.pNext;
  358.     g_EffectsList.pNext = pEffectNode;
  359.  
  360.     return DIENUM_CONTINUE;
  361. }
  362.  
  363.  
  364.  
  365.  
  366. //-----------------------------------------------------------------------------
  367. // Name: OnPlayEffects()
  368. // Desc: Plays all of the effects enumerated in the file 
  369. //-----------------------------------------------------------------------------
  370. HRESULT OnPlayEffects( HWND hDlg )
  371. {
  372.     EFFECTS_NODE*       pEffectNode = g_EffectsList.pNext;
  373.     LPDIRECTINPUTEFFECT pDIEffect   = NULL;
  374.     HRESULT             hr;
  375.  
  376.     // Stop all previous forces
  377.     if( FAILED( hr = g_pFFDevice->SendForceFeedbackCommand( DISFFC_STOPALL ) ) )
  378.         return hr;
  379.  
  380.     while ( pEffectNode != &g_EffectsList )
  381.     {
  382.         // Play all of the effects enumerated in the file 
  383.         pDIEffect = pEffectNode->pDIEffect;
  384.  
  385.         if( NULL != pDIEffect )
  386.         {
  387.             if( FAILED( hr = pDIEffect->Start( pEffectNode->dwPlayRepeatCount, 0 ) ) )
  388.                 return hr;
  389.         }
  390.  
  391.         pEffectNode = pEffectNode->pNext;
  392.     }
  393.  
  394.     return S_OK;
  395. }
  396.  
  397.  
  398.  
  399.  
  400.