Tricks of the Windows Game Programming Gurus:Uplinking with DirectInput and Force Feedback

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

Setting the Keyboard’s Cooperative Level

Once you’ve created your device (the keyboard in this case), you must set its cooperation level, just like the main DirectDraw object. But in the case of DirectInput, there isn’t as much of a selection. Table 9.1 lists the various possibilities for the cooperation level.

Table 9.1 Cooperation Flags for DirectInput `SetCooperativeLevel()`

Value | Description
--- | ---

`DISCL_BACKGROUND` | Your application can use a DirectInput device when it’s either in the background or active in the foreground.
`DISCL_FOREGROUND` | The application requires foreground access. If foreground access is granted, the device is automatically unacquired when the associated window moves to the background.
`DISCL_EXCLUSIVE` | Once you acquire the device, no other application can request exclusive access to it. However, other applications can still request non-exclusive access.
`DISCL_NONEXCLUSIVE` | The application requires non-exclusive access. Access to the device will not interfere with other applications that are accessing the same device.

These give me a headache. It’s like, “Background, foreground, exclusive,non-exclusive—you’re killing me!” However, after reading the definitions a few times, it becomes clear how the various flags work. In general, if you set `DISCL_BACKGROUND`, your application will receive input whether it’s active or minimized. Setting `DISCL_FOREGROUND` will only send your application input when it’s on top.

The exclusive/non-exclusive setting controls whether your application has total control of the device and no other application can have access. For example, the mouse and keyboard are implicitly exclusive devices; when your application acquires them, no other application can use them until it gains focus. This creates some paradoxes.

First, you can only acquire the keyboard in non-exclusive mode because Windows itself always has to be able to get the Alt-key combinations. Second, you can acquire the mouse in exclusive mode if you want, but you will lose normal mouse messages to your application (this may be your intent) and the mouse cursor will disappear. Like you care, because you will most probably render one yourself. Finally, most force feedback joysticks (and joysticks in general) should be acquired in exclusive mode. However, you can set normal joysticks for non-exclusive.

Thus, the moral of the story is to set the flags to `DISCL_BACKGROUND | DISCL_NONEXCLUSIVE`. The only time you’ll really need to set exclusive access is for force feedback devices. Of course, with this setting it’s possible that you could lose the device to something that wants exclusive access when it becomes the active application. In that case you will have to reacquire the device, but we’ll get to that in a moment.

For now, just set the cooperation level with `IDIRECTINPUTDEVICE::SetCooperativeLevel(...)`, shown here:

    HRESULT SetCooperativeLevel(HWND hwnd, // the window handle

           DWORD dwFlags); // cooperation flags

And here’s the call to set the cooperation level for your keyboard (all devices are done in the same way):

    if (FAILED(lpdikey->SetCooperativeLevel(main_window_handle,

         DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))

       { /* error */ }

The only way this won’t work is if there is another application that has exclusive/foreground access and is the current application. Then you just have to wait or tell the user to kill the application that is hogging the input device.

Setting the Data Format of the Keyboard

The next step to getting the keyboard ready to send input is to set the data format. This is done with a call to `IDIRECTINPUTDEVICE::SetDataFormat()`, shown here:

    HRESULT SetDataFormat(LPCDIDATAFORMAT lpdf); // ptr to data format

    structure

Bummer... That single parameter is the problem. Here’s the data structure:

    // directinput dataformat

    typedef struct

     {

     DWORD dwSize;    // size of this structure in bytes

     DWORD dwObjSize; // size of DIOBJECTDATAFORMAT in bytes

     DWORD dwFlags;   // flags:either DIDF_ABSAXIS or

                      // DIDF_RELAXIS for absolute or

                      // relative reporting

     DWORD dwDataSize;// size of data packets

     DWORD dwNumObjs; // number of objects that are defined in

                      // the following array of object

     LPDIOBJECTDATAFORMAT rgodf; // ptr to array of objects

      } DIDATAFORMAT, *LPDIDATAFORMAT;

This a really complex structure to set up and is overkill for your purposes. Basically, it allows you to define how the data from the input device will be formatted at the device object level. Luckily, though, DirectInput comes with some custom-made data formats that work for just about everything, and you will use one of them. Take a look at Table 9.2 to see these formats.

Table 9.2 Generic Data Formats Available to DirectInput

Value | Description
--- | ---

`c_dfDIKeyboard` | Generic keyboard
`c_dfDIMouse` | Generic mouse
`c_dfDIJoystick` | Generic joystick
`c_dfDIJoystick2` | Generic force feedback

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.