Click here to Skip to main content
15,867,834 members
Articles / Game Development

Joystick Driver Project

Rate me:
Please Sign up or sign in to vote.
4.48/5 (14 votes)
10 Feb 2013CPOL5 min read 76.5K   4.1K   21   19
Need to control something with a Joystick in Windows? Here is an easy to use driver that will help you do it.

Introduction

When I wanted to create a Joystick driver so I could control my robot via a joystick plugged into my computer, one of the first things I did was look for a simple joystick driver that could set up everything for me and give me the readings I wanted without me having to code anything myself or even understand how it works. Unfortunately, despite all the people using joysticks in their programs and projects before me, it seems I couldn’t find anyone had created anything like what I was looking for and shared it online.

So if no one else had done it, I decided I would do it myself. Thus, I began this project to create a portable and reusable universal joystick driver that anyone could use to easily implement joystick control in their programs. This driver uses the Joystick sample program from the DirectX SDK, as its foundation.

If you know what you’re doing, it isn’t that hard to write a simple program to get some readings from a joystick. But if you don’t know what you’re doing, learning all about direct input in order to create your own joystick driver isn’t easy. Given I didn’t and still don’t know what the hell I’m doing, I decided to adapt the sample code from the SDK rather than writing a driver from scratch. This probably ended up being more difficult for me in the long run, however the sample code from the SDK is very comprehensive and robust program that will acquire and accept any joystick device you plug in, giving me what I believe is a better result than I could have produced otherwise.

My driver is meant to handle Joystick stuff only so all the GUI related code from the sample program has been removed making it all considerably smaller and simpler.

This driver packages all your joystick needs into a Joystick class which gets all your joystick readings. You can read 8 possible axis/sliders, four possible POV/hats and 128 possible buttons.

Here is a test GUI showing readings from a twist handle Joystick.

Image 1

An altered version for the test GUI of a steering wheel set.

Image 2

Just Tell Me How to Use It Already!

Step 1

Download the files and add the Joystick_Driver.h, Joystick_Driver.cpp and resource.h to your project

Step 2

Make sure the linker can find all your required external dependencies: windows.h, commctrl.h, dinput.h, dinputd.h, assert.h, and wbemidl.h and additional dependencies. If your project is in Visual Studio, right click on your project and go to properties. In the properties window, go to...

Configuration properties->linker->input->additional dependencies->edit

Then add dxguid.lib, dinput8.lib, comctl32.lib.

At the moment, I am yet to try using this in another IDE but you should need to do for whatever IDE you may be trying to use this in.

Step 3

Now for the easy part.

Declare the following:

C++
Joystick* myJoystick; //pointer to joystick object
HWND hWnd; //window handler

Where appropriate, initialize:

C++
myJoystick = new Joystick();
hWnd = //define a handle to the window of your application with the appropriate syntax

Step 4

Create a timer driven function call to run the joystick.

Using a while loop is a bad idea. Especially, if you have a GUI, that you don’t want to have freezing up on you.

You can check that things work using a while loop but in the end, you are going to need a timer driven function call regardless.

Configure your timer to go off 20-30 times a second or at intervals of 30ms-50ms.

Step 5

In your timer driven function, you may have something as simple as:

C++
Void timerFunct()
{
  myJoystick->runJoystick(hWnd); 
//only update readings while a joystick is available
if(myJoystick->getmsg() == WM_TIMER)
  {
  XAxis = myJoystick->getXAxis();
  YAxis = myJoystick->getYAxis();
  ZRot = myJoystick->getZRot();
  Slider1 = myJoystick->getSlider0();

  POV1 = myJoystick->getPOV0();

  Button0 = myJoystick->getButton(0);
  Button1 = myJoystick->getButton(1);
  Button2 = myJoystick->getButton(2);
  Button3 = myJoystick->getButton(3);
  Button4 = myJoystick->getButton(4);
  }
}

This should give you the gist of how to use it. For a proper working example, consider the next section.

Windows Form Application Example

Design a form application while following this example and add in the following code where needed in your form.h.

C++
#include "Joystick_Driver.h"

public ref class Form1 : public System::Windows::Forms::Form
{
public:
    Form1(void)
    {
        InitializeComponent();
        this->JS = new Joystick();
        this->hWnd = static_cast<HWND>(this->Handle.ToPointer());
    }
    ~Form1()
    {
        if (components)
        {
            delete components;
        }
    }

//***********Here there be lots of************
//private: System::Windows::Forms::Stuff^  stuff;
//********************************************

private:
    Joystick* JS; //pointer to joystick object
private:
    HWND hWnd; //window handler

    #pragma region Windows Form Designer generated code

    void InitializeComponent(void)
    {
        //******** Here there be lots of ********
        //this->stuff->stuff = stuff;
        //***************************************
    }
    #pragma endregion

    //your own functions go here
};

In the design view, add a timer to your form:

Image 3

Don’t forget to set the timer properties:

Image 4

You will now have a function in your form:

C++
private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
}

In the design view, double click the Run and Stop buttons and use these button click event functions to enable and disable the timer.

C++
private: System::Void Run_Click(System::Object^  sender, System::EventArgs^  e)
{
    this->timer1->Enabled = true;
}

private: System::Void Stop_Click(System::Object^  sender, System::EventArgs^  e)
{
    this->timer1->Enabled = false;
}

Add the following to the timer tick function:

