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

Started by
4 comments, last by Tape_Worm 15 years, 7 months ago
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?
Advertisement
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.
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.
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 SubEnd Class
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.
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.

This topic is closed to new replies.

Advertisement