Sign in to follow this  
ed209

[.net] read joystick buttons using windows api without DirectX

Recommended Posts

ed209    122
Hi, I'm trying to use joyGetPosEx to read the buttons pressed. First I use joyGetNumDevs to get the number of controls, but 81269371174928 is what is returned. Shouldn't it return the number of controllers? Also, joygetposex just returns 165, which also doesnt make sense. Could someone please tell me what I'm doing wrong?

Share this post


Link to post
Share on other sites
Tape_Worm    2807
81269371174928 is unlikely as the joyGetNumDevs() function returns a UINT, and that number would be far outside of the range of an unsigned 32 bit integer. Of course, that's assuming you're returning an unsigned integer (if it's a long/int64 then you have the function declared incorrectly). How is your p/invoke declaration for that function set up? I have mine as:

/// <summary>
/// Function to return the number of joystick devices supported by the current driver.
/// </summary>
/// <returns>Number of joysticks supported, 0 if no driver is installed.</returns>
[DllImport("WinMM.dll"), System.Security.SuppressUnmanagedCodeSecurity]
public static extern int joyGetNumDevs();

And that works perfectly for me.

Also, you're getting error code 165 from joyGetPos? That error would be:
JOYERR_PARMS /* bad parameters */ (according to mmsystem.h)

According to MSDN, that means the ID of the joystick isn't valid.

Also make sure your joysticks showing up in the joystick control panel.

Share this post


Link to post
Share on other sites
ed209    122
Hi, and thanks for your response.

I tried ID's 0-15 and all of them return 165 even when the joysticks show up in the joystick control panel.

Share this post


Link to post
Share on other sites
ed209    122
I finally got getjoyposex to work, but it isn't returning any of the joystick information, such as the x position or the buttons pressed. So i tried my code in vb 6.0 and it works fine! Why would my code work in vb 6.0 and not in vb.net?


Public Class Form1
Public Const JOY_RETURNBUTTONS = &H80&
Public Const JOY_RETURNCENTERED = &H400&
Public Const JOY_RETURNPOV = &H40&
Public Const JOY_RETURNR = &H8&
Public Const JOY_RETURNU = &H10
Public Const JOY_RETURNV = &H20
Public Const JOY_RETURNX = &H1&
Public Const JOY_RETURNY = &H2&
Public Const JOY_RETURNZ = &H4&
Public Const JOY_RETURNALL = (JOY_RETURNX Or JOY_RETURNY Or JOY_RETURNZ Or JOY_RETURNR Or JOY_RETURNU Or JOY_RETURNV Or JOY_RETURNPOV Or JOY_RETURNBUTTONS)


Public Declare Function joyGetPosEx Lib "winmm.dll" (ByVal uJoyID As UInteger, ByRef pji As JOYINFOEX) As Integer



Public Structure JOYINFOEX
Dim dwSize As Long ' size of structure
Dim dwFlags As Long ' flags to indicate what to return
Dim dwXpos As Long ' x position
Dim dwYpos As Long ' y position
Dim dwZpos As Long ' z position
Dim dwRpos As Long ' rudder/4th axis position
Dim dwUpos As Long ' 5th axis position
Dim dwVpos As Long ' 6th axis position
Dim dwButtons As Long ' button states
Dim dwButtonNumber As Long ' current button number pressed
Dim dwPOV As Long ' point of view state
Dim dwReserved1 As Long ' reserved for communication between winmm driver
Dim dwReserved2 As Long ' reserved for future expansion
End Structure


Dim joy As JOYINFOEX



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

joy.dwSize = Len(joy)
joy.dwFlags = JOY_RETURNALL
joyGetPosEx(0, joy)

Label2.Text = joy.dwXpos
End Sub


End Class

Share this post


Link to post
Share on other sites
SeaEagle1    122
I don't know VB.NET but in C# you should declare joyGetPosEx with either "[Out]ref JOYINFOEX" or "out JOYINFOEX", otherwise it will only be marshalled from managed to unmanaged code, not the other way around.

Share this post


Link to post
Share on other sites
Tape_Worm    2807
You don't have the [StructLayout(LayoutKind.Sequential)] attribute defined for the JOYINFOEX value type. If you don't define that attribute, the runtime will possibly rearrange your value type for a number of reasons (e.g. performance, because it's evil, etc...). Specifying sequential will tell the runtime that the fields should stay in the order in which they're declared. You can learn more about it on the MSDN.

Here's what I've got:

/// <summary>
/// Value type containing joystick position information.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct JOYINFOEX
{
/// <summary>Size of structure, in bytes.</summary>
public int Size;
/// <summary>Flags to indicate what information is valid for the device.</summary>
public JoystickInfoFlags Flags;
/// <summary>X axis.</summary>
public int X;
/// <summary>Y axis.</summary>
public int Y;
/// <summary>Z axis.</summary>
public int Z;
/// <summary>Rudder position.</summary>
public int Rudder;
/// <summary>5th axis position.</summary>
public int Axis5;
/// <summary>6th axis position.</summary>
public int Axis6;
/// <summary>State of buttons.</summary>
public JoystickButtons Buttons;
/// <summary>Currently pressed button.</summary>
public int ButtonNumber;
/// <summary>Angle of the POV hat, in degrees (0 - 35900, divide by 100 to get 0 - 359 degrees.</summary>
public int POV;
/// <summary>Reserved.</summary>
int Reserved1;
/// <summary>Reserved.</summary>
int Reserved2;
}


In VB.NET that attribute would be declared like this (and don't forget to import the System.Runtime.InteropServices namespace):
<StructLayout(LayoutKind.Sequential)> _
Public Structure JOYINFOEX

Also I noticed you have all your fields declared as "Long" in your VB6 version. If you haven't changed those already, know that it's not going to work in VB.NET. You need to declare those fields as Integer in VB.NET. This is because in VB6, Long was a 32 bit integer, while in VB.NET Long is a 64 bit integer.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this