C++
private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e)
{
    this->JS->runJoystick(this->hWnd);
    //only update readings on GUI while a joystick is available
    if(this->JS->getmsg() == WM_TIMER)
    {
        this->XAxis->Text = (this->JS->getXAxis()).ToString();
        this->YAxis->Text = (this->JS->getYAxis()).ToString();
        this->ZAxis->Text = (this->JS->getZAxis()).ToString();
        this->XRot->Text = (this->JS->getXRot()).ToString();
        this->YRot->Text = (this->JS->getYRot()).ToString();
        this->ZRot->Text = (this->JS->getZRot()).ToString();

        this->Slider1->Text = (this->JS->getSlider0()).ToString();
        this->Slider2->Text = (this->JS->getSlider1()).ToString();

        this->POV1->Text = (this->JS->getPOV0()).ToString();
        this->POV2->Text = (this->JS->getPOV1()).ToString();
        this->POV3->Text = (this->JS->getPOV2()).ToString();
        this->POV4->Text = (this->JS->getPOV3()).ToString();

        this->Button0->Checked = this->JS->getButton(0);
        this->Button1->Checked = this->JS->getButton(1);
        this->Button2->Checked = this->JS->getButton(2);
        this->Button3->Checked = this->JS->getButton(3);
        this->Button4->Checked = this->JS->getButton(4);
        this->Button5->Checked = this->JS->getButton(5);
        this->Button6->Checked = this->JS->getButton(6);
        this->Button7->Checked = this->JS->getButton(7);
        this->Button8->Checked = this->JS->getButton(8);
        this->Button9->Checked = this->JS->getButton(9);
        this->Button10->Checked = this->JS->getButton(10);
        this->Button11->Checked = this->JS->getButton(11);
        this->Button12->Checked = this->JS->getButton(12);
        this->Button13->Checked = this->JS->getButton(13);
        this->Button14->Checked = this->JS->getButton(14);
        this->Button15->Checked = this->JS->getButton(15);
        this->Button16->Checked = this->JS->getButton(16);
        this->Button17->Checked = this->JS->getButton(17);
        this->Button18->Checked = this->JS->getButton(18);
    }
}

Running the Program

All Axis and Sliders should read within the range of -1000 to 1000. The POV will give 8 different values for all 8 directions and all buttons will simply read true or false.

Notes on Functionality

You may need to delve into the driver and add your own code to it in order to do certain things. Depending on your application, you are going to have to consider...

What happens when you disconnect the joystick?

At this time, the diver will automatically look for another joystick and will accept any joystick it finds, whether it be the same joystick once it’s plugged back in or another joystick that is already plugged in or is to be plugged in.

What happens to the readings when you disconnect the joystick?

Do you want them to freeze at the last updated value or do you want everything to go back to its default zero position?

At this time, the driver freezes the readings at the last read value if the joystick disconnects.

What happens when you have two or more joysticks plugged in?

You may want to be able to choose a joystick device, or you may want to switch between joysticks while your program is running, or you may wish to have two or more joysticks working at the same time.

At this time, the driver doesn’t support multiple joysticks, but it could be adapted to do so. What it will do is create a list of joystick devices and pick one of them automatically. So you can’t choose which joystick.

You can switch devices while the program is running but this means you need to physically unplug them and plug them in.

What if you want to accept inputs only from a specific type of joystick?

The driver has the capacity to recognize the Axis and Buttons that the connected joystick has available so to some degree, you could implement this.

History

  • 10th February, 2013: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Student
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionLink problems Pin
Member 118454863-Mar-16 5:04
Member 118454863-Mar-16 5:04 
QuestionPro! Which Project should I create? Pin
Member 1203295714-Oct-15 16:40
Member 1203295714-Oct-15 16:40 
QuestionThanks a lot Pin
Member 119642537-Sep-15 0:18
Member 119642537-Sep-15 0:18 
I have used your code in my program...Thanks a lot for your opening source code.
QuestionC++ CONSOLE APPLICATION Pin
majdi8611-May-15 21:56
majdi8611-May-15 21:56 
QuestionLinker problems Pin
Alan Laplace20-Mar-15 4:28
Alan Laplace20-Mar-15 4:28 
AnswerRe: Linker problems Pin
Member 1215015122-Nov-15 12:52
Member 1215015122-Nov-15 12:52 
QuestionPolling while host window is minimized Pin
Member 88477853-Mar-15 4:43
Member 88477853-Mar-15 4:43 
AnswerRe: Polling while host window is minimized Pin
showtime7-May-19 12:28
showtime7-May-19 12:28 
Questionhow to complete step 3 ? please help Pin
Muh Rifai Anugrah29-Jan-15 1:33
Muh Rifai Anugrah29-Jan-15 1:33 
Questionplease help me !!! Pin
Muh Rifai Anugrah28-Jan-15 3:11
Muh Rifai Anugrah28-Jan-15 3:11 
GeneralI needed this Pin
Siri Vivienne MK Ancheta1-Dec-14 0:36
Siri Vivienne MK Ancheta1-Dec-14 0:36 
QuestionLinker Error in Project Pin
Member 1097292119-Aug-14 3:58
Member 1097292119-Aug-14 3:58 
AnswerRe: Linker Error in Project Pin
dan o10-Nov-14 4:13
dan o10-Nov-14 4:13 
QuestionCan You Post The Source Code Pin
Classic Corporation5-Jan-14 9:16
Classic Corporation5-Jan-14 9:16 
QuestionMore than one joystick Pin
patoigz11-Sep-13 3:39
patoigz11-Sep-13 3:39 
QuestionJoystick Initialization Problem Pin
Member 98106329-Jul-13 13:18
Member 98106329-Jul-13 13:18 
QuestionJoystick support Pin
Pasteko13-Feb-13 6:06
Pasteko13-Feb-13 6:06 
AnswerRe: Joystick support Pin
Work Damnit!13-Feb-13 13:44
Work Damnit!13-Feb-13 13:44 
GeneralRe: Joystick support Pin
Pasteko14-Feb-13 11:09
Pasteko14-Feb-13 11:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.