home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / mmcaps / zyztlb.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  16KB  |  725 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. //  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  5. //  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
  6. //  A PARTICULAR PURPOSE.
  7. //
  8. //  Copyright (C) 1993 - 1997 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. //  zyztlb.c
  13. //
  14. //  Description:
  15. //
  16. //
  17. //  History:
  18. //       5/18/93
  19. //
  20. //==========================================================================;
  21.  
  22. #include <windows.h>
  23. #include <windowsx.h>
  24. #include <stdlib.h>
  25.  
  26. #include "appport.h"
  27. #include "zyztlb.h"
  28.  
  29. #include "debug.h"
  30.  
  31.  
  32. //==========================================================================;
  33. //
  34. //
  35. //
  36. //
  37. //==========================================================================;
  38.  
  39. //--------------------------------------------------------------------------;
  40. //  
  41. //  int GetRealTextMetrics
  42. //  
  43. //  Description:
  44. //      This function gets the textmetrics of the font currently selected
  45. //      into the hdc.  It returns the average char width as the return value.
  46. //
  47. //      This function computes the average character width correctly by
  48. //      using GetTextExtent() on the string "abc...xzyABC...XYZ" which works
  49. //      out much better for proportional fonts. This is also necessary
  50. //      for correct alignment between dialog and client units.
  51. //
  52. //      Note that this function returns the same TEXTMETRIC values that
  53. //      GetTextMetrics() does, it simply has a different return value.
  54. //
  55. //  Arguments:
  56. //      HDC hdc:
  57. //  
  58. //      LPTEXTMETRIC ptm:
  59. //  
  60. //  Return (int):
  61. //  
  62. //  History:
  63. //      05/11/93
  64. //  
  65. //--------------------------------------------------------------------------;
  66.  
  67. int FNGLOBAL GetRealTextMetrics
  68. (
  69.     HDC             hdc,
  70.     LPTEXTMETRIC    ptm
  71. )
  72. {
  73.     TCHAR       achAlphabet[26 * 2];    // upper and lower case
  74.     SIZE        sSize;
  75.     UINT        u;
  76.     int         nAveWidth;
  77.  
  78.     //
  79.     //  get the text metrics of the current font. note that GetTextMetrics
  80.     //  gets the incorrect nAveCharWidth value for proportional fonts.
  81.     //
  82.     GetTextMetrics(hdc, ptm);
  83.     nAveWidth = ptm->tmAveCharWidth;
  84.  
  85.     //
  86.     //  if it's not a variable pitch font GetTextMetrics was correct
  87.     //  so just return.
  88.     //
  89.     if (ptm->tmPitchAndFamily & FIXED_PITCH)
  90.     {
  91.     //
  92.     //
  93.     //
  94.     for (u = 0; u < 26; u++)
  95.     {
  96.         achAlphabet[u]      = (TCHAR)(u + (UINT)'a');
  97.         achAlphabet[u + 26] = (TCHAR)(u + (UINT)'A');
  98.     }
  99.  
  100.     //
  101.     //  round up
  102.     //
  103.     GetTextExtentPoint(hdc, achAlphabet, SIZEOF(achAlphabet), &sSize);
  104.     nAveWidth = ((sSize.cx / 26) + 1) / 2;
  105.     }
  106.  
  107.     //
  108.     //  return the calculated average char width
  109.     //
  110.     return (nAveWidth);
  111. } // GetRealTextMetrics()
  112.  
  113.  
  114. //==========================================================================;
  115. //
  116. //
  117. //
  118. //
  119. //==========================================================================;
  120.  
  121. //--------------------------------------------------------------------------;
  122. //  
  123. //  BOOL TlbPaint
  124. //  
  125. //  Description:
  126. //  
  127. //  
  128. //  Arguments:
  129. //      PZYZTABBEDLISTBOX ptlb:
  130. //  
  131. //      HWND hwnd:
  132. //  
  133. //      HDC hdc:
  134. //  
  135. //  Return (BOOL):
  136. //  
  137. //  History:
  138. //      05/17/93
  139. //  
  140. //--------------------------------------------------------------------------;
  141.  
  142. BOOL FNGLOBAL TlbPaint
  143. (
  144.     PZYZTABBEDLISTBOX   ptlb,
  145.     HWND                hwnd,
  146.     HDC                 hdc
  147. )
  148. {
  149.     RECT        rc;
  150.     HFONT       hfont;
  151.     COLORREF    crBk;
  152.     COLORREF    crText;
  153.     int         nHeight;
  154.  
  155.     //
  156.     //
  157.     //
  158.     hfont = GetWindowFont(ptlb->hlb);
  159.     if (NULL == hfont)
  160.     hfont = GetStockFont(SYSTEM_FONT);
  161.  
  162.     hfont = SelectObject(hdc, hfont);
  163.  
  164.     crBk   = SetBkColor(hdc, GetSysColor(COLOR_ACTIVECAPTION));
  165.     crText = SetTextColor(hdc, GetSysColor(COLOR_CAPTIONTEXT));
  166.  
  167.     //
  168.     //  compute bounding rect for title only
  169.     //
  170.     rc = ptlb->rc;
  171.     nHeight = min(ptlb->nFontHeight, rc.bottom - rc.top);
  172.     rc.bottom = rc.top + nHeight;
  173.  
  174.     ExtTextOut(hdc, rc.left, rc.top, ETO_OPAQUE, &rc, NULL, 0, NULL);
  175.     TabbedTextOut(hdc, rc.left, rc.top,
  176.           ptlb->pszTitleText,
  177.           ptlb->cchTitleText,
  178.           ptlb->uTabStops,
  179.           ptlb->panTitleTabs, 0);
  180.  
  181.     //
  182.     //  restore the dc
  183.     //
  184.     SetBkColor(hdc, crBk);
  185.     SetTextColor(hdc, crText);
  186.  
  187.     SelectObject(hdc, hfont);
  188.  
  189.     return (TRUE);
  190. } // TlbPaint()
  191.  
  192.  
  193. //--------------------------------------------------------------------------;
  194. //  
  195. //  BOOL TlbMove
  196. //  
  197. //  Description:
  198. //  
  199. //  
  200. //  Arguments:
  201. //      PZYZTABBEDLISTBOX ptlb:
  202. //  
  203. //      PRECT prc:
  204. //  
  205. //      BOOL fRedraw:
  206. //  
  207. //  Return (BOOL):
  208. //  
  209. //  History:
  210. //      05/16/93
  211. //  
  212. //--------------------------------------------------------------------------;
  213.  
  214. BOOL FNGLOBAL TlbMove
  215. (
  216.     PZYZTABBEDLISTBOX   ptlb,
  217.     PRECT               prc,
  218.     BOOL                fRedraw
  219. )
  220. {
  221.     RECT        rc;
  222.     int         nHeight;
  223.     HWND        hwnd;
  224.  
  225.  
  226.     hwnd = GetParent(ptlb->hlb);
  227.  
  228.     //
  229.     //  invalidate only the region occupied by the current title bar. this
  230.     //  will make sure that area gets repainted. the listbox portion will
  231.     //  be invalidated correctly by the SetWindowPos() function below..
  232.     //
  233.     rc = ptlb->rc;
  234.  
  235.     nHeight = min(ptlb->nFontHeight, rc.bottom - rc.top);
  236.     rc.bottom = rc.top + nHeight;
  237.  
  238.     InvalidateRect(hwnd, &rc, TRUE);
  239.  
  240.  
  241.     //
  242.     //  now move the listbox--we modify values in the rect structure, so
  243.     //  copy to local storage
  244.     //
  245.     rc = *prc;
  246.  
  247.     //
  248.     //  leave room at the top of the bounding rect for the title text
  249.     //
  250.     nHeight = min(ptlb->nFontHeight, rc.bottom - rc.top);
  251.     rc.top += nHeight;
  252.  
  253.     SetWindowPos(ptlb->hlb, NULL, rc.left, rc.top, rc.right - rc.left,
  254.          rc.bottom - rc.top, SWP_NOZORDER);
  255.  
  256.     //
  257.     //  save the new location and invalidate the area so it is repainted
  258.     //
  259.     ptlb->rc = *prc;
  260.     InvalidateRect(hwnd, prc, TRUE);
  261.  
  262.     if (fRedraw)
  263.     {
  264.     UpdateWindow(hwnd);
  265.     }
  266.  
  267.     return (TRUE);
  268. } // TlbMove()
  269.  
  270.  
  271. //--------------------------------------------------------------------------;
  272. //  
  273. //  BOOL TlbRecalcTabs
  274. //  
  275. //  Description:
  276. //  
  277. //  
  278. //  Arguments:
  279. //      PZYZTABBEDLISTBOX ptlb:
  280. //  
  281. //  Return (BOOL):
  282. //  
  283. //  History:
  284. //      05/18/93
  285. //  
  286. //--------------------------------------------------------------------------;
  287.  
  288. BOOL FNLOCAL TlbRecalcTabs
  289. (
  290.     PZYZTABBEDLISTBOX   ptlb
  291. )
  292. {
  293.     static TCHAR szGonzoThing[] = TEXT("M");
  294.  
  295.     int         anTabsList[TLB_MAX_TAB_STOPS];
  296.     HDC         hdc;
  297.     HFONT       hfont;
  298.     TEXTMETRIC  tm;
  299.     int         nAveCharWidth;
  300.  
  301.     UINT        u;
  302.     int         nWidth;
  303.     int         nPrevTabTitle;
  304.     int         nPrevTabList;
  305.     SIZE        sSize;
  306.  
  307.  
  308.     //
  309.     //
  310.     //
  311.     hdc = GetDC(NULL);
  312.     {
  313.     //
  314.     //  get the average char width and height of the current font so we
  315.     //  can compute tabs correctly. note that GetTextMetrics is pretty
  316.     //  bogus when it comes to the average char width--it normally gives
  317.     //  you the width of the character 'x'. what it should be is the
  318.     //  average width of all capitals and lower case letters..
  319.     //
  320.     hfont = GetWindowFont(ptlb->hlb);
  321.     if (NULL == hfont)
  322.         hfont = GetStockFont(SYSTEM_FONT);
  323.  
  324.     hfont = SelectObject(hdc, hfont);
  325.  
  326. #if 0
  327.     GetTextMetrics(hdc, &tm);
  328.     nAveCharWidth = tm.tmAveCharWidth;
  329. #else
  330.     nAveCharWidth = GetRealTextMetrics(hdc, &tm);
  331. #endif
  332.     ptlb->nFontHeight = tm.tmHeight;
  333.  
  334.  
  335.     //
  336.     //
  337.     //
  338.     GetTextExtentPoint(hdc, szGonzoThing, 1, &sSize);
  339.  
  340.  
  341.     //
  342.     //
  343.     //
  344.     hfont = SelectObject(hdc, hfont);
  345.     }
  346.     ReleaseDC(NULL, hdc);
  347.  
  348.  
  349.     //
  350.     //  calculate the width of each column
  351.     //
  352.     nPrevTabTitle = 0;
  353.     nPrevTabList  = 0;
  354.     for (u = 0; u < ptlb->uTabStops; u++)
  355.     {
  356. //      nWidth = nAveCharWidth * ptlb->panTabs[u] + nAveCharWidth * 2;
  357.     nWidth = sSize.cx * ptlb->panTabs[u] + (sSize.cx * 2);
  358.  
  359.     //
  360.     //  set tabstop for title text--this is in client units
  361.     //  for TabbedTextOut in TlbPaint
  362.     //
  363.     ptlb->panTitleTabs[u] = nPrevTabTitle + nWidth;
  364.     nPrevTabTitle = ptlb->panTitleTabs[u];
  365.  
  366.     //
  367.     //  set tabstop for listbox--this is in dialog units
  368.     //
  369.     anTabsList[u] = nPrevTabList + MulDiv(nWidth, 4, nAveCharWidth);
  370.     nPrevTabList  = anTabsList[u];
  371.     }
  372.  
  373.  
  374.     //
  375.     //  now setup the tabstops in the listbox
  376.     //
  377.     ListBox_SetTabStops(ptlb->hlb, ptlb->uTabStops, anTabsList);
  378.  
  379.     return (TRUE);
  380. } // TlbRecalcTabs()
  381.  
  382.  
  383. //--------------------------------------------------------------------------;
  384. //  
  385. //  HFONT TlbSetFont
  386. //  
  387. //  Description:
  388. //  
  389. //  
  390. //  Arguments:
  391. //      PZYZTABBEDLISTBOX ptlb:
  392. //  
  393. //      HFONT hfont:
  394. //  
  395. //      BOOL fRedraw:
  396. //  
  397. //  Return (HFONT):
  398. //  
  399. //  History:
  400. //      05/16/93
  401. //  
  402. //--------------------------------------------------------------------------;
  403.  
  404. HFONT FNGLOBAL TlbSetFont
  405. (
  406.     PZYZTABBEDLISTBOX   ptlb,
  407.     HFONT               hfont,
  408.     BOOL                fRedraw
  409. )
  410. {
  411.     HFONT       hfontOld;
  412.  
  413.     //
  414.     //
  415.     //
  416.     hfontOld = GetWindowFont(ptlb->hlb);
  417.     SetWindowFont(ptlb->hlb, hfont, FALSE);
  418.  
  419.     TlbRecalcTabs(ptlb);
  420.     TlbMove(ptlb, &ptlb->rc, fRedraw);
  421.  
  422.     return (hfontOld);
  423. } // TlbSetFont()
  424.  
  425.  
  426. //--------------------------------------------------------------------------;
  427. //  
  428. //  BOOL TlbSetTitleAndTabs
  429. //  
  430. //  Description:
  431. //      This function sets the title text and tab stops for a Tabbed List
  432. //      Box (TLB). The pszTitleFormat specifies the title text for each
  433. //      column along with the tabstop position for each column. The format
  434. //      of this string is as follows:
  435. //
  436. //      <columnname1>\t<tab1>!<columnname2>
  437. //
  438. //      TCHAR   szTlbThings[] = TEXT("Index\t6!Code\t5!Name");
  439. //
  440. //
  441. //  Arguments:
  442. //      PZYZTABBEDLISTBOX ptlb:
  443. //  
  444. //      PTSTR pszTitleFormat:
  445. //
  446. //      BOOL fRedraw:
  447. //  
  448. //  Return (BOOL):
  449. //  
  450. //  History:
  451. //      05/18/93
  452. //  
  453. //--------------------------------------------------------------------------;
  454.  
  455. BOOL FNGLOBAL TlbSetTitleAndTabs
  456. (
  457.     PZYZTABBEDLISTBOX   ptlb,
  458.     PTSTR               pszTitleFormat,
  459.     BOOL                fRedraw
  460. )
  461. {
  462.     TCHAR       szTitleText[TLB_MAX_TITLE_CHARS];
  463.     int         anTabs[TLB_MAX_TAB_STOPS];
  464.     PTSTR       pch;
  465.     PTSTR       pchTitleText;
  466.     UINT        uTabStops;
  467.     UINT        cchTitleText;
  468.     HWND        hwnd;
  469.  
  470.     //
  471.     //  parse the title format counting tab stops and actual size of title
  472.     //  text
  473.     //
  474.     uTabStops    = 0;
  475.     pchTitleText = szTitleText;
  476.     for (pch = pszTitleFormat; '\0' != *pch; )
  477.     {
  478.     TCHAR       ch;
  479.  
  480.     //
  481.     //  scan to tab
  482.     //
  483.     while ('\0' != (ch = *pch))
  484.     {
  485.         *pchTitleText++ = *pch++;
  486.  
  487.         if ('\t' == ch)
  488.         break;
  489.     }
  490.  
  491.     if ('\0' == ch)
  492.         break;
  493.  
  494.     //
  495.     //  grab the next tab stop value
  496.     //
  497.     anTabs[uTabStops] = atoi(pch);
  498.     uTabStops++;
  499.  
  500.     //
  501.     //  skip to start of next column name
  502.     //
  503.     while ('!' != *pch++)
  504.         ;
  505.     }
  506.  
  507.  
  508.     //
  509.     //  terminate the converted title text
  510.     //
  511.     *pchTitleText = '\0';
  512.     cchTitleText = lstrlen(szTitleText);
  513.  
  514.     //
  515.     //  free the memory used for the previous tab stops and title text
  516.     //
  517.     if (NULL != ptlb->panTabs)
  518.     {
  519.     LocalFree((HLOCAL)ptlb->panTabs);
  520.  
  521.     ptlb->uTabStops    = 0;
  522.     ptlb->panTabs      = NULL;
  523.     ptlb->panTitleTabs = NULL;
  524.     }
  525.  
  526.     if (NULL != ptlb->pszTitleText)
  527.     {
  528.     LocalFree((HLOCAL)ptlb->pszTitleText);
  529.  
  530.     ptlb->cchTitleText = 0;
  531.     ptlb->pszTitleText = NULL;
  532.     }
  533.  
  534.  
  535.     //
  536.     //  allocate new space for tab stops. there are two different tab
  537.     //  arrays:
  538.     //
  539.     //      panTabs: original tab values as passed by caller. these are
  540.     //      virtual tab locations represented as number of characters. we
  541.     //      need to keep these values for recomputing the real tabs when
  542.     //      the font changes.
  543.     //
  544.     //      panTitleTabs: these values are computed by TlbRecalcTabs and
  545.     //      are actual tab positions in client coordinates for the title
  546.     //      text (needed for TabbedTextOut in TlbPaint).
  547.     //
  548.     //  the tabs for the listbox are computed and set in TlbRecalcTabs
  549.     //
  550.     if (0 != uTabStops)
  551.     {
  552.     ptlb->panTabs = (PINT)LocalAlloc(LPTR, (uTabStops * sizeof(int)) * 2);
  553.     if (NULL == ptlb->panTabs)
  554.         return (FALSE);
  555.  
  556.     ptlb->uTabStops    = uTabStops;
  557.     ptlb->panTitleTabs = ptlb->panTabs + uTabStops;
  558.     memcpy(ptlb->panTabs, anTabs, uTabStops * sizeof(int));
  559.     }
  560.  
  561.  
  562.     //
  563.     //  allocate space for the converted title text (stripped of the tab
  564.     //  spacing values). this string is passed directly to TabbedTextOut
  565.     //  in TlbPaint.
  566.     //
  567.     if (0 != cchTitleText)
  568.     {
  569.     ptlb->pszTitleText = (PTSTR)LocalAlloc(LPTR, (cchTitleText + 1) * sizeof(TCHAR));
  570.     if (NULL == ptlb->pszTitleText)
  571.         return (FALSE);
  572.  
  573.     ptlb->cchTitleText = cchTitleText;
  574.     lstrcpy(ptlb->pszTitleText, szTitleText);
  575.     }
  576.  
  577.  
  578.  
  579.     //
  580.     //
  581.     //
  582.     TlbRecalcTabs(ptlb);
  583.  
  584.  
  585.     //
  586.     //  force a complete repaint of the title text and listbox--redraw
  587.     //  immediately if we are supposed to
  588.     //
  589.     hwnd = GetParent(ptlb->hlb);
  590.     InvalidateRect(hwnd, &ptlb->rc, TRUE);
  591.     if (fRedraw)
  592.     {
  593.     UpdateWindow(hwnd);
  594.     }
  595. } // TlbSetTitleAndTabs()
  596.  
  597.  
  598. //--------------------------------------------------------------------------;
  599. //  
  600. //  PZYZTABBEDLISTBOX TlbDestroy
  601. //  
  602. //  Description:
  603. //  
  604. //  
  605. //  Arguments:
  606. //      PZYZTABBEDLISTBOX ptlb:
  607. //  
  608. //  Return (PZYZTABBEDLISTBOX):
  609. //  
  610. //  History:
  611. //      05/16/93
  612. //  
  613. //--------------------------------------------------------------------------;
  614.  
  615. PZYZTABBEDLISTBOX FNGLOBAL TlbDestroy
  616. (
  617.     PZYZTABBEDLISTBOX   ptlb
  618. )
  619. {
  620.     HWND        hwnd;
  621.     int         nHeight;
  622.  
  623.     //
  624.     //  get rid of the listbox
  625.     //
  626.     if (NULL != ptlb->hlb)
  627.     {
  628.     DestroyWindow(ptlb->hlb);
  629.  
  630.     //
  631.     //  invalidate area where title text was so it will be clean
  632.     //
  633.     nHeight = min(ptlb->nFontHeight, ptlb->rc.bottom - ptlb->rc.top);
  634.     ptlb->rc.bottom = ptlb->rc.top + nHeight;
  635.  
  636.     hwnd = GetParent(ptlb->hlb);
  637.     InvalidateRect(hwnd, &ptlb->rc, TRUE);
  638.  
  639.  
  640.     //
  641.     //  free the memory used for tab stops and title text
  642.     //
  643.     if (NULL != ptlb->panTabs)
  644.         LocalFree((HLOCAL)ptlb->panTabs);
  645.  
  646.     if (NULL != ptlb->pszTitleText)
  647.         LocalFree((HLOCAL)ptlb->pszTitleText);
  648.     }
  649.  
  650.     LocalFree((HLOCAL)ptlb);
  651.  
  652.     return (NULL);
  653. } // TlbDestroy()
  654.  
  655.  
  656. //--------------------------------------------------------------------------;
  657. //  
  658. //  PZYZTABBEDLISTBOX TlbCreate
  659. //  
  660. //  Description:
  661. //  
  662. //  
  663. //  Arguments:
  664. //      HWND hwnd:
  665. //  
  666. //      int nId:
  667. //  
  668. //      PRECT prc:
  669. //  
  670. //  Return (PZYZTABBEDLISTBOX):
  671. //  
  672. //  History:
  673. //      05/16/93
  674. //  
  675. //--------------------------------------------------------------------------;
  676.  
  677. PZYZTABBEDLISTBOX FNGLOBAL TlbCreate
  678. (
  679.     HWND                hwnd,
  680.     int                 nId,
  681.     PRECT               prc
  682. )
  683. {
  684.     #define TLB_DEF_STYLE   (WS_VISIBLE|WS_CHILD|WS_VSCROLL|WS_BORDER|  \
  685.                  LBS_NOTIFY|LBS_NOINTEGRALHEIGHT|LBS_USETABSTOPS)
  686.  
  687.     static TCHAR    szNull[]    = TEXT("");
  688.     static TCHAR    szListBox[] = TEXT("ListBox");
  689.  
  690.     PZYZTABBEDLISTBOX   ptlb;
  691.     HINSTANCE           hinst;
  692.  
  693.  
  694.     //
  695.     //  create a new instance data structure..
  696.     //
  697.     ptlb = (PZYZTABBEDLISTBOX)LocalAlloc(LPTR, sizeof(*ptlb));
  698.     if (NULL == ptlb)
  699.     return (NULL);
  700.  
  701.  
  702.     //
  703.     //  create the listbox
  704.     //
  705.     hinst = GetWindowInstance(hwnd);
  706.  
  707.     ptlb->hlb = CreateWindow(szListBox, szNull, TLB_DEF_STYLE,
  708.                  0, 0, 0, 0, hwnd, (HMENU)nId, hinst, NULL);
  709.     if (NULL == ptlb->hlb)
  710.     {
  711.     TlbDestroy(ptlb);
  712.     return (NULL);
  713.     }
  714.  
  715.     TlbRecalcTabs(ptlb);
  716.  
  717.     if (NULL != prc)
  718.     {
  719.     ptlb->rc = *prc;
  720.     TlbMove(ptlb, prc, FALSE);
  721.     }
  722.  
  723.     return (ptlb);
  724. } // TlbCreate()
  725.