Tuesday, November 23, 2010

Using Joysticks from VB.NET

There are several ways for using joystick on VB.NET: APIs and DirectX. Here I'll show you the DirectX Method.

First, download DirectX SDK from Microsoft:
http://msdn.microsoft.com/en-us/directx/aa937788.aspx
and then install it.

Starts a new project on VB.NET and add a reference to DirectX:
Project -> Add reference.
Select Microsoft.DirectX.DirectInput from list in ".NET" tab:


First thing to do is obtain a device list, but VB.NET will throw an exception (Loader Lock). Deactivate Loader Lock exception from menu Debud -> Exceptions. Explode "Managed Debugging Assistant", find "Loader Lock" and uncheck the box "Generated":



Imports DirectInput name space at top of your program:


Add a timer (timer1) on your form and set "Enabled" property on true (we'll use it for joystick polling).

Add a textbox named txtDir
Add a textbox named txtButtons

The code is the following:

Imports Microsoft.DirectX.DirectInput

Public Class Form1

    Dim joystickDevice As Device

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' List of attached joysticks
        Dim gameControllerList As DeviceList = Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly)

        ' There is one controller at least?
        If (gameControllerList.Count > 0) Then

            ' Select first joystick
            gameControllerList.MoveNext()
            ' Create an object instance
            Dim deviceInstance As DeviceInstance = gameControllerList.Current

            joystickDevice = New Device(deviceInstance.InstanceGuid)
            joystickDevice.SetCooperativeLevel(Me, CooperativeLevelFlags.Background Or CooperativeLevelFlags.NonExclusive)

        End If

        joystickDevice.SetDataFormat(DeviceDataFormat.Joystick)
        joystickDevice.Acquire()

        Timer1.Start()
        

    End Sub

    Private Sub joystickPolling()

        Try
            joystickDevice.Poll()
            Dim state As JoystickState = joystickDevice.CurrentJoystickState

            txtDir.Text = "X=" & state.X & " Y=" & state.Y & " Z=" & state.Z

            txtbuttons.Text = state.GetButtons(0) & " " & state.GetButtons(1)

        Catch ex As Exception

        End Try
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        joystickPolling()

    End Sub
End Class

state object will contain all informations you need. State.X is the X position of joystick (type state followed by dot and see the entire list of controls).

the GetButtons property of state object will give you the state of buttons. GetButtons give an array. 
Example: 

dim button1 as byte = state.GetButtons(0) ' retrieve first button state

if the value is 128, the button is pressed, if the value is 0 the button isn't pressed or doesn't exists 

9 comments:

  1. Hi, congratulations for this code. I used it on a man machine interface I am designing and it works like a charm. I have a question for you. Is it possible to get an event from one of the buttons of the joystick without using the state.getbuttons property, but with a routine similar to a mouse button (for example click or doubleclick)?
    thanks in advance
    nunzio

    ReplyDelete
  2. This is the only post that resolved my problems, thank you!

    ReplyDelete
  3. I am getting a "is not a valid Win32 application" error when I try to debug. I think its because my system is Windows 7 64 bit. How would I correct this?

    Thanks

    ReplyDelete
  4. I am getting a "is not a valid Win32 application" error when I try to debug. It hightlights "joystickPolling()" in the code. I think its because my system is Windows 7 64 bit. How would I correct this?

    Thanks

    ReplyDelete
  5. I am having the same problem as William. Any suggestions?

    Thanks

    ReplyDelete
  6. Who will help me? how do ...

    Private Sub Button1_pressed (......

    'If joystick button number one pressed then my code

    End sub

    The code works fine, but I need to send the command once , and now it still sends me as long as the button is pressed

    Thanks

    ReplyDelete
  7. If it was truly your code you would know!

    The line : Call joyGetPosEx(0, myjoyEX)

    Change the 0 to point to a second device, you might consider using a loop to poll through all available devices.

    ReplyDelete