Introduction

When trying to find some code to use my joystick through C#, I found a sad lack of articles. There were a few posts on forums with bits and pieces of code, but no solid code on how you can use it. The scenario of a 6-axis, 20+ buttoned joystick does not seem to have occured in any C# articles before - much less on CodeProject. I intend to demonstrate how to acquire and use a full 6-axis joystick, plus all the buttons availiable.

Managed DirectX

As Managed DirectX (MDX) 2.0 is not yet released and will be included in XNA, this article uses Managed DirectX 1.1, which is fully compatible with .NET 2.0. However, you will need to change a setting within Visual Studio 2005 or a Loader Lock exception will be thrown as soon as you attempt to get a device list. The setting you need to change in VS 2005 is under the Debug menu, in Exceptions. In Managed Debugging Asssitants, uncheck "Thrown" on Loader Lock. This will allow you to debug your application. Once you have downloaded and installed the SDK, you can add a reference to Microsoft.DirectX.DirectInput to your project. To use Managed DirectX, you will have to download the DirectX Software Developers Kit. At the time of writing, the October 2006 SDK is the latest version availiable. You can download the SDK at the DirectX SDK website. It is about 500 MB, so if you are not on a fast connection, it could take some time.

Finding Your Device

To locate a joystick, a list of all game controllers that are attached to the system needs to be obtained; the DeviceList method does this. Once a list of devices has been found, the first controller in the list will be acquired. You could display a list of controllers to the user and allow for them to select the correct one if you wished.

The variable joystickDevice is a Device object declared as a private member of the class, this will be required in other methods later on.

// Find all the GameControl devices that are attached.
DeviceList gameControllerList = Manager.GetDevices(DeviceClass.GameControl,
EnumDevicesFlags.AttachedOnly);
// check that we have at least one device.
if (gameControllerList.Count > 0)
{
// Move to the first device
gameControllerList.MoveNext();
DeviceInstance deviceInstance = (DeviceInstance)
gameControllerList.Current;
// create a device from this controller.
joystickDevice = new Device(deviceInstance.InstanceGuid);
joystickDevice.SetCooperativeLevel(this,
CooperativeLevelFlags.Background |
CooperativeLevelFlags.NonExclusive);
}
// Tell DirectX that this is a Joystick.
joystickDevice.SetDataFormat(DeviceDataFormat.Joystick);
// Finally, acquire the device.
joystickDevice.Acquire();

The joystickDevice variable should now be usable.

What is the Joystick Capable of?

This device can now be queried to find out what it is capable of. The DeviceCaps class is able to find out how many axes, buttons and points of view hats the joystick has.

These numbers will probably play an important role when writing an application implementing the joystick.

Getting Device Input

Each time the current state of the joystick is required, the Poll method needs to be called to update the joystickDevice object. Once this is done, the joystick state is updated, allowing current axis positions and button states to be found. The following private method will poll the joystick and update the state. This method updates a JoystickState object called state, which is a private field in the class.

privatevoid Poll ( )
{
try
{
// poll the joystick
joystickDevice.Poll();
// update the joystick state field
state = joystickDevice.CurrentJoystickState;
}
catch (Exception err)
{
// we probably lost connection to the joystick
// was it unplugged or locked by another application?
Debug.WriteLine(err.Message);
}
}

The exception should probably be dealt with a little smarter, but at the moment, it doesn't matter. This method will need to be called each time we want to retrieve anything from the joystick.

Once the device has been polled for its current state, the axes positions and button state can be retrieved from the state object. The state object only has properties for four axes. The next section demonstrates retrieving the final two that are availiable if a six-axis joystick is in use. An axis' value is between 0 and 65535.

The GetButtons() method on the state object returns a byte array for each of the buttons. When the value is 128, the button has been pressed. A button is read as follows:

bool buttonA = buttons[0] >= 128;

You can do this for each of your joystick's buttons. Additionally, PoV hats also show up in the buttons collection.

