Step 6: Retrieving Data from the Keyboard
Once a device is acquired, your application can start retrieving data from it. The simplest way to do this is to call the IDirectInputDevice::GetDeviceState method, which takes a snapshot of the device's state at the time of the call.
The GetDeviceState method accepts two parameters: the size of a buffer to be filled with device state data, and a pointer to that buffer. For keyboards, always declare a buffer of 256 unsigned bytes.
The following sample attempts to retrieve the state of the keyboard. If this fails, it calls an application-defined sample function to deallocate existing DirectInput objects, if any. (See Sample Function 2: DI_Term.)
After retrieving the keyboard's current state, your application may respond to specific keys that were down at the time of the call. Each element in the buffer represents a key. If an element's high bit is on, the key was down at the moment of the call; otherwise, the key was up. To check the state of a given key, use the DirectInput Keyboard Device Constants to index the buffer for a given key.
The following skeleton function, called from the main loop of a hypothetical spaceship game, uses the IDirectInputDevice::GetDeviceState method to poll the keyboard. It then checks to see if the LEFT ARROW, RIGHT ARROW, UP ARROW or DOWN ARROW keys were pressed when the device state was retrieved. This is accomplished with the KEYDOWN macro defined in the body of the function. The macro accepts a buffer's variable name and an index value, then checks the byte at the specified index to see if the high bit is set and returns TRUE if it is.
void WINAPI ProcessKBInput()
{
#define KEYDOWN(name,key) (name[key] & 0x80)
char buffer[256];
HRESULT hr;
hr = g_lpDIDevice->GetDeviceState(sizeof(buffer),(LPVOID)&buffer);
if FAILED(hr)
{
// If it failed, the device has probably been lost.
// We should check for (hr == DIERR_INPUTLOST)
// and attempt to reacquire it here.
return;
}
// Turn the ship right or left
if (KEYDOWN(buffer, DIK_RIGHT));
// Turn right.
else if(KEYDOWN(buffer, DIK_LEFT));
// Turn left.
// Thrust or stop the ship
if (KEYDOWN(buffer, DIK_UP)) ;
// Move the ship forward.
else if (KEYDOWN(buffer, DIK_DOWN));
// Stop the ship.
}