We help IT Professionals succeed at work.

How do I access a joystick for input?

schworak asked
Medium Priority
Last Modified: 2011-04-14
I am trying to access a joystick (game controller) as input for an application. Any suggestions on how to make it work?
I need Up/Down and Select(fire)
Watch Question

Use your WIN API Text viewer to bring up the declare statements.  There are a series of joy.... API's that you can use to access the Joystick.  Following is some text from an article about using the Joystick in a game environment:

Programming the Joystick
In DirectInput lingo, the term joystick also encompasses game pads, flight yokes, pedal systems, and similar devices. I'll use the term here with a similar range of meaning.
You can read the joystick either through Windows messages or by polling. In the first method, a window "captures" the joystick with joySetCapture so that the window is notified whenever the joystick is moved or a button is pressed. This makes it possible to turn the stick into a pointing device like the mouse: you can move a pointer on the screen every time the angle of the stick is altered. Moby Dick, however, is concerned with the position of the joystick on each pass through the game loop rather than with the stick's actual movements, so you want to use joyGetPosEx to do your own polling rather than monitoring the message queue.
Another reason not to use joySetCapture is that joystick messages are limited to three axes of movement (left-right, forward-back, and throttle, for example) and four buttons. This obviously won't do for a modern input device like the Microsoft Sidewinder 3D Pro, which has eight buttons, a point-of-view hat, and four axes of movement (including a throttle slider and a twisting motion on the stick itself). For the latest joysticks and game pads you definitely need the power of joyGetPosEx, which returns the state of up to 32 buttons, six axes, and the POV hat, besides transparently supporting both digital and analog devices.
The API reference advises using the old joyGetPos function for joystick devices that employ no more than three axes and four buttons. It's true that joyGetPos is a bit simpler to implement, but joyGetPosEx works with all joysticks, and I see no reason not to use it exclusively.
To include the extended joystick services in your program, you need to link to WINMM.LIB and include MMSYSTEM.H.
Detecting the Joystick
To detect the primary joystick, simply call joyGetPosEx with the JOYSTICKID1 argument:
ZeroMemory(joyInfoEx, sizeof(joyInfoEx);
joyInfoEx.dwSize = sizeof(joyInfoEx);
BOOL JoyPresent = (joyGetPosEx(JOYSTICKID1, &joyInfoEx) == JOYERR_NOERROR);
The function returns an error (nonzero) if the joystick is not properly installed in Windows or is simply unplugged.
Note that, as with many of the other DirectX functions, you have to let joyGetPosEx know how big a structure it has to fill—annoying, but necessary for forward compatibility. On the bright side, you don't have to worry about the dwFlags field here, since you don't require any of the values returned in the structure.
Calibrating the Joystick
You don't need to. (Hey, I'm starting to like this Windows stuff!) The user is responsible for selecting and calibrating the joystick under Control Panel. If you want to give the user a chance to do this from the game menu, just call the applet:
WinExec("control joy.cpl", SW_NORMAL);
The "Dead Zone"
In Moby Dick MS-DOS, I did some arithmetic in order to create a "dead zone" around the center of the X and Y axes. Without this zone it would be almost impossible to move the ship along just one axis, as the slightest deviation of the joystick on the other axis would cause the ship to move diagonally.
At first glance it appears that joyGetPosEx is going to simplify life by setting up an automatic dead zone. To quote the API reference, the JOY_USEDEADZONE flag "expands the range for the neutral position of the joystick and calls this range the dead zone. The joystick driver returns a constant value for all positions in the dead zone."
The wording is a bit confusing, and using the dead zone is a bit more complicated than the rather terse documentation suggests. First of all, it's your responsibility to put the dead zone boundaries in the registry (under the keys defined in REGSTR.H) and then notify the system by calling joyConfigChanged. After you've done that, you still have to figure out the constant value returned for the dead zone. (One way to do it is to set the dead zone to the same size as the whole range of the joystick, read the axis positions, and then reset the dead zone to the size you actually want.) And finally, when you close your program you really should restore the original registry values, because other applications may expect the defaults.
All in all, it's simpler for us to maintain your own dead zone. You'll do the arithmetic in Moby Dick Windows just as in the MS-DOS version.
Using the Throttle
Just for fun, and to show you how easy it is to read any of the joystick controls, I've added a throttle to Ahab's ship in Moby Dick Windows. This will work with any device that has a third—or a Z axis—in addition to the X and Y axes on the stick itself. Typically the third axis is controlled by a slider or wheel on the base of the unit.
This is all you have to do to get the throttle information:
JOYCAPS   joyCaps;

ZeroMemory(joyInfoEx, sizeof(joyInfoEx);

// see whether a throttle is available
joyGetDevCaps(JOYSTICKID1, &joyCaps, sizeof(joyCaps));
BOOL JoyHasThrottle = (joyCaps.wCaps & JOYCAPS_HASZ);

// if so, read its position
if (JoyHasThrottle)
  joyInfoEx.dwSize = sizeof(joyInfoEx);
  joyInfoEx.dwFlags = JOY_RETURNZ;
  joyGetPosEx(JOYSTICKID1, &joyInfoEx);
Now joyInfoEx.dwZpos gives you the position of the throttle. You can calculate its relative position from the wZmin and wZmax fields of joyCaps.
You can, of course, combine JOY_RETURNZ with other flags (using the "or" operator) to get information on the stick position, button states, and so on, with a single call.
Besides X, Y, and Z, three other axes can be monitored: R (for Rudder), U, and V. These will accommodate foot pedals, twisting sticks, and various other sliders, knobs, and dials, but not the POV hat, whose position is returned instead in the dwPOV field of the JOYINFOEX structure. (I'm looking forward to implementing the hat in the 3-D version of Moby Dick!)

Your declares would be in VB:

Declare Function joyGetPos Lib "winmm.dll" Alias "joyGetPos" (ByVal uJoyID As Long, pji As JOYINFO) As Long

Declare Function joyGetPosEx Lib "winmm.dll" Alias "joyGetPosEx" (ByVal uJoyID As Long, pji As JOYINFOEX) As Long

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Thanks verry much. I had never used the joystick before and wasn't sure where to start. This will work well for me.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.