home *** CD-ROM | disk | FTP | other *** search
/ Beginning Direct3D Game Programming / Direct3D.iso / directx / dxf / samples / multimedia / directinput / diconfig / useful.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-11  |  13.7 KB  |  654 lines

  1. //-----------------------------------------------------------------------------
  2. // File: useful.cpp
  3. //
  4. // Desc: Contains various utility classes and functions to help the
  5. //       UI carry its operations more easily.
  6. //
  7. // Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  8. //-----------------------------------------------------------------------------
  9.  
  10. #include <windows.h>
  11. #include <tchar.h>
  12. #include <wchar.h>
  13. #include <stdio.h>
  14. #include <stdarg.h>
  15.  
  16. // assert include (make sure assert actually works with build)
  17. #ifdef DBG
  18. #undef NDEBUG
  19. #endif
  20. #include <assert.h>
  21.  
  22. #include "useful.h"
  23. #include "collections.h"
  24.  
  25.  
  26. /*--------- \/ stuff for collections.h \/ ---------*/
  27. BOOL AfxIsValidAddress( const void* lp, UINT nBytes, BOOL bReadWrite)
  28. {
  29. //    return lp != NULL;
  30.  
  31.     // simple version using Win-32 APIs for pointer validation.
  32.     return (lp != NULL && !IsBadReadPtr(lp, nBytes) &&
  33.         (!bReadWrite || !IsBadWritePtr((LPVOID)lp, nBytes)));
  34. }
  35.  
  36. CPlex* PASCAL CPlex::Create(CPlex*& pHead, UINT nMax, UINT cbElement)
  37. {
  38.     assert(nMax > 0 && cbElement > 0);
  39.     CPlex* p = (CPlex*) new BYTE[sizeof(CPlex) + nMax * cbElement];
  40.             // may throw exception
  41.     p->pNext = pHead;
  42.     pHead = p;  // change head (adds in reverse order for simplicity)
  43.     return p;
  44. }
  45.  
  46. void CPlex::FreeDataChain()     // free this one and links
  47. {
  48.     CPlex* p = this;
  49.     while (p != NULL)
  50.     {
  51.         BYTE* bytes = (BYTE*) p;
  52.         CPlex* pNext = p->pNext;
  53.         delete[] bytes;
  54.         p = pNext;
  55.     }
  56. }
  57. /*--------- /\ stuff for collections.h /\ ---------*/
  58.  
  59.  
  60. int ConvertVal(int x, int a1, int a2, int b1, int b2)
  61. {
  62.     assert(a1 != a2 && a2 - a1);
  63.     return MulDiv(x - a1, b2 - b1, a2 - a1) + b1;
  64. }
  65.  
  66. double dConvertVal(double x, double a1, double a2, double b1, double b2)
  67. {
  68.     assert(a1 != a2 && a2 - a1);
  69.     return (x - a1) * (b2 - b1) / (a2 - a1) + b1;
  70. }
  71.  
  72. SIZE GetRectSize(const RECT &rect)
  73. {
  74.     SIZE size = {
  75.         rect.right - rect.left,
  76.         rect.bottom - rect.top};
  77.     return size;
  78. }
  79.  
  80. SIZE GetTextSize(LPCTSTR tszText, HFONT hFont)
  81. {
  82.     if (!tszText)
  83.     {
  84.         SIZE z = {0, 0};
  85.         return z;
  86.     }
  87.     RECT trect = {0, 0, 1, 1};
  88.     HDC hDC = CreateCompatibleDC(NULL);
  89.     if (hDC != NULL)
  90.     {
  91.         HGDIOBJ hOld = NULL;
  92.         if (hFont)
  93.             hOld = SelectObject(hDC, hFont);
  94.         DrawText(hDC, tszText, -1, &trect, DT_CALCRECT | DT_NOPREFIX);
  95.         if (hFont)
  96.             SelectObject(hDC, hOld);
  97.         DeleteDC(hDC);
  98.     }
  99.     SIZE size = {trect.right - trect.left, trect.bottom - trect.top};
  100.     return size;
  101. }
  102.  
  103. int GetTextHeight(HFONT hFont)
  104. {
  105.     static const TCHAR str[] = _T("Happy Test!  :D");
  106.     SIZE size = GetTextSize(str, hFont);
  107.     return size.cy;
  108. }
  109.  
  110. int vFormattedMsgBox(HINSTANCE hInstance, HWND hParent, UINT uType, UINT uTitle, UINT uMsg, va_list args)
  111. {
  112.     int i;
  113.     const int len = 1024;
  114.     static TCHAR title[len], format[len], msg[len];
  115.  
  116.     if (!LoadString(hInstance, uTitle, title, len))
  117.         _tcscpy(title, _T("(could not load title string)"));
  118.     
  119.     if (!LoadString(hInstance, uMsg, format, len))
  120.         return MessageBox(hParent, _T("(could not load message/format string)"), title, uType);
  121.  
  122. #ifdef WIN95
  123.     {
  124.         char *psz = NULL;
  125.         char szDfs[1024]={0};
  126.         strcpy(szDfs,format);                            // make a local copy of format string
  127.         while (psz = strstr(szDfs,"%p"))                // find each %p
  128.             *(psz+1) = 'x';                                // replace each %p with %x
  129.         i = _vsntprintf(msg, len, szDfs, args);            // use the local format string
  130.     }
  131. #else
  132.     {
  133.         i = _vsntprintf(msg, len, format, args);
  134.     }
  135. #endif
  136.  
  137.     if (i < 0)
  138.         return MessageBox(hParent, _T("(could not format message)"), title, uType);
  139.  
  140.     if (i < 1)
  141.         msg[0] = 0;
  142.  
  143.     return MessageBox(hParent, msg, title, uType);
  144. }
  145.  
  146. int FormattedMsgBox(HINSTANCE hInstance, HWND hParent, UINT uType, UINT uTitle, UINT uMsg, ...)
  147. {
  148.     va_list args;
  149.     va_start(args, uMsg);
  150.     int i = vFormattedMsgBox(hInstance, hParent, uType, uTitle, uMsg, args);
  151.     va_end(args);
  152.     return i;
  153. }
  154.  
  155. BOOL UserConfirm(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, ...)
  156. {
  157.     va_list args;
  158.     va_start(args, uMsg);
  159.     int i = vFormattedMsgBox(hInstance, hParent, MB_ICONQUESTION | MB_YESNO, uTitle, uMsg, args);
  160.     va_end(args);
  161.     return i == IDYES;
  162. }
  163.  
  164. int FormattedErrorBox(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, ...)
  165. {
  166.     va_list args;
  167.     va_start(args, uMsg);
  168.     int i = vFormattedMsgBox(hInstance, hParent, MB_OK | MB_ICONSTOP, uTitle, uMsg, args);
  169.     va_end(args);
  170.     return i;
  171. }
  172.  
  173. int FormattedLastErrorBox(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, DWORD dwError)
  174. {
  175.     // format an error message from GetLastError().
  176.     LPVOID lpMsgBuf = NULL;
  177.     DWORD result = FormatMessage(
  178.         FORMAT_MESSAGE_ALLOCATE_BUFFER |
  179.         FORMAT_MESSAGE_FROM_SYSTEM |
  180.         FORMAT_MESSAGE_IGNORE_INSERTS,
  181.         NULL,
  182.         dwError,
  183.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  184.         (LPTSTR) &lpMsgBuf,
  185.         0,
  186.         NULL);
  187.  
  188.     if (!result || lpMsgBuf == NULL)
  189.         return FormattedErrorBox(hInstance, hParent, uTitle, uMsg, 
  190.             _T("An unknown error occured (could not format the error code)."));
  191.  
  192.     int i = FormattedErrorBox(hInstance, hParent, uTitle, uMsg, (LPCTSTR)lpMsgBuf);
  193.  
  194.     LocalFree(lpMsgBuf);
  195.  
  196.     return i;
  197. }
  198.  
  199. LPTSTR AllocLPTSTR(LPCWSTR wstr)
  200. {
  201.     if (wstr == NULL)
  202.         return NULL;
  203.  
  204. #ifdef UNICODE
  205.     return _tcsdup(wstr);
  206. #else
  207.     int len = wcslen(wstr) * 2 + 1;
  208.     char *ret = (char *)malloc(len);
  209.     if (!ret)
  210.         return NULL;
  211.     WideCharToMultiByte(CP_ACP, 0, wstr, -1, ret, len, NULL, NULL);
  212.     ret[len-1] = '\0';
  213.     return ret;
  214. #endif
  215. }
  216.  
  217. LPTSTR AllocLPTSTR(LPCSTR str)
  218. {
  219.     if (str == NULL)
  220.         return NULL;
  221.  
  222. #ifndef UNICODE
  223.     return _tcsdup(str);
  224. #else
  225.     int len = strlen(str);
  226.     WCHAR *ret = (WCHAR *)malloc((len + 1) * sizeof(WCHAR));
  227.     if (!ret)
  228.         return NULL;
  229.     mbstowcs(ret, str, len);
  230.     ret[len] = L'\0';
  231.     return ret;
  232. #endif
  233. }
  234.  
  235. void CopyStr(LPWSTR dest, LPCWSTR src, size_t max)
  236. {
  237.     if (dest == NULL || src == NULL)
  238.         return;
  239.  
  240.     wcsncpy(dest, src, max);
  241. }
  242.  
  243. void CopyStr(LPSTR dest, LPCSTR src, size_t max)
  244. {
  245.     if (dest == NULL || src == NULL)
  246.         return;
  247.  
  248.     strncpy(dest, src, max);
  249. }
  250.  
  251. void CopyStr(LPWSTR dest, LPCSTR src, size_t max)
  252. {
  253.     if (dest == NULL || src == NULL)
  254.         return;
  255.  
  256.     mbstowcs(dest, src, max);
  257. }
  258.  
  259. void CopyStr(LPSTR dest, LPCWSTR src, size_t max)
  260. {
  261.     if (dest == NULL || src == NULL)
  262.         return;
  263.  
  264.     WideCharToMultiByte(CP_ACP, 0, src, -1, dest, max, NULL, NULL);
  265. }
  266.  
  267. LPWSTR AllocLPWSTR(LPCWSTR wstr)
  268. {
  269.     if (wstr == NULL)
  270.         return NULL;
  271.  
  272.     return _wcsdup(wstr);
  273. }
  274.  
  275. LPWSTR AllocLPWSTR(LPCSTR str)
  276. {
  277.     if (str == NULL)
  278.         return NULL;
  279.  
  280.     size_t len = strlen(str);
  281.     size_t retsize = mbstowcs(NULL, str, len);
  282.     WCHAR *ret = (WCHAR *)malloc((retsize + 1) * sizeof(WCHAR));
  283.     if (!ret)
  284.         return NULL;
  285.     mbstowcs(ret, str, len);
  286.     ret[retsize] = L'\0';
  287.     return ret;
  288. }
  289.  
  290. LPSTR AllocLPSTR(LPCWSTR wstr)
  291. {
  292.     if (wstr == NULL)
  293.         return NULL;
  294.  
  295.     size_t len = wcslen(wstr);
  296.     size_t retsize = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
  297.     CHAR *ret = (CHAR *)malloc((retsize + 1) * sizeof(CHAR));
  298.     if (!ret)
  299.         return NULL;
  300.     WideCharToMultiByte(CP_ACP, 0, wstr, -1, ret, retsize, NULL, NULL);
  301.     ret[retsize] = '\0';
  302.     return ret;
  303. }
  304.  
  305. LPSTR AllocLPSTR(LPCSTR str)
  306. {
  307.     if (str == NULL)
  308.         return NULL;
  309.  
  310.     return _strdup(str);
  311. }
  312.  
  313. LPTSTR AllocFileNameNoPath(LPTSTR path)
  314. {
  315.     TCHAR fname[_MAX_FNAME];
  316.     TCHAR ext[_MAX_EXT];
  317.  
  318.     assert(path != NULL);
  319.  
  320.     _tsplitpath(path, NULL, NULL, fname, ext);
  321.  
  322.     LPTSTR ret = (LPTSTR)malloc(sizeof(TCHAR) * (_tcslen(fname) + _tcslen(ext) + 1));
  323.     if (ret != NULL)
  324.     {
  325.         _tcscpy(ret, fname);
  326.         _tcscat(ret, ext);
  327.     }
  328.  
  329.     return ret;
  330. }
  331.  
  332. LPTSTR utilstr::Eject()
  333. {
  334.     LPTSTR str = m_str;
  335.     m_str = NULL;
  336.     m_len = 0;
  337.     return str;
  338. }
  339.  
  340. void utilstr::Empty()
  341. {
  342.     if (m_str != NULL)
  343.         free(m_str);
  344.     m_len = 0;
  345. }
  346.  
  347. bool utilstr::IsEmpty() const
  348. {
  349.     return !GetLength();
  350. }
  351.  
  352. int utilstr::GetLength() const
  353. {
  354.     if (m_str == NULL)
  355.         return 0;
  356.     if (!m_len)
  357.         return 0;
  358.  
  359.     return _tcslen(m_str);
  360. }
  361.  
  362. void utilstr::Format(LPCTSTR format, ...)
  363. {
  364.     static TCHAR buf[2048];
  365.     va_list args;
  366.     va_start(args, format);
  367. #ifdef WIN95
  368.     {
  369.         char *psz = NULL;
  370.         char szDfs[1024]={0};
  371.         strcpy(szDfs,format);  // make a local copy of format string
  372.         while (psz = strstr(szDfs,"%p"))  // find each %p
  373.             *(psz+1) = 'x';  // replace each %p with %x
  374.         _vstprintf(buf, szDfs, args);  // use the local format string
  375.     }
  376. #else
  377.     {
  378.         _vstprintf(buf, format, args);
  379.     }
  380. #endif
  381.     va_end(args);
  382.     equal(buf);
  383. }
  384.  
  385. void utilstr::equal(LPCTSTR str)
  386. {
  387.     Empty();
  388.     if (str == NULL)
  389.         return;
  390.     m_len = _tcslen(str);
  391.     m_str = (LPTSTR)malloc(sizeof(TCHAR) * (m_len + 1));
  392.     if (m_str != NULL)
  393.         _tcscpy(m_str, str);
  394.     else
  395.         m_len = 0;
  396. }
  397.  
  398. void utilstr::add(LPCTSTR str)
  399. {
  400.     if (str == NULL)
  401.         return;
  402.     if (IsEmpty())
  403.     {
  404.         equal(str);
  405.         return;
  406.     }
  407.     int len = _tcslen(str);
  408.     int newlen = m_len + len;
  409.     LPTSTR newstr = (LPTSTR)malloc(sizeof(TCHAR) * (newlen + 1));
  410.     if (newstr == NULL)
  411.         return;
  412.     _tcscpy(newstr, m_str);
  413.     _tcscat(newstr, str);
  414.     Empty();
  415.     m_str = newstr;
  416.     m_len = newlen;
  417. }
  418.  
  419. LPTSTR AllocFlagStr(DWORD value, const AFS_FLAG flag[], int flags)
  420. {
  421.     utilstr ret;    // return string
  422.     DWORD allknownbits = 0;  // check value to see if there are any bits
  423.                              // set for which we don't have a define
  424.  
  425.     // handle each flag
  426.     bool bflagfound = false;
  427.     for (int i = 0; i < flags; i++)
  428.     {
  429.         // set bit for this flag in allknownbits
  430.         allknownbits |= flag[i].value;
  431.  
  432.         // if this bit is set in the passed value, or the value
  433.         // is zero and we're on the zero flag,
  434.         // add the define for this bit/flag to the return string
  435.         if (value ? value & flag[i].value : !flag[i].value)
  436.         {
  437.             // adding binary or operators between flags
  438.             if (bflagfound)
  439.                 ret += _T(" | ");
  440.             ret += flag[i].name;
  441.             bflagfound = true;
  442.         }
  443.     }
  444.  
  445.     // now see if there are any unknown bits in passed flag
  446.     DWORD unknownbits = value & ~allknownbits;
  447.     if (unknownbits)
  448.     {
  449.         // add hex number for unknown bits
  450.         utilstr unk;
  451.         unk.Format(_T("0x%08X"), unknownbits);
  452.         if (bflagfound)
  453.             ret += _T(" | ");
  454.         ret += unk;
  455.     }
  456.  
  457.     // if value is zero (and no flags for zero) we should just set the string to "0"
  458.     if (!value && !bflagfound)
  459.         ret = _T("0");
  460.  
  461.     // now the string should definitely not be empty, in any case
  462.     assert(!ret.IsEmpty());
  463.  
  464.     // finally, add a comment that has hex number for entire value
  465.     // (for debugging)
  466.     utilstr temp;
  467.     temp.Format(_T(" /* 0x%08X */"), value);
  468.     ret += temp;
  469.  
  470.     // done
  471.     return ret.Eject();
  472. }
  473.  
  474. void PutLinePoint(HDC hDC, POINT p)
  475. {
  476.     MoveToEx(hDC, p.x, p.y, NULL);
  477.     LineTo(hDC, p.x + 1, p.y);
  478. }
  479.  
  480. void PolyLineArrowShadow(HDC hDC, POINT *p, int i)
  481. {
  482.     PolyLineArrow(hDC, p, i, TRUE);
  483. }
  484.  
  485. void PolyLineArrow(HDC hDC, POINT *rgpt, int nPoints, BOOL bDoShadow)
  486. {
  487.     int i;
  488.  
  489.     if (rgpt == NULL || nPoints < 1)
  490.         return;
  491.  
  492.     if (nPoints > 1)
  493.         for (i = 0; i < nPoints - 1; i++)
  494.         {
  495.             SPOINT a = rgpt[i], b = rgpt[i + 1];
  496.  
  497.             if (bDoShadow)
  498.             {
  499.                 int rise = abs(b.y - a.y), run = abs(b.x - a.x);
  500.                 bool vert = rise > run;
  501.                 int ord = vert ? 1 : 0;
  502.                 int nord = vert ? 0 : 1;
  503.                 
  504.                 for (int o = -1; o <= 1; o += 2)
  505.                 {
  506.                     SPOINT c(a), d(b);
  507.                     c.a[nord] += o;
  508.                     d.a[nord] += o;
  509.                     MoveToEx(hDC, c.x, c.y, NULL);
  510.                     LineTo(hDC, d.x, d.y);
  511.                 }
  512.  
  513.                 bool reverse = a.a[ord] > b.a[ord];
  514.                 SPOINT e(reverse ? b : a), f(reverse ? a : b);
  515.                 e.a[ord] -= 1;
  516.                 f.a[ord] += 1;
  517.                 PutLinePoint(hDC, e);
  518.                 PutLinePoint(hDC, f);
  519.             }
  520.             else
  521.             {
  522.                 MoveToEx(hDC, a.x, a.y, NULL);
  523.                 LineTo(hDC, b.x, b.y);
  524.             }
  525.         }
  526.  
  527.     POINT z = rgpt[nPoints - 1];
  528.  
  529.     if (bDoShadow)
  530.     {
  531.         POINT pt[5] = {
  532.             {z.x, z.y + 2},
  533.             {z.x + 2, z.y},
  534.             {z.x, z.y - 2},
  535.             {z.x - 2, z.y}, };
  536.         pt[4] = pt[0];
  537.         Polyline(hDC, pt, 5);
  538.     }
  539.     else
  540.     {
  541.         MoveToEx(hDC, z.x - 1, z.y, NULL);
  542.         LineTo(hDC, z.x + 2, z.y);
  543.         MoveToEx(hDC, z.x, z.y - 1, NULL);
  544.         LineTo(hDC, z.x, z.y + 2);
  545.     }
  546. }
  547.  
  548. BOOL bEq(BOOL a, BOOL b)
  549. {
  550.     bool c = !a, d = !b;
  551.     return (c == d) ? TRUE : FALSE;
  552. }
  553.  
  554. void DrawArrow(HDC hDC, const RECT &rect, BOOL bVert, BOOL bUpLeft)
  555. {
  556.     SRECT srect = rect;
  557.     srect.right--;
  558.     srect.bottom--;
  559.     int ord = bVert ? 1 : 0;
  560.     int nord = bVert ? 0 : 1;
  561.     SPOINT p(!bUpLeft ? srect.lr : srect.ul), b(!bUpLeft ? srect.ul : srect.lr);
  562.     b.a[ord] += bUpLeft ? -1 : 1;
  563.     SPOINT t = p;
  564.     t.a[nord] = (p.a[nord] + b.a[nord]) / 2;
  565.     SPOINT u;
  566.     u.a[ord] = b.a[ord];
  567.     u.a[nord] = p.a[nord];
  568.     POINT poly[] = { {t.x, t.y}, {u.x, u.y}, {b.x, b.y} };
  569.     Polygon(hDC, poly, 3);
  570. }
  571.  
  572. BOOL ScreenToClient(HWND hWnd, LPRECT rect)
  573. {
  574.     if (rect == NULL)
  575.         return FALSE;
  576.  
  577.     SRECT sr = *rect;
  578.  
  579.     if (ScreenToClient(hWnd, &sr.ul.p) &&
  580.         ScreenToClient(hWnd, &sr.lr.p))
  581.     {
  582.         *rect = sr;
  583.         return TRUE;
  584.     }
  585.  
  586.     return FALSE;
  587. }
  588.  
  589. BOOL ClientToScreen(HWND hWnd, LPRECT rect)
  590. {
  591.     if (rect == NULL)
  592.         return FALSE;
  593.  
  594.     SRECT sr = *rect;
  595.  
  596.     if (ClientToScreen(hWnd, &sr.ul.p) &&
  597.         ClientToScreen(hWnd, &sr.lr.p))
  598.     {
  599.         *rect = sr;
  600.         return TRUE;
  601.     }
  602.  
  603.     return FALSE;
  604. }
  605.  
  606. #define z ((L"\0")[0])
  607.  
  608. int StrLen(LPCWSTR s)
  609. {
  610.     if (s == NULL)
  611.         return 0;
  612.  
  613.     return wcslen(s);
  614. }
  615.  
  616. int StrLen(LPCSTR s)
  617. {
  618.     if (s == NULL)
  619.         return 0;
  620.  
  621.     return strlen(s);
  622. }
  623.  
  624. LPCTSTR GetOpenFileName(HINSTANCE hInst, HWND hWnd, LPCTSTR title, LPCTSTR filter, LPCTSTR defext, LPCTSTR inidir)
  625. {
  626.     OPENFILENAME ofn;
  627.     static TCHAR tszFile[MAX_PATH + 1] = _T("");
  628.     tszFile[MAX_PATH] = 0;
  629.  
  630.     ofn.lStructSize = sizeof(OPENFILENAME);
  631.     ofn.hwndOwner = hWnd;
  632.     ofn.hInstance = hInst;
  633.     ofn.lpstrFilter = filter;
  634.     ofn.lpstrCustomFilter = NULL;
  635.     ofn.nMaxCustFilter = 0;
  636.     ofn.nFilterIndex = 0;
  637.     ofn.lpstrFile = tszFile;
  638.     ofn.nMaxFile = MAX_PATH;
  639.     ofn.lpstrFileTitle = NULL;
  640.     ofn.nMaxFileTitle = 0;
  641.     ofn.lpstrInitialDir = inidir;
  642.     ofn.lpstrTitle = title;
  643.     ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
  644.     ofn.lpstrDefExt = defext;
  645.     ofn.lCustData = NULL;
  646.     ofn.lpfnHook = NULL;
  647.     ofn.lpTemplateName = NULL;
  648.  
  649.     if (!GetOpenFileName(&ofn))
  650.         return NULL;
  651.  
  652.     return tszFile;
  653. }
  654.