Link to home
Start Free TrialLog in
Avatar of RobK6364
RobK6364

asked on

where's the controller ID?

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 DDeviceEnum = DInput.GetDIDevice(DI8DEVTYPE_JOYSTICK, DIEDFL_ATTACHEDONLY)

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
'// ====================================
Avatar of RobK6364
RobK6364

ASKER

P.S.  yeah, this is VB... but if you give me help in C++, that's cool too :)
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..).

d
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.
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.
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 ...

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

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

szPname
Null-terminated string containing the joystick product name.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_joycaps_str.asp



... 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?
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! ;)

-d
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:
//   REGSTR_PATH_JOYCONFIG
//   REGSTR_PATH_JOYOEM
//   REGSTR_VAL_JOYOEMNAME
//
// ----------------------------------------------------------------------------

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.
 id++;
 
 if (id > joyGetNumDevs() ) return JOYERR_NOCANDO;

// Open .. MediaResources\CurrentJoystickSettings
 joyGetDevCaps((id-1), &JoyCaps, sizeof(JoyCaps));
 sprintf(szKey,
   "%s\\%s\\%s",
   REGSTR_PATH_JOYCONFIG,
   JoyCaps.szRegKey,
   REGSTR_KEY_JOYCURR);

 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);
 RegCloseKey(hKey);

 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,
           REGSTR_VAL_JOYOEMNAME,
           0, 0,
           (LPBYTE) pszName,
           (LPDWORD) &dwcb);
 RegCloseKey(hKey);

 if (lr != ERROR_SUCCESS)
  return JOYERR_NOCANDO;
 else
  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.
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_PATH_MEDIARESOURCES As String = REGSTR_PATH_CURRENT_CONTROL_SET & "\MediaResources"
Const REGSTR_PATH_MEDIAPROPERTIES As String = REGSTR_PATH_CURRENT_CONTROL_SET & "\MediaProperties"
Const REGSTR_PATH_PRIVATEPROPERTIES As String = REGSTR_PATH_MEDIAPROPERTIES & "\PrivateProperties"
Const REGSTR_PATH_JOYOEM As String = REGSTR_PATH_PRIVATEPROPERTIES & "\Joystick\OEM"
Const REGSTR_PATH_JOYCONFIG As String = REGSTR_PATH_MEDIARESOURCES & "\Joystick"
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
'//====================================
ASKER CERTIFIED SOLUTION
Avatar of GhostMod
GhostMod
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial