Step 4: Setting the Joystick Behavior

The joystick device has been created, and its data format has been set. The next step is to set its cooperative level. As in the previous step, g_pJoystick is a pointer to the device interface.

if (FAILED(hr = g_pJoystick->SetCooperativeLevel(hDlg, 
                    DISCL_EXCLUSIVE | DISCL_FOREGROUND)))
    return hr;

The first parameter to IDirectInputDevice8::SetCooperativeLevel is a window handle. In this case, the handle to the dialog box serving as the main program window is passed to the function.

The final parameter is a combination of flags describing the desired cooperative level. The Joystick sample requires input from the joystick only when it is the foreground application. Also, when the joystick sample is in the foreground, it should be the only application with exclusive access to the joystick. Therefore, the flags are set to DISCL_EXCLUSIVE | DISCL_FOREGROUND. See Cooperative Levels for a full explanation of these flags.

The next step is to gather information about the capabilities of the joystick. This information includes the number of axes, buttons, and other controllers, whether the device supports force feedback, and other details about the joystick's behavior and supported options.

A DIDEVCAPS structure is used to hold the capability information. The dwSize member of the DIDEVCAPS structure must first be initialized, then the address of the structure sent to IDirectInputDevice8::GetCapabilities. In the example below, g_diDevCaps is a previously declared DIDEVCAPS structure.

g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
if (FAILED(hr = g_pJoystick->GetCapabilities(&g_diDevCaps)))
    return hr;

At this point, you could proceed using the device defaults or you could customize the device properties. The Joystick sample enumerate the axes on the joystick and sets a range for each by calling IDirectInputDevice8::EnumObjects.

if (FAILED(hr = g_pJoystick->EnumObjects(EnumAxesCallback, 
                                       (VOID*)hDlg, DIDFT_AXIS)))
    return hr;

The first parameter to the IDirectInputDevice8::EnumObjects method, EnumAxesCallback, is the address of a callback function which processes the enumerated objects as desired.

The second parameter can be any 32-bit value that you might want to provide to the callback function. Here, the handle to the main dialog window is passed so that it can update the display to indicate which axes are found on the joystick.

The last parameter, DIDFT_AXIS, tells the callback function to enumerate only device axes.

In the sample, the properties changed will be the range for any axis or slider detected (a slider is considered an axis ).

By setting the range, you are telling DirectInput what maximum and minimum values you want returned for an axis. If you set a range of -1,000 to +1,000 for the x-axis, as in the example, you are asking that a value of -1,000 be returned when the stick is at the extreme left, +1,000 when it is at the extreme right, and zero when it is in the middle.

The following sample code sets the range of an enumerated axis. The pdidoi variable is the address of a DIDEVICEOBJECTINSTANCE structure passed by the system to the callback function. This variable contains information about the object currently being enumerated.

DIPROPRANGE diprg; 

diprg.diph.dwSize       = sizeof(DIPROPRANGE); 
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
diprg.diph.dwHow        = DIPH_BYID; 
diprg.diph.dwObj        = pdidoi->dwType; 
diprg.lMin              = -1000; 
diprg.lMax              = +1000; 
.
.
hr = g_pJoystick->SetProperty(DIPROP_RANGE, &diprg.diph);
if (FAILED(hr))
    return DIENUM_STOP;

The first task here is to set up the DIPROPRANGE structure diprg, whose address is passed into the IDirectInputDevice8::SetProperty method. Note that it is not the address of the structure itself that is passed but rather the address of its first member, which is a DIPROPHEADER structure. For more information, see Device Properties.

The property header is initialized with the following values.

The lmin and lmax members of the DIPROPRANGE structure are assigned the desired range values.

The application now calls the IDirectInputDevice8::SetProperty method. The first parameter is a flag indicating which property is being changed. The second parameter is the address of the DIPROPHEADER member of the property structure.

After setting the joystick behavior, go to Step 5: Gaining Access to the Joystick.