TLB.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:17k
源码类别:

Windows编程

开发平台:

Visual C++

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