Finding Additional Inputs

If the joystick has additional axes that are not availiable as properties on the state object, you can use the GetSliders method to obtain an additional two axes. The GetSliders method returns an array of two ints; just like the other axis, these are values from 0 to 65535.

Conclusion

Hopefully, this information will be useful to you and you'll be able to use your joystick without any issues. This article only covers the basics and you may wish to implement Force Feedback or PoV hats or other technologies that are availiable.

History

Friday, 8 December 2006 - First version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Mark spends his spare time working on his radio control planes, helicopters and trucks. He devises new ways to make them crash faster and easier than ever before. Mark has progressed this joy of destroying nice toys into build UAV's - which can crash themselves with, or without user input.

hi Harris,I have a problem regarding this application when i am compiling this code ,it runs successfully but i am getting blank form,means after compiling it is not showig any buttons and bars which you have showm in attached jpeg file please help me out.kindly do the needful

Hi M Harris,Thanks a lot for your code! Its exactly what im looking for. Im having a slight problem getting it to work though. Im pretty new to Visual Studio and C#, and when i open your project and run it, the main window pops up, but its empty (no buttons or scroll bars...). I am using Visual Studio 2010Thanks!

I have used this program months ago...now i have changed my system..added references as given but now it says * this is not a win32 application *i am wondering why this error is coming again n again...any one help please !!!

DLL 'C:\Windows\assembly\GAC\Microsoft.DirectX\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.dll' is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.

Read the article - it explains quite clearly that you will get a LoaderLock exception and how to get rid of it. You can either disable the exception using the settings provided or you can use Managed DirectX 2.0 beta, which is available in the December 2005 DirectX SDK. It was compiled to fully support .NET 2.0 and thus no longer causes the exception to be thrown -- note however that there are some minor syntactical changes between MDX 1.1 and 2.0 beta however it is faster and more reliable overall. DirectInput (along with all the other APIs - Direct3D, ACT, XInput) have been bundled together under the unified Microsoft.DirectX namespace and are all in the one .DLL file. I understand that DXGI is the formal replacement for the 2.0 beta library, however it does not include DirectInput.

DLL 'C:\Windows\assembly\GAC\Microsoft.DirectX\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.dll' is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.

i have this problem when running code on studio 2008 can any one have solution of this please give replay

I have tried creating my own code from the MSDN examples as well. I am using C# 2010. Your exe works unless I load the solution and recompile. If I run the exe after compiling it freezes before anything gets displayed. Same as when I made from scratch. I have Microsoft.DirectX.DirectInput and Microsoft.DirectX References added and also under the 'Using' area.

It seems like there is something wrong on my end. I have re-installed the DirectX SDK already with no luck.

Wondering if you ever encountered this type of problem before during your development.

(took some time to trace...)this is due to the fact that if you are running an application with .net4 - the dx dlls need legacy mode in order to work (i spent about a day to work this thing out...)inside app.config just use this block:

I've downloaded the source code and tested it on VS2010 and it threw me an exception LoaderLock.After a bit of searching I found that it relates to DirectX and found a project called SlimDX which is just like Microsoft DirectX only better and compiled in .Net framework 4.0.

The joystick project now works in .Net framework 4.0 and doesn't throw any exception.

great advice, thank you! I'm trying to also get my joystick working but it's unsupported on WIn7 (Sidewinder Force Feedback 2) though plug and play shows up as a "usb input device". So I may need to buy a different joystick, which one do you have?

i downloaded the source file in this website and i running it with Microsoft visual C# 2008 edition i runs without errors. but my joystick is not working . u given some device initialization code(find ur device) in this website . but i dont know where i have to paste it on that source file?. pls can u tell that how to initialize the joystick pls reply me soon... thank you....

I have used this example with great success to read the state of joystick buttons on a games port. However until a button is pressed, joystickState.GetButtons() just returns an array of 0's for all buttons.

