home *** CD-ROM | disk | FTP | other *** search
/ Beginning Direct3D Game Programming / Direct3D.iso / directx / dxf / samples / multimedia / directinput / diconfig / usefuldi.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-22  |  8.7 KB  |  348 lines

  1. //-----------------------------------------------------------------------------
  2. // File: usefuldi.cpp
  3. //
  4. // Desc: Contains various DInput-specific utility classes and functions
  5. //       to help the UI carry its operations more easily.
  6. //
  7. // Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9.  
  10. #include "common.hpp"
  11.  
  12. // don't want useful.cpp to use precompiled header
  13. #include "useful.cpp"
  14.  
  15.  
  16. BOOL IsObjectOnExcludeList(DWORD dwOfs)
  17. {
  18.     if (dwOfs == DIK_PREVTRACK ||
  19.         dwOfs == DIK_NEXTTRACK ||
  20.         dwOfs == DIK_MUTE ||
  21.         dwOfs == DIK_CALCULATOR ||
  22.         dwOfs == DIK_PLAYPAUSE ||
  23.         dwOfs == DIK_MEDIASTOP ||
  24.         dwOfs == DIK_VOLUMEDOWN ||
  25.         dwOfs == DIK_VOLUMEUP ||
  26.         dwOfs == DIK_WEBHOME ||
  27.         dwOfs == DIK_SLEEP ||
  28.         dwOfs == DIK_WEBSEARCH ||
  29.         dwOfs == DIK_WEBFAVORITES ||
  30.         dwOfs == DIK_WEBREFRESH ||
  31.         dwOfs == DIK_WEBSTOP ||
  32.         dwOfs == DIK_WEBFORWARD ||
  33.         dwOfs == DIK_WEBBACK ||
  34.         dwOfs == DIK_MYCOMPUTER ||
  35.         dwOfs == DIK_MAIL ||
  36.         dwOfs == DIK_MEDIASELECT)
  37.         return TRUE;
  38.  
  39.     return FALSE;
  40. }
  41.  
  42. BOOL CALLBACK IncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  43. {
  44.     if (pvRef != NULL)
  45.         ++(*((int *)pvRef));
  46.     return DIENUM_CONTINUE;
  47. }
  48.  
  49. BOOL CALLBACK KeyboardIncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  50. {
  51.     if (pvRef != NULL && !IsObjectOnExcludeList(lpddoi->dwOfs))
  52.         ++(*((int *)pvRef));
  53.     return DIENUM_CONTINUE;
  54. }
  55.  
  56. BOOL CALLBACK FillDIDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  57. {
  58.     if (pvRef == NULL || lpddoi == NULL)
  59.         return DIENUM_CONTINUE;
  60.  
  61.     DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
  62.     assert(os.pdoi != NULL);
  63.     assert(os.n < os.nObjects);
  64.     if (os.pdoi != NULL && os.n < os.nObjects)
  65.         os.pdoi[os.n++] = *lpddoi;
  66.  
  67.     return DIENUM_CONTINUE;
  68. }
  69.  
  70. // This is a special EnumObjects() callback for keyboard type devices.  When we enumerate, dwOfs
  71. // member of lpddoi is meaningless.  We need to take the middle 16 bits of dwType as dwOfs
  72. // (also same as DIK_xxx).
  73. BOOL CALLBACK FillDIKeyboardDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
  74. {
  75.     if (pvRef == NULL || lpddoi == NULL || IsObjectOnExcludeList(lpddoi->dwOfs))
  76.         return DIENUM_CONTINUE;
  77.  
  78.     DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
  79.     assert(os.pdoi != NULL);
  80.     assert(os.n < os.nObjects);
  81.     if (os.pdoi != NULL && os.n < os.nObjects)
  82.     {
  83.         os.pdoi[os.n] = *lpddoi;
  84.         os.pdoi[os.n].dwOfs = os.pdoi[os.n].dwType >> 8;
  85.         ++os.n;
  86.     }
  87.  
  88.     return DIENUM_CONTINUE;
  89. }
  90.  
  91. HRESULT FillDIDeviceObjectStruct(DIDEVOBJSTRUCT &os, LPDIRECTINPUTDEVICE8W pDID)
  92. {
  93.     if (pDID == NULL)
  94.         return E_FAIL;
  95.  
  96.     DIDEVICEINSTANCEW didi;
  97.     didi.dwSize = sizeof(didi);
  98.     pDID->GetDeviceInfo(&didi);
  99.  
  100.     HRESULT hr;
  101.     if (LOBYTE(didi.dwDevType) == DI8DEVTYPE_KEYBOARD)
  102.         hr = pDID->EnumObjects(KeyboardIncrementValPerObject, &os.nObjects,
  103.             DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  104.     else
  105.         hr = pDID->EnumObjects(IncrementValPerObject, &os.nObjects,
  106.             DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  107.     if (FAILED(hr))
  108.     {
  109.         os.nObjects = 0;
  110.         return hr;
  111.     }
  112.     
  113.     if (os.nObjects == 0)
  114.         return S_OK;
  115.  
  116.     if (os.pdoi != NULL)
  117.         free(os.pdoi);
  118.     os.pdoi = (DIDEVICEOBJECTINSTANCEW *)malloc(sizeof(DIDEVICEOBJECTINSTANCEW) * os.nObjects);
  119.     if (os.pdoi == NULL)
  120.     {
  121.         os.nObjects = 0;
  122.         return E_FAIL;
  123.     }
  124.  
  125.     // Check if this device is a keyboard. If so, it needs special treatment.
  126.     os.n = 0;
  127.     if ((didi.dwDevType & 0xFF) == DI8DEVTYPE_KEYBOARD)
  128.     {
  129.         hr = pDID->EnumObjects(FillDIKeyboardDeviceObject, &os,
  130.             DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  131.         // Here we initialize the object names to that returned by GetProperty() using DIPROP_KEYNAME.
  132.         for (int i = 0; i < os.n; ++i)
  133.         {
  134.             DIPROPSTRING dips;
  135.             dips.diph.dwSize = sizeof(DIPROPSTRING);
  136.             dips.diph.dwHeaderSize = sizeof(DIPROPHEADER);
  137.             dips.diph.dwObj = os.pdoi[i].dwType;
  138.             dips.diph.dwHow = DIPH_BYID;
  139.             pDID->GetProperty(DIPROP_KEYNAME, &dips.diph);
  140.             wcscpy(os.pdoi[i].tszName, dips.wsz);
  141.         }
  142.     }
  143.     else
  144.         hr = pDID->EnumObjects(FillDIDeviceObject, &os,
  145.             DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
  146.     if (FAILED(hr))
  147.     {
  148.         os.nObjects = 0;
  149.         return hr;
  150.     }
  151.     assert(os.nObjects == os.n);
  152.     os.nObjects = os.n;
  153.  
  154.     return S_OK;
  155. }
  156.  
  157. LPTSTR AllocConfigureFlagStr(DWORD dwFlags)
  158. {
  159.     static const AFS_FLAG flag[] = {
  160. #define f(F) { F, _T(#F) }
  161.         f(DICD_EDIT), f(DICD_DEFAULT)
  162. #undef f
  163.     };
  164.     static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
  165.     return AllocFlagStr(dwFlags, flag, flags);
  166. }
  167.  
  168. LPTSTR AllocActionFlagStr(DWORD dwFlags)
  169. {
  170.     static const AFS_FLAG flag[] = {
  171. #define f(F) { F, _T(#F) }
  172.         f(DIA_FORCEFEEDBACK),
  173.         f(DIA_APPMAPPED),
  174.         f(DIA_APPNOMAP),
  175.         f(DIA_NORANGE),
  176. #undef f
  177.     }; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
  178.     return AllocFlagStr(dwFlags, flag, flags);
  179. }
  180.  
  181. LPTSTR AllocActionHowFlagStr(DWORD dwFlags)
  182. {
  183.     static const AFS_FLAG flag[] = {
  184. #define f(F) { F, _T(#F) }
  185.         f(DIAH_UNMAPPED),
  186.         f(DIAH_USERCONFIG),
  187.         f(DIAH_APPREQUESTED),
  188.         f(DIAH_HWAPP),
  189.         f(DIAH_HWDEFAULT),
  190.         f(DIAH_DEFAULT),
  191.         f(DIAH_ERROR)
  192. #undef f
  193.     }; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
  194.     return AllocFlagStr(dwFlags, flag, flags);
  195. }
  196.  
  197. void CleanupActionFormatCopy(DIACTIONFORMATW &c)
  198. {
  199.     if (c.rgoAction != NULL)
  200.     {
  201.         for (DWORD i = 0; i < c.dwNumActions; i++)
  202.             if (c.rgoAction[i].lptszActionName != NULL)
  203.                 free((LPTSTR)c.rgoAction[i].lptszActionName);
  204.         free(c.rgoAction);
  205.     }
  206.     c.rgoAction = NULL;
  207. }
  208.  
  209. HRESULT CopyActionFormat(DIACTIONFORMATW &to, const DIACTIONFORMATW &from)
  210. {
  211.     DWORD i;
  212.  
  213.     // copy all simple members
  214.     to = from;
  215.  
  216.     // null copied pointers since we're going to duplicate them (makes sure cleanup works)
  217.     to.rgoAction = NULL;
  218.  
  219.     // handle pointers/arrays/strings
  220.     to.rgoAction = new DIACTIONW [to.dwNumActions];
  221.     if (to.rgoAction == NULL)
  222.         goto fail;
  223.  
  224.     // first null it all 
  225.     memset(to.rgoAction, 0, sizeof(DIACTIONW) * to.dwNumActions);
  226.  
  227.     // now copy...
  228.     for (i = 0; i < to.dwNumActions; i++)
  229.     {
  230.         // copy simple members
  231.         to.rgoAction[i] = from.rgoAction[i];
  232.  
  233.         // handle pointers/arrays/strings
  234.         to.rgoAction[i].lptszActionName = _wcsdup(from.rgoAction[i].lptszActionName);
  235.         if (to.rgoAction[i].lptszActionName == NULL)
  236.             goto fail;
  237.     }
  238.  
  239.     return S_OK;
  240. fail:
  241.     CleanupActionFormatCopy(to);
  242.     return E_OUTOFMEMORY;
  243. }
  244.  
  245. LPDIACTIONFORMATW DupActionFormat(LPCDIACTIONFORMATW lpAcFor)
  246. {
  247.     if (!lpAcFor)
  248.         return NULL;
  249.  
  250.     LPDIACTIONFORMATW pdup = new DIACTIONFORMATW;
  251.     if (!pdup)
  252.         return NULL;
  253.  
  254.     if (FAILED(CopyActionFormat(*pdup, *lpAcFor)))
  255.     {
  256.         delete pdup;
  257.         return NULL;
  258.     }
  259.  
  260.     return pdup;
  261. }
  262.  
  263. void FreeActionFormatDup(LPDIACTIONFORMATW &lpAcFor)
  264. {
  265.     if (!lpAcFor)
  266.         return;
  267.  
  268.     CleanupActionFormatCopy(*lpAcFor);
  269.     delete lpAcFor;
  270.     lpAcFor = NULL;
  271. }
  272.  
  273. void TraceActionFormat(LPTSTR header, const DIACTIONFORMATW &acf)
  274. {
  275. #ifdef CFGUI__TRACE_ACTION_FORMATS
  276.     tracescope(a, header);
  277.     trace(_T("\n"));
  278.  
  279.     traceDWORD(acf.dwSize);
  280.     traceDWORD(acf.dwActionSize);
  281.     traceDWORD(acf.dwDataSize);
  282.     traceDWORD(acf.dwNumActions);
  283.     {tracescope(b, _T("acf.rgoAction Array\n"));
  284.         for (DWORD i = 0; i < acf.dwNumActions; i++)
  285.         {
  286.             const DIACTIONW &a = acf.rgoAction[i];
  287.             static TCHAR buf[MAX_PATH];
  288.             _stprintf(buf, _T("Action %d\n"), i);
  289.             {tracescope(c, buf);
  290.                 traceHEX(a.uAppData);
  291.                 traceDWORD(a.dwSemantic);
  292.                 LPTSTR str = AllocActionFlagStr(a.dwFlags);
  293.                 trace1(_T("a.dwFlags = %s\n"), str);
  294.                 free(str);
  295.                 traceWSTR(a.lptszActionName);
  296.                 traceUINT(a.uResIdString);
  297.                 traceDWORD(a.dwObjID);
  298.                 traceGUID(a.guidInstance);
  299.                 str = AllocActionHowFlagStr(a.dwHow);
  300.                 trace1(_T("a.dwHow = %s\n"), str);
  301.                 free(str);
  302.             }
  303.         }
  304.     }
  305.     traceGUID(acf.guidActionMap);
  306.     traceDWORD(acf.dwGenre);
  307.     traceDWORD(acf.dwBufferSize);
  308.     traceLONG(acf.lAxisMin);
  309.     traceLONG(acf.lAxisMax);
  310.     traceHEX(acf.hInstString);
  311.     traceHEX(acf.dwCRC);
  312.     traceWSTR(acf.tszActionMap);
  313. #endif
  314. }
  315.  
  316. BOOL IsZeroOrInvalidColorSet(const DICOLORSET &cs)
  317. {
  318.     if (cs.dwSize < sizeof(DICOLORSET))
  319.         return TRUE;
  320.  
  321.     const int colors = 8;
  322.     D3DCOLOR color[colors] = {
  323.         cs.cTextFore,
  324.         cs.cTextHighlight,
  325.         cs.cCalloutLine,
  326.         cs.cCalloutHighlight,
  327.         cs.cBorder,
  328.         cs.cControlFill,
  329.         cs.cHighlightFill,
  330.         cs.cAreaFill
  331.     };
  332.  
  333.     for (int i = 0; i < colors; i++)
  334.         if (color[i])
  335.             return FALSE;
  336.  
  337.     return TRUE;
  338. }
  339.  
  340. // D3DCOLOR2COLORREF swaps the blue and red components since GDI and D3D store RGB in the opposite order.
  341. // It also removes the alpha component as the GDI doesn't use that, and including it causes incorrect color.
  342. COLORREF D3DCOLOR2COLORREF(D3DCOLOR c)
  343. {
  344.     LPBYTE pC = (LPBYTE)&c;
  345.  
  346.     return (COLORREF)((DWORD(*pC) << 16) + (DWORD(*(pC+1)) << 8) + DWORD(*(pC+2)));
  347. }
  348.