where's the controller ID?

Posted on 2004-10-30
Last Modified: 2013-12-26
hello experts, i'm trying to enumerate all the joysticks on my pc... and i've been had some success, i got the names... but where is the controller ID?  can i assume the controller ID's are coming back in the order of enumeration?  in other words in my code below... is GetItem(1) always controller ID 1?  and GetItem(2) always ID 2 and so forth?

and also another side question... below my references are for DirectX8... if i use DirectX7 instead, will that allow me to perform this simple enumeration on DirectX7 or later? or do i need to detect the DirectX version on the user's os and use the references that match his version?

'// ====================================
Dim x As Integer
Dim diJoystick As DirectInputDevice8
Dim enumDevice As DirectInputEnumDevices8
Dim DirectX As DirectX8
Dim DInput As DirectInput8
Dim DDeviceEnum As DirectInputEnumDevices8
Dim DDeviceInst As DirectInputDeviceInstance8

Set DirectX = New DirectX8

Set DInput = DirectX.DirectInputCreate()


Set diJoystick = DInput.CreateDevice(DDeviceEnum.GetItem(1).GetGuidInstance)

For x = 1 To DDeviceEnum.GetCount
    Set DDeviceInst = DDeviceEnum.GetItem(x)
    Debug.Print DDeviceInst.GetProductName
