Direct Input 7 Joystick Class

Environment: Win9x, Windows NT/2000, DirectX Installed

Introduction

DirectX isn’t the most friendly of API’s available, so here’s a simple class
that you can use to utilise DirectX7 for multiple Joystick Control.

Unfortunately it doesn’t include ForceFeedback support as I don’t have a
compatible device, however if you want to add that support, the code is well
commented.

To use the class, define a global variable

CDIJoystick myJoystick1;

The class will automatically enumerate all attached joysticks on the target
PC upon creation.
If there are more than one attached device, you could give the games player a
choice of device to use.
Alternatively, you can use multiple instances of this class so that two player
games can use different joysticks for instance!

The class has the following public methods.

  • void CDIJoystick.SetHWND(HWND hwnd)
    

    Set the windows handle to which Direct
    Input Will be attached to.  Must be the Parent Window.

  •  

  • LPCDIDEVICEINSTANCE CDIJoystick.GetFirstJoystickID(void)
    

    Get the first Device Instance of Enumerated
    Devices.  Returns NULL if none attached.
    Must be called before proceeding Method.

  •  

  • LPCDIDEVICEINSTANCE CDIJoystick.GetNextJoystickID(void)
    

    Get the Next Device Instance of Enumerated
    Devices.  Returns NULL if no more attached.

  •  

  • void CDIJoystick.SetPreferredDevice(&myguid);
    

    Sets the current Joystick Device Based on it GUID

  •  

  • int CDIJoystick.HowManyButtons(void);
    

    Returns the number of buttons attached to
    the prefferred device.  0 = None or a problem with the
    device.  I.e. unplugged or removed from system.

  •  

  • TCHAR* CDIJoystick.GetFirstButtonName(void)
    

    Returns the friendly button name for the
    attached device.
    Must be called before proceeding Method.

  •  

  • TCHAR* CDIJoystick.GetNextButtonName(void)
    

    Returns the next friendly button name for the attached device.

  •  

  • bool CDIJoystick.PollDevice(void)
    

    Must be called to update joystick state
    information.  Returns true if data obtained.  false if there
    is a problem polling the device.

  •  

  • bool CDIJoystick.IsJoystickLeft(void)
    

    true if the joystick is being pushed left, false if not

  •  

  • bool CDIJoystick.IsJoystickRight(void)
    true if the joystick is being pushed right, false if not
    
  •  

  • bool CDIJoystick.IsJoystickUp(void)
    

    true if the joystick is being pushed up, false if not

  •  

  • bool CDIJoystick.IsJoystickDown(void)
    

    true if the joystick is being pushed down, false if not

  •  

  • bool CDIJoystick.IsJoystickFire(void)
    

    true if any of the joystick buttons are pressed, false if not

  •  

  • int CDIJoystick.IsJoystickFire(int button)
    

    returns true if button has been pressed,
    false otherwise.  Button = 0 to Number of Buttons Available -1

  •  

  • LPDIJOYSTATE2 CDIJoystick.GetJoystickStateInfo(void);
    

    Returns a LPDIJOYSTATE2 pointer, This
    enables you to probe more of the functionality of the joystick if more
    advance features are required.

  •  

  • void CDIJoystick.RunControlPanel(void)
    

Start the windows control panel.

Before using or obtaining information about the device you must supply a HWND
to the Parent window from which you will receive input.

If you are using MFC you can either set the HWND from the Application from
using:

myJoystick1.SetHWND(m_pMainWnd->m_hWnd);

if you’re inside a Dialog Based Application:

CWnd *jb=this;
myJoystick1.SetHWND(jb->m_hWnd);

if your not using MFC you will have to Initiailise COM and set HWND according
to your global window

HRESULT hr=CoInitialize(NULL);
myJoystick1.SetHWND(g_hwnd);
// Remember to CoUninitialize when exiting your application!

For the purpose of demonstration, the following code snippet shows how to
populate a list control with the names of each attached device to your system.

CWnd *jb=this;
myJoystick1.SetHWND(jb->m_hWnd);

// Reset Combo Control
m_ctlJoystickName.ResetContent();

LPCDIDEVICEINSTANCE lpddi=NULL;

// Ensure you have First Joystick ID to start 
// search for additional Devices!
lpddi=myJoystick1.GetFirstJoystickID();

if(!lpddi)
{
 // No joysticks have been found!
 MessageBox("I have not been able to find a joystick on
            "your system.","No Joystick Detected",
            MB_ICONHAND|MB_OK);
 OnCancel();
}
else
{

 while(lpddi)
 {
  int x=m_ctlJoystickName.AddString(lpddi->tszInstanceName);
  m_ctlJoystickName.SetItemDataPtr(x,(void*)lpddi);
  lpddi=myJoystick1.GetNextJoystickID();
 }

 m_ctlJoystickName.SetCurSel(0);
 OnSelchangeButtonNames();

 SetTimer(1,50,NULL);

 // return TRUE unless you set the focus to a control
 return TRUE;
}
return TRUE;

Now that the list control has been populated, You may wish to
find out how many fire buttons are attached to the device.  Using a snippet
from the demo project we have:

CWnd*jb=this;
myJoystick1.SetHWND(jb->m_hWnd);

LPCDIDEVICEINSTANCE lpddi=NULL;

m_ctlButtonNames.ResetContent();

int x=m_ctlJoystickName.GetCurSel();

lpddi=(LPCDIDEVICEINSTANCE)m_ctlJoystickName.GetItemDataPtr(x);

GUID myguid;

if(lpddi && ((int)lpddi!=-1))
{
 memcpy(&myguid,&(lpddi->guidInstance),sizeof(GUID));

 myJoystick1.SetPreferredDevice(&myguid);

 m_Buttons=myJoystick1.HowManyButtons();

 TCHAR* name=NULL;
 name=myJoystick1.GetFirstButtonName();

 while(name)
 {
  m_ctlButtonNames.AddString(name);
  name=myJoystick1.GetNextButtonName();
 }
}

m_ctlButtonNames.SetCurSel(0);

Now that a Joystick Device has been selected, all that remains
is to read the device.
You must allways all the PollDevice Method to obtain the latest joystick
data.  
If you are only interested in Up, Down, Left, Right and Fire movements the
following code snippet will work:

myJoystick1.PollDevice();

if(myJoystick1.IsJoystickLeft()) m_Left=true;
else m_Left=false;

if(myJoystick1.IsJoystickRight()) m_Right=true;
else m_Right=false;

if(myJoystick1.IsJoystickUp()) m_Up=true;
else m_Up=false;

if(myJoystick1.IsJoystickDown()) m_Down=true;
else m_Down=false;

if(myJoystick1.IsJoystickFire()) m_Fire=true;
else m_Fire=false;

If on the other hand your interested in precision data, i.e. your
device is analogue you can use:

myJoystick1.PollDevice();
LPDIJOYSTATE2 joy=myJoystick1.GetJoystickStateInfo();

m_XAxis.Format("%d",joy->lX);
m_YAxis.Format("%d",joy->lY);
m_ZAxis.Format("%d",joy->lZ);

m_RXAxis.Format("%d",joy->lRx);
m_RYAxis.Format("%d",joy->lRy);
m_RZAxis.Format("%d",joy->lRz);


m_FireText.Empty();

for(int i=0;i<m_Buttons;i++)
{
 if(myJoystick1.IsJoystickFire(i))
 {
  CString temp;
  temp.Format("Fire Button : %d\r\n",i);
  m_FireText+=temp;
 }
}

Downloads

Download demo project – 33 Kb

Download source – 10 Kb

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read