For example, if I have button 1 permenantly pressed, then when the app starts it shows as off. Then if I press button 2, 3 or 4, that button shows, and SO DOES button 1.

So how do I get DirectX to tell me the initial state of the buttons, or force a refresh, etc? It must be possible?

All help gratefully received. I've found 1 other person asking this on Google (no answers though) - but it must be an issue for other peoples applications?

I have been trying to get this code to work for a long time now. I realize this is very old now, but it seems as though others have been able to get it to work.

One, on Windows 7 64-bit no matter what I do(reading through the old comments) I cannot get it to work, it either stalls out, or I get a DirectX.DirectInput alarm saving DirectX.DirectInput.dll is not a valid Win32 file....

Either way, I was wondering if someone would like to share anything they have made with this code.

I have recently tried to get this to work. If I run the application it works correctly, but if I open the source in C# Express, Build it and Debug, I also get a blank Form. I have changed to compile x86, any CPU etc. but nothing seems to work for Debugging???

I´m working with a Thrustmaster F430 Steering wheel and want to control a rc-car via PC, that works perfect. I woukd like to use the coolie hat button (Engine Start on the Steering wheel) for starting the car, but i the program can´t find that button on it´s own.

Now my question is had somebody a similar problem and can help me to resolve this problem?

Hey there, I would like to thank you on providing all of this useful information. However, I cannot seem to find how to interact with the POV hats. I am able to see that the axis and buttons are being used, but there seems to be no response from the POV hats. Hope to hear from you soon!

If I create a new project and I use your dll in the main screen, it works correctly. But if I want to use it in a configuration screen (that must be reached by the main menu), it fails. Extactly in the SetCooperativeLeven function.

I haven't done c# coding for quite a while so i may be missing something quite obvious! I am not sure where i have to put my code so that i can use your code as a reference but still get my form1.cs to come up instead of the frmmain.

I am attempting to do what you did in yours, make a trackbar move with the axis but whenever i do that it just stays in one position, i have tried using the state.X, both AxisC and axisC but i cant get it to work :s

hello, i am new to C#, but i would like to write a program for a joystick. (hense the research on this article) i have Visual C# 2008, and i think i properly installed Windows SDK 6.1, but when i try to use this code, DeviceList and Device are under errors. For DeviceList, it says that a namespace doesn't directly contain members such as fields or methods. and for Device it says "expected class, delegate, enum, interface, or struct." Plz help! Thanks.

Thanks for this great article!In my case I wanted to change the program to check multiple controllers. I had two exactly the same controllers and this caused troubles in the joystick class, because both controllers have the same name. To fix this I changed FindJoysticks() to return deviceInstance.InstanceGuid. AquireJoystick takes a Guid as an argument and compares that in the foreach loop to the deviceInstance.InstanceGuid. This way the controllers never get mixed up.

I have purchased an USB card that functions as a joystick. it has 5 analog axis and 32 buttons.I need them to build a simulator cockpit, but the switches I will use are ON-OF-ON switches or ON-ON,i will connect the ON-OFF-ON each ON on 1 button, and the ON-ON on another two buttons, but:I don't need them to be sending "PUSHED" status or how it's said every time it is pressed, just the moment it detects the changed status.

How can I listen for a button (in fact, 24 buttons of 32) and if the previus state is diferent from actual, send actual state, and if it's equal, send OFF state?

I was thinking on implement a configurator for the joy using your code and put a combo for telling the program how to function each button

Hi M Harris,Thanks a lot for your code! Its exactly what im looking for. Im having a slight problem getting it to work though. Im pretty new to Visual Studio and C#, and when i open your project and run it, the main window pops up, but its empty (no buttons or scroll bars...). I was wondering if this is a problem with my visual studio setting or maybe its some other known issue?? (By the way, i have changed the settings about the exception you warned, as well as downloaded the latest SDK for DirectX. I am also using Visual Studio 2008)Thanks!