Next x
'// ====================================
Question by:RobK6364
    LVL 1

    Author Comment

    P.S.  yeah, this is VB... but if you give me help in C++, that's cool too :)
    LVL 17

    Expert Comment

    each version of directx uses slightly different interfaces, and exposes different capabilities.  You'd probably want to use DX8 or DX9, and not go back to DX7 unless you need to support really old machines.

    what 'controller ID' are you looking for?  You are already using GetGuidInstance to create the device linkage -- that's a unique identifier for the device on that system.

    You can also use DDeviceInst.GetInstanceName for a human-readable form of 'controller ID', like "Joystick 1" (the example the MSDN website gives..).

    LVL 1

    Author Comment

    LVL 1

    Author Comment

    maybe joystick id is the correct term... unless those are 2 different things?  all i want to do is put a "human-readable" name in a combobox... and then query joyGetDevCaps for the info for the controller name that the user selects from that combo... for instance.
    LVL 17

    Expert Comment

    The two API sets are completely different -- I don't know of any connection between the old joyGetZZZ calls and DirectX.  There a reason you are trying to mix the two?

    GetInstanceName (and/or GetProductName) are your best human-readable strings for devices under DirectX.
    LVL 1

    Author Comment

    well.. basically i have developed my app around the joyGetZZZ API calls... figuring later to create the user interface.  it's just now that i am trying to build the combobox that i mentioned... which should hold 'human-readable' controller names... yet i need to know which joyID to enter into my functions based on that.

    so if there is no connection between the directx and the api... do you know of a way to get a 'human readable' names for your controllers another way?

    the JOYCAPS structure returned by joyGetDevCaps contains ...

    Manufacturer identifier. Manufacturer identifiers are defined in Manufacturer and Product Identifiers.

    Product identifier. Product identifiers are defined in Manufacturer and Product Identifiers.

    Null-terminated string containing the joystick product name.

    ... but none of those seem to lead to a human-readable name.  the product name returned is "Microsoft Joystick 1" or something like that, and not the nice name returned by DDeviceInst.GetProductName or DDeviceInst.GetInstanceName

    any ideas how this can be done without directx?
    LVL 17

    Expert Comment

    Not off the top of my head.  It's been a loooooong time since I used the joyZZZ functions, since DirectInput has much more control (and information, as you are noting!).

    It is possible there's a way to look up the longer string in the registry (szRegKey), but I don't know of it.  That doesn't mean it doesn't exist.  You can also potentially use the manufacturer and product IDs, if you have the most up-to-date mmreg.h, but I've no clue if you can get to a string from that.

    Yeah, unfortunately, you're hitting the wall that was why DirectInput was created -- it exposed everything developers needed! ;)

    LVL 1

    Author Comment

    hmm... i found this in the MSDN

    // ----------------------------------------------------------------------------
    // Function: joyGetOEMProductName
    // Parameters: UINT id  - Joystick ID from JOYSTICKID1 to JOYSTICK16
    //    TCHAR * pszName - String storage for the OEM Product name
    //         for the selected Joystick device specified
    //         by the parameter "id"
    // Returns:  If Successful, pszName contains OEM product name for JOYSTICKID
    //    else Failure, returns MMRESULT error code, and pszName is cleared.
    // Comments:
    // JOYSTICKID1 to JOYSTICKID16 is zero-based, while the registry entries are
    //  1-based.  This routine expects the parameter "id" to be using JOYSTICKID1
    //  to JOYSTICKID16 which are defined in the multimedia header file mmsystem.h
    //  The following registry keys/values are defined in the header file
    //  regstr.h:
    // ----------------------------------------------------------------------------

    MMRESULT joyGetOEMProductName(UINT id, TCHAR * pszName)
     JOYCAPS JoyCaps;
     TCHAR szKey[256];
     TCHAR szValue[256];
     UCHAR szOEMKey[256];
     HKEY hKey;
     DWORD dwcb;
     LONG lr;

    // Note: JOYSTICKID1-16 is zero-based; registry entries for VJOYD areis 1-based.
     if (id > joyGetNumDevs() ) return JOYERR_NOCANDO;

    // Open .. MediaResources\CurrentJoystickSettings
     joyGetDevCaps((id-1), &JoyCaps, sizeof(JoyCaps));

     lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPTSTR) &szKey, 0, KEY_ALL_ACCESS, &hKey);
     if (lr != ERROR_SUCCESS) return JOYERR_NOCANDO;

    // Get OEM Key name. If the query is unsuccessful, then  Null the string and return
    // an Error.
     dwcb = sizeof(szOEMKey);
     sprintf(szValue, "Joystick%d%s", id, REGSTR_VAL_JOYOEMNAME);
     lr = RegQueryValueEx(hKey, szValue, 0, 0, (LPBYTE) &szOEMKey, (LPDWORD) &dwcb);

     if (lr != ERROR_SUCCESS)
      *pszName = 0;
      return JOYERR_NOCANDO;

    // Open OEM Key from ...MediaProperties
     sprintf(szKey, "%s\\%s", REGSTR_PATH_JOYOEM, szOEMKey);
     lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_ALL_ACCESS, &hKey);

     if (lr != ERROR_SUCCESS) return JOYERR_NOCANDO;

    // Get OEM Name
     dwcb = sizeof(szValue);
     lr = RegQueryValueEx( hKey,
               0, 0,
               (LPBYTE) pszName,
               (LPDWORD) &dwcb);

     if (lr != ERROR_SUCCESS)
      return JOYERR_NOCANDO;
      return JOYERR_NOERROR;

    ... i think that may return the name i want, by looking up the szRegKey... but my problem is that i cant find regstr.h to get vb const definitions for REGSTR_PATH_JOYCONFIG, REGSTR_PATH_JOYOEM, or REGSTR_VAL_JOYOEMNAME.
    LVL 1

    Author Comment

    nevermind... i found regstr.h and converted the function to VB... works like a charm :)

    Const REGSTR_PATH_CURRENT_CONTROL_SET As String = "System\CurrentControlSet\Control"
    Const REGSTR_VAL_JOYOEMNAME As String = "OEMName"
    Const REGSTR_KEY_JOYCURR As String = "CurrentJoystickSettings"

    Public Function joyGetOEMProductName(joyID As Integer) As String
    '// Note: JOYSTICKID1-16 is zero-based, registry entries for VJOYD are 1-based.
    Dim lR As Long
    Dim oJoyCaps As JOYCAPS
    Dim szKey As String
    Dim szValue As String
    Dim szOEMKey As String * 256
    Dim hKey As Long
    Dim sRegKey As String
    Dim sResult As String * 256

    If (joyID > joyGetNumDevs()) Then Exit Function

    '// Open .. MediaResources\CurrentJoystickSettings
    Call joyGetDevCaps(joyID, oJoyCaps, Len(oJoyCaps))
    sRegKey = Left(oJoyCaps.szRegKey, InStr(oJoyCaps.szRegKey, vbNullChar) - 1)
    szKey = REGSTR_PATH_JOYCONFIG & "\" & sRegKey & "\" & REGSTR_KEY_JOYCURR
    lR = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_ALL_ACCESS, hKey)
    If (lR <> ERROR_SUCCESS) Then Exit Function

    '// Get OEM Key name. If the query is unsuccesful, then Null the string and return  an Error.
    szValue = "Joystick" & (joyID + 1) & REGSTR_VAL_JOYOEMNAME
    lR = RegQueryValueEx(hKey, szValue, 0, 0, ByVal szOEMKey, Len(szOEMKey))
    Call RegCloseKey(hKey)
    If (lR <> ERROR_SUCCESS) Then Exit Function

    '// Open OEM Key from ...MediaProperties
    szKey = REGSTR_PATH_JOYOEM & "\" & szOEMKey
    lR = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_ALL_ACCESS, hKey)
    If (lR <> ERROR_SUCCESS) Then Exit Function

    '// Get OEM Name
    lR = RegQueryValueEx(hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, ByVal sResult, Len(sResult))
    Call RegCloseKey(hKey)

    '// return the product name
    If (lR = ERROR_SUCCESS) Then joyGetOEMProductName = Left(sResult, InStr(sResult, vbNullChar) - 1)
    End Function
    LVL 1

    Accepted Solution

    PAQd, 125 points refunded - asker posted solution

    Community Support Moderator

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    How your wiki can always stay up-to-date

    Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
    - Increase transparency
    - Onboard new hires faster
    - Access from mobile/offline

    Suggested Solutions

    What is RenderMan: RenderMan is a not any particular piece of software. RenderMan is an industry standard, defining set of rules that any rendering software should use, to be RenderMan-compliant. Pixar's RenderMan is a flagship implementation of …
    Artificial Intelligence comes in many forms, and for game developers, Path-Finding is an important ability for making an NPC (Non-Playable Character) maneuver through terrain.  A* is a particularly easy way to approach it.  I’ll start with the algor…
    Hi everyone! This is Experts Exchange customer support.  This quick video will show you how to change your primary email address.  If you have any questions, then please Write a Comment below!
    Sending a Secure fax is easy with eFax Corporate ( First, Just open a new email message.  In the To field, type your recipient's fax number You can even send a secure international fax — just include t…

    856 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    9 Experts available now in Live!

    Get 1:1 Help Now