DirectInput Device Enumeration

DirectInput is able to query the system for all available input devices, determine whether they are connected, and return information about them. This process is called enumeration.

If your application is using only the standard keyboard or mouse, or both, you don't need to enumerate the available input devices. As explained under Creating the DirectInput Device, you can simply use predefined global variables when calling the IDirectInput::CreateDevice method.

For all other input devices, and for systems with multiple keyboards or mice, you need to call IDirectInput::EnumDevices in order to obtain at least the instance GUIDs (globally unique identifiers) so that device objects can be created.

Here's a sample implementation of the IDirectInput::EnumDevices method

GUID              KeyboardGUID = GUID_SysKeyboard; 
// LPDIRECTINPUT  lpdi;   //This has been initialized with
                          //DirectInputCreate and points to
                          //the DirectInput object 
 
lpdi->EnumDevices(DIDEVTYPE_KEYBOARD, 
                  DIEnumDevicesProc, 
                  &KeyboardGUID, 
                  DIEDFL_ATTACHEDONLY); 
 

The first parameter determines what types of devices are to be enumerated. It is NULL if you want to enumerate all devices regardless of type; otherwise it is one of the DIDEVTYPE_* values described in the reference for DIDEVICEINSTANCE.

The second parameter is a pointer to a callback function that will be called once for each device enumerated. This function can be called by any name; the documentation uses the placeholder name DIEnumDevicesProc.

The third parameter to the EnumDevices method is any 32-bit value that you want to pass into the callback function. In the examples above, it's a pointer to a variable of type GUID, passed in so that the callback can assign a keyboard instance GUID.

The fourth parameter is a flag to request enumeration of either all devices or only those that are attached (DIEDFL_ALLDEVICES or DIEDFL_ATTACHEDONLY).

If your application is using more than one input device, the callback function is a good place to initialize each device as it is enumerated. (For an example, see Tutorial 3: Using the Joystick.) The callback function is where you obtain the instance GUID of the device. You can also perform other processing here, such as looking for particular subtypes of devices.

Here is a sample callback function that checks for the presence of an enhanced keyboard and stops the enumeration as soon as it finds one. It assigns the instance GUID of the last keyboard found to the KeyboardGUID variable (passed in as pvRef by the EnumDevices call above), which can then be used in a call to IDirectInput::CreateDevice.

BOOL          hasEnhanced; 
 
BOOL CALLBACK DIEnumKbdProc(LPCDIDEVICEINSTANCE lpddi, 
                            LPVOID pvRef) 
{ 
  *(GUID*) pvRef = lpddi->guidInstance; 
  if (GET_DIDEVICE_SUBTYPE(lpddi->dwDevType) == 
                       DIDEVTYPEKEYBOARD_PCENH) 
  { 
    hasEnhanced = TRUE; 
    return DIENUM_STOP; 
  } 
  return DIENUM_CONTINUE; 
} // end of callback 
 

The first parameter points to a structure containing information about the device. This structure is created for you by DirectInput.

The second parameter points to data passed in from EnumDevices. In this case it is a pointer to the variable KeyboardGUID. This variable was assigned a default value earlier, but it will be given a new value each time a device is enumerated. It is not actually important what instance GUID you use for a single keyboard, but the code does illustrate a technique for retrieving an instance GUID from the callback.

The return value in this case indicates that enumeration is to stop if the sought-for device has been found, or otherwise that it is to continue. Enumeration will automatically stop as soon as all devices have been enumerated.