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