home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / dxview / dinput.c next >
Encoding:
C/C++ Source or Header  |  1997-07-15  |  15.5 KB  |  546 lines

  1. /****************************************************************************
  2.  
  3.     Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  
  5.     PROGRAM: dinput.c
  6.  
  7.     PURPOSE: DirectX Device Viewer - DirectInput module
  8.  
  9.     FUNCTIONS:
  10.  
  11.     COMMENTS:
  12.  
  13. ****************************************************************************/
  14.  
  15. #include "dxview.h"
  16.  
  17. #define DICAPDEF(name,val,flag) {name, FIELD_OFFSET(DIDEVCAPS,val), flag}
  18. #define DIVALDEF(name,val)      {name, FIELD_OFFSET(DIDEVCAPS,val), 0}
  19.  
  20. /****************************************************************************
  21.  *
  22.  *  DI_CreateDI
  23.  *
  24.  *  Create a DirectInput pointer.  Try the current DirectInput version
  25.  *  first; if that doesn't work, try version 3.0.
  26.  *
  27.  ****************************************************************************/
  28.  
  29. LPDIRECTINPUT
  30. DI_CreateDI(void)
  31. {
  32.     LPDIRECTINPUT pdi;
  33.  
  34.     if (SUCCEEDED(DirectInputCreate(g_hInstance, DIRECTINPUT_VERSION,
  35.                                     &pdi, NULL))) {
  36.     } else
  37.     if (SUCCEEDED(DirectInputCreate(g_hInstance, 0x0300,
  38.                                     &pdi, NULL))) {
  39.     } else {
  40.         pdi = 0;
  41.     }
  42.  
  43.     return pdi;
  44. }
  45.  
  46. /****************************************************************************
  47.  *
  48.  *  DI_CreateDevice
  49.  *
  50.  *  Create a device with the specified instance GUID.
  51.  *
  52.  ****************************************************************************/
  53.  
  54. LPDIRECTINPUTDEVICE
  55. DI_CreateDevice(LPCGUID pguid)
  56. {
  57.     LPDIRECTINPUT pdi;
  58.     LPDIRECTINPUTDEVICE pdev;
  59.  
  60.     pdi = DI_CreateDI();
  61.     if (pdi) {
  62.         if (SUCCEEDED(IDirectInput_CreateDevice(pdi, pguid, &pdev, NULL))) {
  63.         } else {
  64.             pdev = 0;
  65.         }
  66.         IDirectInput_Release(pdi);
  67.     } else {
  68.         pdev = 0;
  69.     }
  70.     return pdev;
  71. }
  72.  
  73. /****************************************************************************
  74.  *
  75.  *  DI3Info
  76.  *
  77.  *      Structure that describes the caps maintained by DIDEVCAPS
  78.  *      that existed in DirectX 3.
  79.  *
  80.  ****************************************************************************/
  81.  
  82. CAPDEF DI3Info[] =
  83. {
  84.     DIVALDEF("Axes",                dwAxes),
  85.     DIVALDEF("Buttons",             dwButtons),
  86.     DIVALDEF("POVs",                dwPOVs),
  87.  
  88.     DICAPDEF("ATTACHED",            dwFlags,        DIDC_ATTACHED),
  89.     DICAPDEF("POLLEDDEVICE",        dwFlags,        DIDC_POLLEDDEVICE),
  90.     DICAPDEF("EMULATED",            dwFlags,        DIDC_EMULATED),
  91.  
  92.     {"", 0, 0}
  93. };
  94.  
  95. /****************************************************************************
  96.  *
  97.  *  DI5Info
  98.  *
  99.  *      Structure that describes the caps maintained by DIDEVCAPS
  100.  *      that exist in DirectX 5 and were't in DirectX 3.
  101.  *
  102.  ****************************************************************************/
  103.  
  104. CAPDEF DI5Info[] =
  105. {
  106.     DICAPDEF("FORCEFEEDBACK",       dwFlags,        DIDC_FORCEFEEDBACK),
  107.     DICAPDEF("FFATTACK",            dwFlags,        DIDC_FFATTACK),
  108.     DICAPDEF("FFFADE",              dwFlags,        DIDC_FFFADE),
  109.     DICAPDEF("SATURATION",          dwFlags,        DIDC_SATURATION),
  110.     DICAPDEF("POSNEGCOEFFICIENTS",  dwFlags,        DIDC_POSNEGCOEFFICIENTS),
  111.     DICAPDEF("POSNEGSATURATION",    dwFlags,        DIDC_POSNEGSATURATION),
  112.  
  113.     DIVALDEF("FFSamplePeriod",      dwFFSamplePeriod),
  114.     DIVALDEF("FFMinTimeResolution", dwFFMinTimeResolution),
  115.     {"", 0, 0}
  116. };
  117.  
  118. /****************************************************************************
  119.  *
  120.  *  DISubTypeList
  121.  *
  122.  *      List of various DirectInput device subtypes and their names.
  123.  *
  124.  ****************************************************************************/
  125.  
  126. typedef struct SUBTYPEINFO {
  127.     DWORD dwDevType;
  128.     LPCTSTR pszName;
  129. } SUBTYPEINFO;
  130.  
  131. #define SUBTYPE(type, subtype, name)    \
  132.     {   MAKEWORD(DIDEVTYPE_##type, \
  133.         DIDEVTYPE##type##_##subtype), \
  134.         TEXT("%d - ") TEXT(name) }
  135.  
  136. SUBTYPEINFO DISubTypes[] = {
  137.     SUBTYPE(MOUSE,          UNKNOWN,            "Unknown"),
  138.     SUBTYPE(MOUSE,          TRADITIONAL,        "Traditional"),
  139.     SUBTYPE(MOUSE,          FINGERSTICK,        "Fingerstick"),
  140.     SUBTYPE(MOUSE,          TOUCHPAD,           "Touchpad"),
  141.     SUBTYPE(MOUSE,          TRACKBALL,          "Trackball"),
  142.  
  143.     SUBTYPE(KEYBOARD,       UNKNOWN,            "Unknown"),
  144.     SUBTYPE(KEYBOARD,       PCXT,               "XT"),
  145.     SUBTYPE(KEYBOARD,       OLIVETTI,           "Olivetti"),
  146.     SUBTYPE(KEYBOARD,       PCAT,               "AT"),
  147.     SUBTYPE(KEYBOARD,       PCENH,              "Enhanced"),
  148.     SUBTYPE(KEYBOARD,       NOKIA1050,          "Nokia 1050"),
  149.     SUBTYPE(KEYBOARD,       NOKIA9140,          "Nokia 9140"),
  150.     SUBTYPE(KEYBOARD,       NEC98,              "NEC98"),
  151.     SUBTYPE(KEYBOARD,       NEC98LAPTOP,        "NEC98 Laptop"),
  152.     SUBTYPE(KEYBOARD,       NEC98106,           "NEC98 106"),
  153.     SUBTYPE(KEYBOARD,       JAPAN106,           "Japan 106"),
  154.     SUBTYPE(KEYBOARD,       JAPANAX,            "Japan AX"),
  155.     SUBTYPE(KEYBOARD,       J3100,              "J3100"),
  156.  
  157.     SUBTYPE(JOYSTICK,       UNKNOWN,            "Unknown"),
  158.     SUBTYPE(JOYSTICK,       TRADITIONAL,        "Traditional"),
  159.     SUBTYPE(JOYSTICK,       FLIGHTSTICK,        "Flightstick"),
  160.     SUBTYPE(JOYSTICK,       GAMEPAD,            "Gamepad"),
  161.     SUBTYPE(JOYSTICK,       RUDDER,             "Rudder"),
  162.     SUBTYPE(JOYSTICK,       WHEEL,              "Wheel"),
  163.     SUBTYPE(JOYSTICK,       HEADTRACKER,        "Head tracker"),
  164.     { 0, 0 },
  165. };
  166.  
  167. /****************************************************************************
  168.  *
  169.  *  DIAddRow
  170.  *
  171.  *  Add a row to the growing two-column listview or printer.
  172.  *
  173.  *      lpInfo = print context or NULL if adding to listview
  174.  *      pszName = name of cap
  175.  *      pszFormat = wsprintf-style format string
  176.  *      ... = inserts for wsprintf
  177.  *
  178.  ****************************************************************************/
  179.  
  180. BOOL __cdecl
  181. DIAddRow(PRINTCBINFO *lpInfo, LPCTSTR pszName, LPCTSTR pszFormat, ...)
  182. {
  183.     BOOL fRc;
  184.     TCHAR szBuf[1024];
  185.     int cch;
  186.     va_list ap;
  187.  
  188.     va_start(ap, pszFormat);
  189.     cch = wvsprintf(szBuf, pszFormat, ap);
  190.     va_end(ap);
  191.  
  192.     if (lpInfo == NULL) {
  193.         LVAddText(g_hwndLV, 0, pszName, 0);
  194.         LVAddText(g_hwndLV, 1, TEXT("%s"), szBuf);
  195.     } else {
  196.         int xName, xVal, yLine;
  197.  
  198.         // Calculate Name and Value column x offsets
  199.         xName   = (lpInfo->dwCurrIndent * DEF_TAB_SIZE * lpInfo->dwCharWidth);
  200.         xVal    = xName + (32 * lpInfo->dwCharWidth);
  201.         yLine = lpInfo->dwCurrLine * lpInfo->dwLineHeight;
  202.  
  203.         // Print name
  204.         fRc = PrintLine(xName, yLine, pszName, lstrlen(pszName), lpInfo);
  205.         if (!fRc) goto done;
  206.  
  207.         // Print value
  208.         fRc = PrintLine(xVal, yLine, szBuf, cch, lpInfo);
  209.         if (!fRc) goto done;
  210.  
  211.         // Advance to next line on page
  212.         fRc = PrintNextLine(lpInfo);
  213.         if (!fRc) goto done;
  214.     }
  215.  
  216.     fRc = TRUE;
  217.  
  218. done:;
  219.     return fRc;
  220. }
  221.  
  222. /****************************************************************************
  223.  *
  224.  *  DIAddTypes
  225.  *
  226.  *  Emit the device type information to the output device.
  227.  *
  228.  *      lpInfo = print context or NULL if adding to listview
  229.  *      dwDevType = device type to decode
  230.  *
  231.  ****************************************************************************/
  232.  
  233. BOOL DIAddTypes(PRINTCBINFO *lpInfo, DWORD dwDevType)
  234. {
  235.     BOOL fRc;
  236.     DWORD dwType;
  237.     LPCTSTR pszValue;
  238.     SUBTYPEINFO *psti;
  239.  
  240.     /*
  241.      *  Add the type code.
  242.      */
  243.  
  244.     dwType = GET_DIDEVICE_TYPE(dwDevType);
  245.     switch (dwType) {
  246.     case DIDEVTYPE_MOUSE:   pszValue = TEXT("%d - Mouse"); break;
  247.     case DIDEVTYPE_KEYBOARD:pszValue = TEXT("%d - Keyboard"); break;
  248.     case DIDEVTYPE_JOYSTICK:pszValue = TEXT("%d - Joystick"); break;
  249.     default:                pszValue = TEXT("%d"); break;
  250.     }
  251.  
  252.     fRc = DIAddRow(lpInfo, "Type", pszValue, dwType);
  253.     if (!fRc) goto done;
  254.  
  255.     /*
  256.      *  Add the sub type code.
  257.      */
  258.  
  259.     pszValue = TEXT("%d");
  260.     for (psti = DISubTypes; psti->dwDevType; psti++) {
  261.         if (psti->dwDevType == (dwDevType & 0xFFFF)) {
  262.             pszValue = psti->pszName;
  263.             break;
  264.         }
  265.     }
  266.  
  267.     fRc = DIAddRow(lpInfo, TEXT("Subtype"), pszValue,
  268.                    GET_DIDEVICE_SUBTYPE(dwDevType));
  269.     if (!fRc) goto done;
  270.  
  271.     fRc = TRUE;
  272. done:;
  273.     return fRc;
  274. }
  275.  
  276. /****************************************************************************
  277.  *
  278.  *  DIAddCapsToTarget
  279.  *
  280.  *  Add the caps either to the listview or to the printer.
  281.  *
  282.  *      lpInfo = print context or NULL if adding to listview
  283.  *      pcd = pointer to CAPDEF array describing the caps
  284.  *      pv = pointer to structure to be parsed
  285.  *
  286.  ****************************************************************************/
  287.  
  288. BOOL
  289. DIAddCapsToTarget(PRINTCBINFO *lpInfo, CAPDEF *pcd, LPVOID pv)
  290. {
  291.     BOOL fRc;
  292.  
  293.     if (lpInfo) {
  294.         fRc = PrintCapsToDC(pcd, pv, lpInfo);
  295.     } else {
  296.         AddMoreCapsToLV(pcd, pv);
  297.         fRc = TRUE;
  298.     }
  299.     return fRc;
  300. }
  301.  
  302. /****************************************************************************
  303.  *
  304.  *  DIPrintCaps
  305.  *
  306.  *      lpInfo = print context or NULL if adding to listview
  307.  *      lParam1 = state info recorded by DIEnumDevCallback (LPGUID)
  308.  *      lParam2 = refdata (not used)
  309.  *
  310.  ****************************************************************************/
  311.  
  312. BOOL
  313. DIPrintCaps(LPARAM lParam1, LPARAM lParam2, PRINTCBINFO *lpInfo)
  314. {
  315.     BOOL fRc;
  316.     LPGUID pguid = (LPGUID)lParam1;
  317.     LPDIRECTINPUTDEVICE pdev;
  318.  
  319.     if (lpInfo == NULL) {
  320.         AddColsToLV();
  321.     }
  322.  
  323.     fRc = TRUE;
  324.  
  325.     pdev = DI_CreateDevice(pguid);
  326.  
  327.     if (pdev) {
  328.         DIDEVCAPS caps;
  329.         HRESULT hres;
  330.  
  331.         /*
  332.          *  First use the DX3 caps.
  333.          */
  334.         caps.dwSize = sizeof(DIDEVCAPS_DX3);
  335.  
  336.         hres = IDirectInputDevice_GetCapabilities(pdev, &caps);
  337.         if (SUCCEEDED(hres)) {
  338.  
  339.             fRc = DIAddTypes(lpInfo, caps.dwDevType) &&
  340.                   DIAddCapsToTarget(lpInfo, DI3Info, &caps);
  341.         }
  342.  
  343.         /*
  344.          *  Now get the DX5 caps if we haven't cancelled printing yet.
  345.          */
  346.         if (fRc) {
  347.             caps.dwSize = sizeof(DIDEVCAPS);
  348.  
  349.             hres = IDirectInputDevice_GetCapabilities(pdev, &caps);
  350.             if (SUCCEEDED(hres)) {
  351.  
  352.                 fRc = DIAddCapsToTarget(lpInfo, DI5Info, &caps);
  353.             }
  354.         }
  355.  
  356.         IDirectInputDevice_Release(pdev);
  357.     }
  358.     return fRc;
  359. }
  360.  
  361. /****************************************************************************
  362.  *
  363.  *  DIAddCaps
  364.  *
  365.  *      lParam1 = state info recorded by DIEnumDevCallback (LPGUID)
  366.  *      lParam2 = refdata (not used)
  367.  *
  368.  ****************************************************************************/
  369.  
  370. void
  371. DIAddCaps(LPARAM lParam1, LPARAM lParam2)
  372. {
  373.     DIPrintCaps(lParam1, lParam2, NULL);
  374. }
  375.  
  376. /****************************************************************************
  377.  *
  378.  *  DIEnumEffCallback
  379.  *
  380.  *  Add the enumerated DirectInput effect to the listview.
  381.  *
  382.  ****************************************************************************/
  383.  
  384. BOOL CALLBACK
  385. DIEnumEffCallback(LPCDIEFFECTINFO pei, LPVOID lpInfo)
  386. {
  387.     BOOL fRc;
  388.     const GUID *pguid = &pei->guid;
  389.  
  390.     fRc = DIAddRow(lpInfo, pei->tszName,
  391.                    TEXT("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
  392.                     pguid->Data1, pguid->Data2, pguid->Data3,
  393.                     pguid->Data4[0], pguid->Data4[1],
  394.                     pguid->Data4[2], pguid->Data4[3],
  395.                     pguid->Data4[4], pguid->Data4[5],
  396.                     pguid->Data4[6], pguid->Data4[7]);
  397.     if (fRc) {
  398.         return DIENUM_CONTINUE;
  399.     } else {
  400.         return DIENUM_STOP;
  401.     }
  402. }
  403.  
  404. /****************************************************************************
  405.  *
  406.  *  DIPrintEffects
  407.  *
  408.  *      lpInfo = print context or NULL if adding to listview
  409.  *      lParam1 = state info recorded by DIEnumDevCallback (LPGUID)
  410.  *      lParam2 = refdata (not used)
  411.  *
  412.  ****************************************************************************/
  413.  
  414. BOOL
  415. DIPrintEffects(LPARAM lParam1, LPARAM lParam2, PRINTCBINFO *lpInfo)
  416. {
  417.     BOOL fRc;
  418.     LPGUID pguid = (LPGUID)lParam1;
  419.     LPDIRECTINPUTDEVICE pdev;
  420.  
  421.     /*
  422.      *  The effects are not a simple name/value thing.
  423.      *  But DXView doesn't like multiple nesting levels,
  424.      *  so we mash it into the name/value paradigm
  425.      *  because I'm lazy.  Someday I won't be quite so
  426.      *  lazy and do it right.
  427.      */
  428.  
  429.     if (lpInfo == NULL) {
  430.         AddColsToLV();
  431.     }
  432.  
  433.     fRc = TRUE;
  434.     pdev = DI_CreateDevice(pguid);
  435.  
  436.     if (pdev) {
  437.         LPDIRECTINPUTDEVICE2 pdev2;
  438.         HRESULT hres;
  439.  
  440.         hres = IDirectInputDevice_QueryInterface(
  441.                         pdev, &IID_IDirectInputDevice2, (LPVOID *)&pdev2);
  442.  
  443.         if (SUCCEEDED(hres)) {
  444.             /*
  445.              *  Enumerate the effects and add them to the listview.
  446.              */
  447.             IDirectInputDevice2_EnumEffects(pdev2,
  448.                                             DIEnumEffCallback, lpInfo,
  449.                                             DIEFT_ALL);
  450.  
  451.             IDirectInputDevice2_Release(pdev2);
  452.         }
  453.  
  454.         IDirectInputDevice_Release(pdev);
  455.     }
  456.  
  457.     return fRc;
  458. }
  459.  
  460. /****************************************************************************
  461.  *
  462.  *  DIAddEffects
  463.  *
  464.  *      lParam1 = state info recorded by DIEnumDevCallback (LPGUID)
  465.  *      lParam2 = refdata (not used)
  466.  *
  467.  ****************************************************************************/
  468.  
  469. void
  470. DIAddEffects(LPARAM lParam1, LPARAM lParam2)
  471. {
  472.     DIPrintEffects(lParam1, lParam2, NULL);
  473. }
  474.  
  475. /****************************************************************************
  476.  ***************************************************************************/
  477.  
  478. CAPDEFS DICapDefs[] =
  479. {
  480.     {"",                    DIAddCaps,          0,              DIPrintCaps},
  481.     {"Effects",             DIAddEffects,       0,              DIPrintEffects},
  482.     {NULL, 0, 0, NULL}
  483. };
  484.  
  485. /****************************************************************************
  486.  *
  487.  *  DIEnumDevCallback
  488.  *
  489.  *  Add the enumerated DirectInput device to the treeview.
  490.  *
  491.  ****************************************************************************/
  492.  
  493. BOOL CALLBACK
  494. DIEnumDevCallback(LPCDIDEVICEINSTANCE pinst, LPVOID pv)
  495. {
  496.     HTREEITEM hParent = pv;
  497.     TCHAR     szText[MAX_PATH + 2 + MAX_PATH + 2];
  498.     LPGUID    pguid;
  499.  
  500.     pguid = LocalAlloc(LPTR, sizeof(GUID));
  501.     if (pguid == NULL) {
  502.         return DIENUM_STOP;
  503.     }
  504.  
  505.     *pguid = pinst->guidInstance;
  506.  
  507.     wsprintf(szText, "%s (%s)", pinst->tszInstanceName,
  508.                                 pinst->tszProductName);
  509.  
  510.     DICapDefs[0].szName = szText;
  511.     AddCapsToTV(hParent, DICapDefs, (LPARAM)pguid);
  512.  
  513.     return(DIENUM_CONTINUE);
  514. }
  515.  
  516. /****************************************************************************
  517.  *
  518.  *  DI_FillTree
  519.  *
  520.  *  Add the DirectInput nodes to the treeview.
  521.  *
  522.  ****************************************************************************/
  523.  
  524. void
  525. DI_FillTree(void)
  526. {
  527.     LPDIRECTINPUT pdi;
  528.     HTREEITEM hTree;
  529.  
  530.     // Add direct input devices if DInput is found
  531.  
  532.     pdi = DI_CreateDI();
  533.     if (pdi) {
  534.  
  535.         hTree = TVAddNode(TVI_ROOT, "DirectInput Devices", TRUE,
  536.                           IDI_DIRECTX, NULL, 0, 0, NULL);
  537.  
  538.         IDirectInput_EnumDevices(pdi, 0, DIEnumDevCallback, hTree,
  539.                                  DIEDFL_ALLDEVICES);
  540.  
  541.         TreeView_Expand(g_hwndTV, hTree, TVE_EXPAND);
  542.  
  543.         IDirectInput_Release(pdi);
  544.     }
  545. }
  546.