Creating a DirectInput Object

[Previous] [Next]

Integrating DirectInput support into your applications is reasonably simple. You need to create just two main objects. The first is the LPDIRECTINPUT7 variable, g_pDI in the code below, which is the interface to the DirectInput object. You use this interface to handle all the DirectInput aspects of your game.

The second object is the LPDIRECTINPUTDEVICE2 object, g_pdidDevice2 in the code below, which is a pointer to an IDirectInputDevice2 interface. IDirectInputDevice2 inherits all the methods of IDirectInputDevice and adds methods for polling devices and using force feedback.

In the following code, the variable g_guidJoystick holds the globally unique identifier (GUID) for the joystick. Finally, the g_bUseMouse and g_bUseJoystick variables specify whether the mouse or the joystick is currently being used as the input device. If neither the mouse nor the joystick is available, the keyboard becomes the default input device.

 #include <dinput.h> extern LPDIRECTINPUTDEVICE2 g_Keyboard_pdidDevice2; extern LPDIRECTINPUT7       g_Keyboard_pDI; LPDIRECTINPUT7       g_pDI;            // The DInput object LPDIRECTINPUT7       g_Keyboard_pDI;   // The DInput object LPDIRECTINPUTDEVICE2 g_pdidDevice2;    // The DIDevice2 interface LPDIRECTINPUTDEVICE2 g_Keyboard_pdidDevice2;    // The DIDevice2                                                 // interface GUID                 g_guidJoystick;   // The GUID for the joystick BOOL g_bUseKeyboard = TRUE; BOOL g_bUseMouse    = FALSE; BOOL g_bUseJoystick = FALSE; BOOL bMouseLookOn   = TRUE; BOOL bMouseLookup_is_mouse_forward = TRUE; 

Once the variables are defined, you need to add the code to create the DirectInput7 object. In the WinMain routine, you can create the DirectInput7 object by using the CreateDInput routine. You then create the keyboard input device by using CreateInputDevice because you should always support at least keyboard input for any game you create. You won't need to perform an enumeration process for the keyboard because all computers are required to have one. (Computers won't even boot without a keyboard device in place.)

When the user exits the game, you'll need to call the DestroyInputDevice and DestroyDInput routines to destroy the DirectInput device and the DirectInput interface to make sure that you clean up the objects you generated to support the DirectInput activities.

The calls necessary to add the creation and destruction of these objects during game startup and end (in this case, they are added to the WinMain routine) are shown here:

 //------------------------------------------------------------------- // WinMain // Desc: Application entry point //------------------------------------------------------------------- int PASCAL WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow ) {      //     // Create the DInput object.     //     if( FAILED(d3dApp.CreateDInput( d3dApp.Get_hWnd() ) ) )     {         return FALSE;     }     if( FAILED( hr = CoInitialize( NULL ) ) )         return FALSE;     // Create a keyboard device.     if( FAILED(d3dApp.CreateInputDevice( d3dApp.Get_hWnd(),                                           g_Keyboard_pDI,                                           g_Keyboard_pdidDevice2,                                           GUID_SysKeyboard,                                           &c_dfDIKeyboard,                                          DISCL_NONEXCLUSIVE |                                          DISCL_FOREGROUND )))     {         return FALSE;     }          d3dApp.InitRRvariables();     d3dApp.LoadRR_Resources();     d3dApp.Run();     PrintMessage(NULL, "Quitting", NULL, LOGFILE_ONLY);              d3dApp.DestroyInputDevice();     d3dApp.DestroyDInput();          d3dApp.FreeDirectSound();          CoUninitialize();     return TRUE; } 

You create the actual DirectInput object by calling the DirectInputCreateEx function. This function creates an instance of a DirectInput object that supplies the newest set of DirectInput interfaces. You pass the value DIRECTINPUT_VERSION as defined in dinput.h. This value, when passed in, will request the use of the newest DirectInput version. You must set the third parameter to IID_IDirectInput7 or an error will be returned.

If the call is successful, this function returns a pointer to an IDirectInput7 COM interface. The CreateDInput routine you'll see in a moment acquires all the DirectInput devices available on the target system. In this routine, you acquire a DirectX 7 DirectInput interface by using the DirectInputCreateEx routine.

Here's the function declaration for DirectInputCreateEx:

 HRESULT WINAPI DirectInputCreateEx (     HINSTANCE hInst,     DWORD dwVersion,     REFIID riidltf,     LPVOID * ppvOut,     LPUNKNOWN punkOuter ); 

ParameterDescription
hInstInstance handle of the application or DLL creating the DirectInput object.
dwVersionVersion number, which must be DIRECTINPUT_VERSION, of the dinput.h header file used; determines which version of DirectInput your code was designed for.
riidltfGUID of the desired DirectInput interface. Acceptable values are IID_IDirectInput, IID_IDirectInput2, and IID_IDirectInput7.
ppvOutAddress of a pointer to be initialized with a DirectInput interface pointer.
punkOuterAddress of the controlling object's IUnknown interface. If the interface isn't aggregated, pass NULL for this parameter. Most callers pass NULL for this parameter.

 //------------------------------------------------------------------- // Name: CreateDInput // Desc: Initializes the DirectInput objects //------------------------------------------------------------------- HRESULT CMyD3DApplication::CreateDInput( HWND hWnd ) {     // Create the main DirectInput object.     PrintMessage(NULL, "CD3DApplication::CreateDInput()", NULL,                   LOGFILE_ONLY);          if( FAILED( DirectInputCreateEx( (HINSTANCE)GetWindowLong(                      hWnd, GWL_HINSTANCE ), DIRECTINPUT_VERSION,                      IID_IDirectInput7, (LPVOID*) &g_pDI, NULL) ) )     {         DisplayError( "DirectInputCreate() failed." );             return E_FAIL;     }     // Check to see whether a joystick is present. If one is, the      // enumeration callback will save the joystick's GUID, so we can      // create it later.     ZeroMemory( &g_guidJoystick, sizeof(GUID) );          g_pDI->EnumDevices( DIDEVTYPE_JOYSTICK, EnumJoysticksCallback,                         &g_guidJoystick, DIEDFL_ATTACHEDONLY );     // Keyboard     if( FAILED( DirectInputCreateEx( (HINSTANCE)GetWindowLong( hWnd,                      GWL_HINSTANCE ), DIRECTINPUT_VERSION,                      IID_IDirectInput7, (LPVOID*) &g_Keyboard_pDI,                     NULL) ) )     {         DisplayError( "DirectInputCreate() failed." );         return E_FAIL;     }          return S_OK; } 

After creating the DirectInput object, the CreateDInput routine enumerates the joystick devices on the target system since, other than the keyboard, you can't be sure which devices exist. To do this, the routine calls the IDirectInput7::EnumDevices method with the first parameter set to DIDEVTYPE_JOYSTICK to locate all the joystick devices connected to the machine. (You can set it to DIDEVTYPE_KEYBOARD if you want to locate attached keyboards or to NULL if you want to locate all available input devices.) In DirectInput terminology, a joystick can be any of a wide range of devices, including standard joysticks, steering wheels, game pads, and force-feedback devices.

Here's the function declaration for this method:

 BOOL IDirectInput::EnumDevices(     DWORD dwDevType,     LPDIENUMCALLBACK lpCallback,     LPVOID pvRef,     DWORD dwFlags ); 

ParameterDescription
dwDevTypeDevice type filter. If you set this parameter to 0, the function enumerates all device types. If you want to enumerate a specific device type, pass a device type constant, such as DIDEVTYPE_MOUSE or DIDEVTYPE_KEYBOARD.
lpCallbackAddress of a callback function that will be called with a description of each DirectInput device.
pvRefApplication-defined 32-bit value that is passed to the enumeration callback each time it's called.
dwFlagsIndicates the scope of the enumeration. The values can be any of the following flags:

DIEDFL_ALLDEVICES The default value in which all installed devices will be enumerated

DIEDFL_ATTACHEDONLY Enumerate only attached and installed devices

DIEDFL_FORCEFEEDBACK Enumerate only devices that support force feedback

DIEDFL_INCLUDEALIASES Include devices that are aliases for other devices

DIEDFL_INCLUDEPHANTOMS Include phantom (placeholder) devices

You'll notice that I used the DIEDFL_ATTACHEDONLY value as the last value to the call to indicate that I care about only the devices that are attached to and installed in the system. In most cases, this is what you'll want to do too.

The enumeration routine you pass to the EnumDevices call is the EnumJoysticksCallback routine. This routine is called once for each enumerated joystick. For each of these enumerated devices, you create a device interface so that you can use it in your application.

 //------------------------------------------------------------------- // Name: EnumJoysticksCallback // Desc: Called once for each enumerated joystick. If we find one,  //       create a device interface on it so that we can play with it. //------------------------------------------------------------------- BOOL CALLBACK EnumJoysticksCallback( LPCDIDEVICEINSTANCE pInst,                                       VOID* pvContext ) {     memcpy( pvContext, &pInst->guidInstance, sizeof(GUID) );     return DIENUM_STOP; } 

In addition to the code you added to the WinMain routine, you also need to add code to the WndProc routine to handle acquiring and unacquiring the DirectInput device you want to use for the application. In DirectInput, when you acquire a device, you give the application access to it. While the device is acquired, DirectInput will allow your application to use its data. When a device is not acquired, you can change its characteristics, but you can't acquire its data.

By setting the cooperative level (we'll cover this in a moment), a device can be unacquired automatically when your application moves into the background. As an example, the mouse will be unacquired automatically when the user clicks on a menu because Windows will take over the device at this point. You also need to unacquire a device manually if you want to change its properties (unless you're changing the gain of a force-feedback device while it's in an acquired state). If you didn't unacquire it and something like a hardware interrupt were to be performed, accessing a data buffer just as you were changing the buffer size could completely corrupt the data.

One other issue you should remember is that Windows doesn't have access to the mouse when your application is using it in exclusive mode, so you need to release the mouse if you want Windows to use it.

The additions to the MsgProc routine below handle selecting the input device.

 LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,                                     LPARAM lParam )  {     switch( msg )     {              case WM_COMMAND:             switch( LOWORD(wParam) )             {                 case IDM_SELECTINPUTDEVICE:                     DialogBox( (HINSTANCE)GetWindowLong( hWnd,                         GWL_HINSTANCE ),                         MAKEINTRESOURCE(IDD_SELECTINPUTDEVICE),                         hWnd,(DLGPROC)InputDeviceSelectProc );                     break;                                                   default:                     return CD3DApplication::MsgProc( hWnd, uMsg,                                                   wParam, lParam );             }             break;                  default:             return CD3DApplication::MsgProc( hWnd, uMsg, wParam,                                              lParam );     }     return DefWindowProc( hWnd, msg, wParam, lParam ); } 



Inside Direct3D
Inside Direct3D (Dv-Mps Inside)
ISBN: 0735606137
EAN: 2147483647
Year: 1999
Pages: 131

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net