home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / perfmon / legend.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  39KB  |  1,346 lines

  1. /*
  2. ==============================================================================
  3.  
  4.   Application:
  5.  
  6.             Microsoft Windows NT (TM) Performance Monitor
  7.  
  8.   File:
  9.             legend.c - legend window routines.                          
  10.  
  11.             This file contains code creating the legend window, which is
  12.             a child of the graph windows. The legend window displays a
  13.             legend line for each line in the associated graph. It also 
  14.             includes an area called the label, which are headers for those
  15.             lines.
  16.  
  17.  
  18.   Copyright 1992-1997, Microsoft Corporation. All Rights Reserved.
  19. ==============================================================================
  20. */
  21.  
  22.  
  23. //==========================================================================//
  24. //                                  Includes                                //
  25. //==========================================================================//
  26.  
  27.  
  28. #include <stdio.h>      // for sprintf
  29. #include "perfmon.h"
  30. #include "legend.h"     // external declarations for this file
  31.  
  32. #include "owndraw.h"
  33.  
  34. #include "alert.h"      // for EditAlert
  35. #include "grafdata.h"   // for EditChart
  36. #include "pmemory.h"    // for MemoryXXX (mallloc-type) routines
  37. #include "utils.h"
  38. #include "valuebar.h"   // for StatusTimer
  39. #include "playback.h"   // for PlayingBackLog()
  40. #include "perfmops.h"   // for COnvertDecimalPoint
  41.  
  42. #define eScaleValueSpace       TEXT(">9999999999.0")
  43.  
  44. //==========================================================================//
  45. //                                  Constants                               //
  46. //==========================================================================//
  47.  
  48.  
  49. #define dwGraphLegendClassStyle     (CS_HREDRAW | CS_VREDRAW)
  50. #define iGraphLegendClassExtra      (0)
  51. #define iGraphLegendWindowExtra     (sizeof (PLEGEND))
  52. #define dwGraphLegendWindowStyle    (WS_CHILD | WS_VISIBLE) 
  53.  
  54. #define xLegendBorderWidth          (xDlgBorderWidth)
  55. #define yLegendBorderHeight         (yDlgBorderHeight)
  56.  
  57. #define iLabelLen                   30
  58. #define iLegendColMax               1000
  59.  
  60. #define LEFTORIENTATION             1
  61. #define CENTERORIENTATION           2
  62. #define RIGHTORIENTATION            3
  63.  
  64. #define LegendColorCol              0
  65. #define LegendScaleCol              1
  66. #define LegendCounterCol            2
  67. #define LegendInstanceCol           3
  68. #define LegendParentCol             4
  69. #define LegendObjectCol             5
  70. #define LegendSystemCol             6  
  71.  
  72. #define iLegendNumCols              7
  73.  
  74. #define iLegendMaxVisibleItems      8
  75.  
  76. #define dwGraphLegendItemsWindowClass  TEXT("ListBox")
  77. #define dwGraphLegendItemsWindowStyle           \
  78.    (LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | LBS_OWNERDRAWFIXED | \
  79.     WS_VISIBLE | WS_CHILD | WS_VSCROLL)
  80.  
  81.  
  82. //==========================================================================//
  83. //                                  Typedefs                                //
  84. //==========================================================================//
  85.  
  86.  
  87. typedef struct LEGENDCOLSTRUCT
  88.    {
  89.    TCHAR          szLabel [iLabelLen] ;
  90.    int            xMinWidth ;
  91.    int            xMaxWidth ;
  92.    int            xWidth ;
  93.    int            xPos ;
  94.    int            iOrientation ;
  95.    } LEGENDCOL ;
  96.  
  97. typedef LEGENDCOL *PLEGENDCOL ;
  98.  
  99.  
  100. typedef struct LEGENDTRUCT
  101.    {
  102.    HWND           hWndItems ;
  103.    HFONT          hFontItems ;
  104.    HFONT          hFontLabels ;
  105.    int            xMinWidth ;
  106.    int            yLabelHeight ;
  107.    int            yItemHeight ;
  108.    int            iNumItemsVisible ;
  109.    LEGENDCOL      aCols [iLegendNumCols] ;
  110.    int            iLineType ;
  111.    PLINE          pCurrentLine ;    // current selected line
  112.    }  LEGEND ;
  113.  
  114. typedef LEGEND *PLEGEND ;
  115.  
  116.  
  117. //==========================================================================//
  118. //                                   Macros                                 //
  119. //==========================================================================//
  120.  
  121.  
  122. #define LabelTopMargin()      (2)
  123. #define LegendLeftMargin()    (3 + ThreeDPad)
  124.  
  125. #define LegendItemTopMargin() (yBorderHeight)
  126.  
  127.  
  128. #define IsLegendLabelVisible()  (TRUE)
  129.  
  130. #define ColCanGrow(pCol)                     \
  131.    (pCol->xMaxWidth > pCol->xWidth)
  132.  
  133.  
  134. #define LegendHorzMargin()    (3)
  135.  
  136.  
  137.  
  138. //==========================================================================//
  139. //                                Local Data                                //
  140. //==========================================================================//
  141.  
  142.  
  143. // LEGEND            Legend ;
  144. PLEGEND     pGraphLegendData ;
  145. PLEGEND     pAlertLegendData ;
  146.  
  147. #define  LegendData(hWnd)     \
  148.    ((hWnd == hWndGraphLegend) ? pGraphLegendData : pAlertLegendData )
  149.  
  150. //==========================================================================//
  151. //                              Local Functions                             //
  152. //==========================================================================//
  153. void LegendSetCurrentLine (PLEGEND pLegend, int iIndex)
  154.    {
  155.    pLegend->pCurrentLine =
  156.       (PLINESTRUCT) LBData (pLegend->hWndItems, iIndex) ;
  157.  
  158.    if (pLegend->pCurrentLine == (PLINESTRUCT) LB_ERR)
  159.       {
  160.       pLegend->pCurrentLine = NULL ;
  161.       }
  162.    }  // LegendSetCurrentLine
  163.  
  164. #if 0
  165. PLEGEND LegendData (HWND hWnd)
  166.    {
  167.    return ((PLEGEND) GetWindowLong (hWnd, 0)) ;
  168.    }
  169. #endif
  170.  
  171.  
  172. PLEGEND AllocateLegendData (HWND hWnd, BOOL bChartLegend)
  173.    {
  174.    PLEGEND        pLegend ;
  175.  
  176.    pLegend = MemoryAllocate (sizeof (LEGEND)) ;
  177. //   SetWindowLong (hWnd, 0, (LONG) pLegend) ;
  178.  
  179.    if (bChartLegend)
  180.       {
  181.       hWndGraphLegend = hWnd ;
  182.       pGraphLegendData = pLegend ;
  183.       }
  184.    else
  185.       {
  186.       hWndAlertLegend = hWnd ;
  187.       pAlertLegendData = pLegend ;
  188.       }
  189.  
  190.    return (pLegend) ;
  191.    }
  192.  
  193.  
  194.  
  195. void DrawLegendLabel (PLEGEND pLegend,
  196.                       HDC hDC,
  197.                       HWND hWnd)
  198.    {  // DrawLegendLabel
  199.    int            i ;
  200.    int            xPos ;
  201.    RECT           rect ;
  202.    RECT           rectLB ;
  203.    INT            LocalThreeDPad = ThreeDPad - 1 ;
  204.  
  205.    SetBkColor (hDC, crLightGray) ;
  206.  
  207.    SelectFont (hDC, pLegend->hFontLabels) ;
  208.  
  209.    GetClientRect (hWnd, &rect) ;
  210. //   Fill (hDC, crLightGray, &rect) ;
  211.    ExtTextOut (hDC, rect.left, rect.top,
  212.       ETO_OPAQUE, &(rect), NULL, 0, NULL ) ;
  213.  
  214.    GetWindowRect (pLegend->hWndItems, &rectLB) ;
  215.    ScreenRectToClient (hWnd, &rectLB) ;
  216.    ThreeDConcave1 (hDC, 
  217.                   rectLB.left - LocalThreeDPad,
  218.                   rectLB.top - LocalThreeDPad,
  219.                   rectLB.right + LocalThreeDPad,
  220.                   rectLB.bottom + LocalThreeDPad) ;
  221.  
  222.    for (i = 0 ;
  223.         i < iLegendNumCols ;
  224.         i++)
  225.       {  // for
  226.       rect.left = pLegend->aCols[i].xPos ;
  227.       rect.top = yBorderHeight ;
  228.       rect.right = rect.left + pLegend->aCols[i].xWidth - LegendHorzMargin () ;
  229.       rect.bottom = pLegend->yLabelHeight ;
  230.  
  231.       switch (pLegend->aCols[i].iOrientation)
  232.          {  // switch
  233.          case LEFTORIENTATION:
  234.             SetTextAlign (hDC, TA_LEFT) ;
  235.             xPos = rect.left ;
  236.             break ;
  237.  
  238.          case CENTERORIENTATION:
  239.             SetTextAlign (hDC, TA_CENTER) ;
  240.             xPos = (rect.left + rect.right) / 2 ;
  241.             break ;
  242.  
  243.          case RIGHTORIENTATION:
  244.             SetTextAlign (hDC, TA_RIGHT) ;
  245.             xPos = rect.right ;
  246.             break ;
  247.  
  248.          default:
  249.             xPos = rect.left ;
  250.             break ;
  251.          }  // switch
  252.  
  253.       ExtTextOut (hDC, 
  254.                   xPos, rect.top, 
  255.                   ETO_OPAQUE,
  256.                   &rect,
  257.                   pLegend->aCols[i].szLabel,
  258.                   lstrlen (pLegend->aCols[i].szLabel),
  259.                   NULL) ;
  260.       }  // for
  261.    }  // DrawLegendLabel
  262.  
  263.  
  264.  
  265. void DrawColorCol (PLEGEND pLegend,
  266.                    PLINE pLine,
  267.                    int iCol,
  268.                    HDC hDC,
  269.                    int yPos)
  270. /*
  271.    Effect:        Draw the "color" column of a legend entry. The color 
  272.                   column displays a small sample of the line drawing.
  273.  
  274.                   For charts, the sample is a line of the correct style,
  275.                   color, and width.  Since we are using wide lines, 
  276.                   the round endcaps of the lines will breach the column.
  277.                   Therefore we need to set the clip region. We could
  278.                   remove this clipping if we find a way to change the
  279.                   end cap design.  
  280.  
  281.                   For alerts, the sample is a small circle which echos
  282.                   the design in the alert log itself.
  283. */      
  284.    {  // DrawColorCol
  285.    HBRUSH         hBrush, hBrushPrevious ;
  286.    RECT           rect ;
  287.    int            yMiddle ;
  288.    int            iCircle ;
  289.  
  290.  
  291.  
  292.    rect.left = pLegend->aCols[iCol].xPos - LegendLeftMargin () + 2 ;
  293.    rect.top = yPos + 1 ;
  294.    rect.right = rect.left + pLegend->aCols[iCol].xWidth - LegendHorzMargin () ;
  295.    rect.bottom = yPos + pLegend->yItemHeight - 1 ;
  296.  
  297.    yMiddle = rect.top + (rect.bottom - rect.top) / 2 ;
  298.    iCircle = rect.bottom - rect.top - 2 ;
  299.  
  300.   switch (pLegend->iLineType)
  301.       {  // switch
  302.       case LineTypeChart:
  303.    
  304.          if (pLine->Visual.iWidth == 1)
  305.             {
  306.             // simple case with thin pen
  307.             hBrush = SelectBrush (hDC, hbLightGray) ;
  308.             Rectangle (hDC, rect.left, rect.top, rect.right, rect.bottom) ;
  309.    
  310.             HLine (hDC, pLine->hPen, 
  311.                    rect.left + 1, rect.right - 1, yMiddle) ;
  312.             SelectBrush (hDC, hBrush) ;
  313.             }
  314.          else
  315.             {
  316.             // thicker pen width, have to set ClipRect so
  317.             // it will not draw otherside the rect.
  318.             SaveDC (hDC) ;
  319.             hBrush = SelectBrush (hDC, hbLightGray) ;
  320.             Rectangle (hDC, rect.left, rect.top, rect.right, rect.bottom) ;
  321.    
  322.             IntersectClipRect (hDC, 
  323.                                rect.left + 1,
  324.                                rect.top + 1,
  325.                                rect.right - 1,
  326.                                rect.bottom - 1) ;
  327.             HLine (hDC, pLine->hPen, 
  328.                    rect.left + 1, rect.right - 1, yMiddle) ;
  329.             SelectBrush (hDC, hBrush) ;
  330.             RestoreDC (hDC, -1) ;
  331.             }
  332.          break ;
  333.  
  334.  
  335.       case LineTypeAlert:
  336.          hBrushPrevious = SelectBrush (hDC, pLine->hBrush) ;
  337.  
  338.          Ellipse (hDC,
  339.                   rect.left + 2,
  340.                   rect.top + 2,
  341.                   rect.left + 2 + iCircle,
  342.                   rect.top + 2 + iCircle) ;
  343.  
  344.          SelectBrush (hDC, hBrushPrevious) ;
  345.          break ;
  346.       }  // switch
  347.  
  348.    }  // DrawColorCol
  349.  
  350.  
  351. void DrawLegendCol (PLEGEND pLegend,
  352.                     int iCol,
  353.                     HDC hDC,
  354.                     int yPos,
  355.                     LPTSTR lpszValue)
  356. /*
  357.    Effect:        Draw the value lpszValue for the column iCol on hDC.
  358.  
  359.    Assert:        The foreground and background text colors of hDC are
  360.                   properly set.
  361. */
  362.    {  // DrawLegendCol
  363.    RECT           rect ;
  364.    int            xPos ;
  365.  
  366.    rect.left = pLegend->aCols[iCol].xPos - LegendLeftMargin () ;
  367.    rect.top = yPos ;
  368.    rect.right = rect.left + pLegend->aCols[iCol].xWidth - LegendHorzMargin () ;
  369.    rect.bottom = yPos + pLegend->yItemHeight ;
  370.  
  371. //   SetTextAlign (hDC, TA_TOP) ;   
  372.    switch (pLegend->aCols[iCol].iOrientation)
  373.       {  // switch
  374.       case LEFTORIENTATION:
  375.          SetTextAlign (hDC, TA_LEFT) ;
  376.          xPos = rect.left ;
  377.          break ;
  378.  
  379.       case CENTERORIENTATION:
  380.          SetTextAlign (hDC, TA_CENTER) ;
  381.          xPos = (rect.left + rect.right) / 2 ;
  382.          break ;
  383.  
  384.       case RIGHTORIENTATION:
  385.          SetTextAlign (hDC, TA_RIGHT) ;
  386.          xPos = rect.right ;
  387.          break ;
  388.  
  389.       default:
  390.          xPos = rect.left ;
  391.          break ;
  392.       }  // switch
  393.  
  394.    ExtTextOut (hDC, 
  395.                xPos, rect.top + LegendItemTopMargin (), 
  396.                ETO_OPAQUE | ETO_CLIPPED,
  397.                &rect,
  398.                lpszValue,
  399.                lstrlen (lpszValue),
  400.                NULL) ;
  401.    }  // DrawLegendCol
  402.  
  403.  
  404. void DrawLegendItem (PLEGEND pLegend,
  405.                      PLINESTRUCT pLine,
  406.                      int yPos,
  407.                      HDC hDC)
  408.    {
  409.    TCHAR          szValue [256] ;
  410.    TCHAR          szInstance [256] ;
  411.    TCHAR          szParent [256] ;
  412.    TCHAR          szNoName[4] ;
  413.  
  414.    szNoName[0] = szNoName[1] = szNoName[2] = TEXT('-') ;
  415.    szNoName[3] = TEXT('\0') ;
  416.  
  417.    //=============================//
  418.    // Determine Instance, Parent  //
  419.    //=============================//
  420.  
  421.    // It's possible that there will be no instance, therefore
  422.    // the lnInstanceName would be NULL.
  423.  
  424.    if (pLine->lnObject.NumInstances > 0)
  425.       {
  426.       // Test for the parent object instance name title index.
  427.       // If there is one, it implies that there will be a valid
  428.       // Parent Object Name and a valid Parent Object Instance Name.
  429.  
  430.       // If the Parent Object title index is 0 then
  431.       // just display the instance name.
  432.  
  433.       lstrcpy (szInstance, pLine->lnInstanceName) ;
  434.       if (pLine->lnInstanceDef.ParentObjectTitleIndex &&
  435.           pLine->lnPINName)
  436.          {
  437.          // Get the Parent Object Name.
  438.          lstrcpy (szParent, pLine->lnPINName) ;
  439.          }
  440.       else
  441.          {
  442.          lstrcpy (szParent, szNoName) ;
  443.          }
  444.       }
  445.    else
  446.       {
  447.       lstrcpy (szInstance, szNoName) ;
  448.       lstrcpy (szParent, szNoName) ;
  449.       }
  450.  
  451.    //=============================//
  452.    // Draw Color                  //
  453.    //=============================//
  454.  
  455.    DrawColorCol (pLegend, pLine, LegendColorCol, hDC, yPos) ;
  456.  
  457.    //=============================//
  458.    // Draw Scale/Value            //
  459.    //=============================//
  460.  
  461.    if (pLegend->iLineType == LineTypeChart)
  462.       {
  463.       if (pLine->eScale < (FLOAT) 1.0)
  464.          {
  465.          TSPRINTF (szValue, TEXT("%6.6f"), pLine->eScale) ;
  466.          }
  467.       else
  468.          {
  469.          TSPRINTF (szValue, TEXT("%10.3f"), pLine->eScale) ;
  470.          }
  471.       ConvertDecimalPoint (szValue) ;
  472.       }
  473.    else
  474.       {
  475.       FLOAT tempAlertValue ;
  476.  
  477.       tempAlertValue = pLine->eAlertValue ;
  478.       if (tempAlertValue < (FLOAT) 0.0)
  479.          {
  480.          tempAlertValue = -tempAlertValue ;
  481.          }
  482.  
  483.       if (tempAlertValue >= (FLOAT) 10000.0)
  484.          {
  485.          if (tempAlertValue < (FLOAT) 1.0E+8)
  486.             {
  487.             TSPRINTF (szValue, TEXT("%c%10.0f"),
  488.                pLine->bAlertOver ? TEXT('>') : TEXT('<'),
  489.                pLine->eAlertValue) ;
  490.             }
  491.          else
  492.             {
  493.             TSPRINTF (szValue, TEXT("%c%10.3e"),
  494.                pLine->bAlertOver ? TEXT('>') : TEXT('<'),
  495.                pLine->eAlertValue) ;
  496.             }
  497.          ConvertDecimalPoint (szValue) ;
  498.          }
  499.       else
  500.          {
  501.          TSPRINTF (szValue, TEXT("%c%10.4f"),
  502.             pLine->bAlertOver ? TEXT('>') : TEXT('<'),
  503.             pLine->eAlertValue) ;
  504.          ConvertDecimalPoint (szValue) ;
  505.          }
  506.       }
  507.  
  508.    SetTextAlign (hDC, TA_TOP) ;   
  509.  
  510.    DrawLegendCol (pLegend, LegendScaleCol,
  511.                   hDC, yPos, szValue) ;
  512.  
  513.  
  514.    //=============================//
  515.    // Draw Counter                //
  516.    //=============================//
  517.  
  518.    DrawLegendCol (pLegend, LegendCounterCol,
  519.                   hDC, yPos, pLine->lnCounterName) ;
  520.  
  521.    
  522.    //=============================//
  523.    // Draw Instance               //
  524.    //=============================//
  525.  
  526.    DrawLegendCol (pLegend, LegendInstanceCol,
  527.                   hDC, yPos, szInstance) ;
  528.  
  529.    //=============================//
  530.    // Draw Parent                 //
  531.    //=============================//
  532.  
  533.    DrawLegendCol (pLegend, LegendParentCol,  
  534.                   hDC, yPos, szParent) ;
  535.  
  536.    //=============================//
  537.    // Draw Object                 //
  538.    //=============================//
  539.  
  540.    DrawLegendCol (pLegend, LegendObjectCol,
  541.                   hDC, yPos, pLine->lnObjectName) ;
  542.  
  543.    //=============================//
  544.    // Draw System                 //
  545.    //=============================//
  546.  
  547.    DrawLegendCol (pLegend, LegendSystemCol,
  548.                   hDC, yPos, pLine->lnSystemName) ;
  549.  
  550.    }
  551.  
  552.  
  553. //==========================================================================//
  554. //                              Message Handlers                            //
  555. //==========================================================================//
  556.  
  557.  
  558. BOOL OnLegendCreate (HWND hWnd, LPCREATESTRUCT lpCS)
  559.    {
  560.    PLEGEND        pLegend ;
  561.    HDC            hDC ;
  562.    int            iCol ;
  563.    BOOL           bChartLegend ;
  564.  
  565.    bChartLegend = (lpCS->lpCreateParams) == (LPVOID) TRUE ;
  566.  
  567.    pLegend = AllocateLegendData (hWnd, bChartLegend) ;
  568.  
  569.    if (!pLegend)
  570.       return (FALSE) ;
  571.  
  572.    if (bChartLegend)
  573.       {
  574.       pLegend->iLineType = LineTypeChart ;
  575.       }
  576.    else
  577.       {
  578.       pLegend->iLineType = LineTypeAlert ;
  579.       }
  580.  
  581.    pLegend->hFontItems = hFontScales ;
  582.    pLegend->hFontLabels = hFontScalesBold ;
  583.    hDC = GetDC (hWnd) ;
  584.  
  585.    //=============================//
  586.    // Load Labels                 //
  587.    //=============================//
  588.  
  589.    StringLoad (IDS_LABELCOLOR, pLegend->aCols[LegendColorCol].szLabel) ;
  590.    if (pLegend->iLineType == LineTypeChart)
  591.       StringLoad (IDS_LABELSCALE, 
  592.                   pLegend->aCols[LegendScaleCol].szLabel) ;
  593.    else
  594.       StringLoad (IDS_LABELVALUE,
  595.                   pLegend->aCols[LegendScaleCol].szLabel) ;
  596.    StringLoad (IDS_LABELCOUNTER, pLegend->aCols[LegendCounterCol].szLabel) ;
  597.    StringLoad (IDS_LABELINSTANCE, pLegend->aCols[LegendInstanceCol].szLabel) ;
  598.    StringLoad (IDS_LABELPARENT, pLegend->aCols[LegendParentCol].szLabel) ;
  599.    StringLoad (IDS_LABELOBJECT, pLegend->aCols[LegendObjectCol].szLabel) ;
  600.    StringLoad (IDS_LABELSYSTEM, pLegend->aCols[LegendSystemCol].szLabel) ;
  601.  
  602.  
  603.    //=============================//
  604.    // Label dimensions            //
  605.    //=============================//
  606.  
  607.    SelectFont (hDC, pLegend->hFontLabels) ;
  608.    pLegend->yLabelHeight = FontHeight (hDC, TRUE) + 2 * LabelTopMargin () ;
  609.  
  610.    //=============================//
  611.    // Column dimensions           //
  612.    //=============================//
  613.  
  614.    for (iCol = 0 ;
  615.         iCol < iLegendNumCols ;
  616.         iCol++)
  617.       {  // for
  618.       pLegend->aCols[iCol].iOrientation = LEFTORIENTATION ;
  619.       pLegend->aCols[iCol].xMinWidth = 
  620.          TextWidth (hDC, pLegend->aCols[iCol].szLabel) + LegendHorzMargin () ;
  621.       }  // for
  622.  
  623.    SelectFont (hDC, pLegend->hFontItems) ;
  624.    pLegend->yItemHeight = FontHeight (hDC, TRUE) + 2 * LegendItemTopMargin () ;
  625.  
  626.    pLegend->aCols[LegendColorCol].xMaxWidth = max (3 * xScrollWidth,
  627.       pLegend->aCols[LegendColorCol].xMinWidth) ;
  628.  
  629.    pLegend->aCols[LegendScaleCol].xMaxWidth = TextWidth (hDC, eScaleValueSpace) ;
  630.    pLegend->aCols[LegendCounterCol].xMaxWidth = iLegendColMax ;
  631.    pLegend->aCols[LegendInstanceCol].xMaxWidth = iLegendColMax ;
  632.    pLegend->aCols[LegendParentCol].xMaxWidth = iLegendColMax ;
  633.    pLegend->aCols[LegendObjectCol].xMaxWidth = iLegendColMax ;
  634.    pLegend->aCols[LegendSystemCol].xMaxWidth = iLegendColMax ;
  635.    
  636.    pLegend->aCols[LegendColorCol].iOrientation = LEFTORIENTATION ;
  637.    pLegend->aCols[LegendScaleCol].iOrientation = RIGHTORIENTATION ;
  638.  
  639.    ReleaseDC (hWnd, hDC) ;   
  640.  
  641.    //=============================//
  642.    // Create Legend Items Listbox //
  643.    //=============================//
  644.  
  645.    pLegend->hWndItems =
  646.       CreateWindow (TEXT("ListBox"),               // window class
  647.                     NULL,                          // window caption
  648.                     dwGraphLegendItemsWindowStyle, // window style
  649.                     0, 0, 0, 0,                    // window size and pos
  650.                     hWnd,                          // parent window
  651.                     NULL,                          // menu
  652.                     hInstance,                     // program instance
  653.                     (LPVOID) TRUE) ;               // user-supplied data
  654.    }  // OnLegendCreate
  655.    
  656.  
  657. void static OnSize (HWND hWnd, int xWidth, int yHeight)
  658. /*
  659.    Effect:        Perform all actions necessary when the legend window is
  660.                   being resized. In particular, set the width and starting
  661.                   position for each column of the legend list and labels.
  662.  
  663.    Internals:     What we do is determine the amount of space in the
  664.                   width that is greater than the minimum, and allocate
  665.                   that space among each of the columns that is willing to
  666.                   be larger than minimum. If there is not enough room for
  667.                   the minimum, don't bother with calculations.
  668. */
  669.  
  670.    {  // OnSize
  671.    PLEGEND        pLegend ;
  672.    PLEGENDCOL     pCol ;
  673.    int            xMin ;
  674.    int            xSlack ;
  675.    int            iColsToGrow ;
  676.    int            iCol ;
  677.  
  678.    pLegend = LegendData (hWnd) ;
  679.  
  680.    //=============================//
  681.    // Resize Legend Items         //
  682.    //=============================//
  683.  
  684.    if (IsLegendLabelVisible ())
  685.       MoveWindow (pLegend->hWndItems, 
  686.                   LegendLeftMargin (), pLegend->yLabelHeight + ThreeDPad,
  687.                   xWidth - 2 * LegendLeftMargin (),
  688.                   yHeight - pLegend->yLabelHeight - yLegendBorderHeight,
  689.                   TRUE) ;
  690.    else
  691.       MoveWindow (pLegend->hWndItems,
  692.                   0, 0, 
  693.                   xWidth, yHeight,
  694.                   TRUE) ;
  695.                   
  696.       
  697.    //=============================//
  698.    // Allocate width to Columns   //
  699.    //=============================//
  700.  
  701.    xMin = LegendMinWidth (hWnd) ;
  702.    xSlack = max (xWidth - xMin, 0) ;
  703.    iColsToGrow = 0 ;
  704.  
  705.    for (iCol = 0 ;
  706.         iCol < iLegendNumCols ;
  707.         iCol++)
  708.       {  // for
  709.       pCol = &(pLegend->aCols[iCol]) ;
  710.  
  711.       pCol->xWidth = pCol->xMinWidth ;
  712.       if (ColCanGrow (pCol))
  713.          iColsToGrow++ ;
  714.       }  // for
  715.  
  716.    for (iCol = 0 ;
  717.         iCol < iLegendNumCols ;
  718.         iCol++)
  719.       {  // for
  720.       pCol = &(pLegend->aCols[iCol]) ;
  721.  
  722.       if (ColCanGrow (pCol))
  723.          {
  724.          if ((pCol->xWidth + xSlack / iColsToGrow) >
  725.              pCol->xMaxWidth)
  726.             {  // if
  727.             pCol->xWidth = pCol->xMaxWidth ;
  728.             xSlack -= (pCol->xMaxWidth - pCol->xMinWidth) ;
  729.             iColsToGrow-- ;
  730.             }  // if
  731.          }  // if
  732.       }  // for
  733.  
  734.    for (iCol = 0 ;
  735.         iCol < iLegendNumCols ;
  736.         iCol++)
  737.       {  // for
  738.       pCol = &(pLegend->aCols[iCol]) ;
  739.  
  740.       if (ColCanGrow (pCol))
  741.         pCol->xWidth += xSlack / iColsToGrow ;
  742.       }  // for
  743.  
  744.    if (pLegend->aCols[LegendCounterCol].xWidth <
  745.       pLegend->aCols[LegendCounterCol].xMaxWidth)
  746.       {
  747.       // cut some from the other columns and give them to CounterCol
  748.       if (pLegend->aCols[LegendColorCol].xWidth - xScrollWidth >=
  749.           pLegend->aCols[LegendColorCol].xMinWidth)
  750.          {
  751.          pLegend->aCols[LegendColorCol].xWidth -= xScrollWidth ;      
  752.          pLegend->aCols[LegendCounterCol].xWidth += xScrollWidth ;
  753.          }
  754.       if (pLegend->aCols[LegendInstanceCol].xWidth - xScrollWidth >=
  755.           pLegend->aCols[LegendInstanceCol].xMinWidth)
  756.          {
  757.          pLegend->aCols[LegendInstanceCol].xWidth -= xScrollWidth ;      
  758.          pLegend->aCols[LegendCounterCol].xWidth += xScrollWidth ;
  759.          }
  760.       if (pLegend->aCols[LegendParentCol].xWidth - xScrollWidth >=
  761.           pLegend->aCols[LegendParentCol].xMinWidth)
  762.          {
  763.          pLegend->aCols[LegendParentCol].xWidth -= xScrollWidth ;      
  764.          pLegend->aCols[LegendCounterCol].xWidth += xScrollWidth ;
  765.          }
  766.       }
  767.  
  768.    
  769.    //=============================//
  770.    // Set Column positions        //
  771.    //=============================//
  772.  
  773.    pLegend->aCols[0].xPos = LegendLeftMargin () ;
  774.    for (iCol = 1 ;
  775.         iCol < iLegendNumCols ;
  776.         iCol++)
  777.       {  // for
  778.       pLegend->aCols[iCol].xPos = 
  779.          pLegend->aCols[iCol - 1].xPos + pLegend->aCols[iCol - 1].xWidth ;
  780.  
  781.       if (iCol == LegendCounterCol)
  782.          {
  783.          // add some space between Scale/Value col & Counter col
  784.          pLegend->aCols[LegendCounterCol].xPos += LegendLeftMargin () ;
  785.          }
  786.       }  // for
  787.  
  788.    }  // OnSize
  789.  
  790.  
  791. void static OnPaint (HWND hWnd)
  792.    {  // OnPaint
  793.    PLEGEND        pLegend ;
  794.    HDC            hDC ;
  795.    PAINTSTRUCT    ps ;
  796.  
  797.    hDC = BeginPaint (hWnd, &ps) ;
  798.  
  799.    if (IsLegendLabelVisible ())
  800.       {
  801.       pLegend = LegendData (hWnd) ;
  802.       DrawLegendLabel (pLegend, hDC, hWnd) ;
  803.       }
  804.  
  805.    if (LBNumItems (pLegend->hWndItems) == 0)
  806.       {
  807.       WindowInvalidate(pLegend->hWndItems) ;
  808.       }
  809.  
  810.    EndPaint (hWnd, &ps) ;
  811.    }  // OnPaint
  812.  
  813.  
  814. void OnDrawLegendItem (HWND hWnd,
  815.                         LPDRAWITEMSTRUCT lpDI)
  816.    {  // OnDrawItem
  817.    HFONT          hFontPrevious ;
  818.    HDC            hDC ;
  819.    PLEGEND        pLegend ;
  820.    PLINESTRUCT    pLine ;
  821.    int            iLBIndex ;
  822.    COLORREF       preBkColor ;
  823.    COLORREF       preTextColor ;
  824.    BOOL           ResetColor = FALSE ;
  825.  
  826.    
  827.    hDC = lpDI->hDC ;
  828.    iLBIndex = DIIndex (lpDI) ;
  829.  
  830.    pLegend = LegendData (hWnd) ;
  831.  
  832.    if (iLBIndex == -1)
  833.       pLine = NULL ;
  834.    else
  835.       pLine = (PLINESTRUCT) LBData (pLegend->hWndItems, iLBIndex) ;
  836.  
  837.    //=============================//
  838.    // Set DC attributes           //
  839.    //=============================//
  840.  
  841.  
  842.    if (DISelected (lpDI) || pLine == NULL)
  843.       {  // if
  844.       preTextColor = SetTextColor (hDC, GetSysColor (COLOR_HIGHLIGHTTEXT)) ;
  845.       preBkColor = SetBkColor (hDC, GetSysColor (COLOR_HIGHLIGHT)) ;
  846.       ResetColor = TRUE ;
  847.       }  // if
  848.    ExtTextOut (hDC, lpDI->rcItem.left, lpDI->rcItem.top,
  849.       ETO_OPAQUE, &(lpDI->rcItem), NULL, 0, NULL ) ;
  850.    
  851.  
  852.    //=============================//
  853.    // Draw Legend Item            //
  854.    //=============================//
  855.  
  856.    hFontPrevious = SelectFont (hDC, pLegend->hFontItems) ;
  857.    if (pLine)
  858.       DrawLegendItem (pLegend, pLine, lpDI->rcItem.top, hDC) ;
  859.    SelectFont (hDC, hFontPrevious) ;
  860.  
  861.    //=============================//
  862.    // Draw Focus                  //
  863.    //=============================//
  864.  
  865.    if (DIFocus (lpDI))
  866.       DrawFocusRect (hDC, &(lpDI->rcItem)) ;
  867.  
  868.  
  869.    if (ResetColor == TRUE)
  870.       {  // if
  871.       preTextColor = SetTextColor (hDC, preTextColor) ;
  872.       preBkColor = SetBkColor (hDC, preBkColor) ;
  873.       }  // if
  874.    }  // OnDrawItem
  875.  
  876.  
  877. void static OnMeasureItem (HWND hWnd,
  878.                            LPMEASUREITEMSTRUCT lpMI)
  879.    {  // OnMeasureItem
  880.    PLEGEND        pLegend ;
  881.  
  882.    pLegend = LegendData (hWnd) ;
  883.    lpMI->itemHeight = pLegend->yItemHeight ;
  884.    }  // OnMeasureItem
  885.  
  886.  
  887. void static OnDestroy (HWND hWnd)
  888.    {
  889.    PLEGEND        pLegend ;
  890.  
  891.    pLegend = LegendData (hWnd) ;
  892.    MemoryFree (pLegend) ;
  893.    }  // OnDestroy
  894.  
  895.  
  896.  
  897. void static OnDoubleClick (HWND hWnd)
  898.    {
  899.    PLEGEND        pLegend ;
  900.  
  901.    pLegend = LegendData (hWnd) ;
  902.    if (!pLegend)
  903.       return ;
  904.  
  905.    switch (pLegend->iLineType)
  906.       {  // switch
  907.       case LineTypeChart:
  908.          EditChart (hWndMain) ;
  909.          break ;
  910.  
  911.       case LineTypeAlert:
  912.          EditAlert (hWndAlert) ;
  913.          break ;
  914.       }  // switch
  915.    }  // OnDoubleClick
  916.  
  917.  
  918. void static OnSetFocus (HWND hWnd)
  919.    {  // OnSetFocus
  920.    PLEGEND        pLegend ;
  921.  
  922.    pLegend = LegendData (hWnd) ;
  923.  
  924.    SetFocus (pLegend->hWndItems) ;
  925.    }
  926.  
  927. void static OnSelectionChanged (HWND hWnd)
  928.    {  // OnSelectionChanged
  929.    PLEGEND        pLegend ;
  930.    PGRAPHSTRUCT         pGraph ;
  931.    int            iIndex ;
  932.  
  933.  
  934.    pLegend = LegendData (hWnd) ;
  935.  
  936.    // set the new selected line
  937.    iIndex = LBSelection (pLegend->hWndItems) ;
  938.  
  939.    if (iIndex == LB_ERR)
  940.       return ;
  941.  
  942.    LegendSetCurrentLine (pLegend, iIndex) ;
  943.  
  944.    if (pLegend->iLineType == LineTypeChart)
  945.       {
  946.       pGraph = GraphData (hWndGraph) ;
  947.       
  948.       if (!PlayingBackLog())
  949.          {
  950.          // update the min, max, & avg of the current line
  951.          UpdateValueBarData (pGraph) ;
  952.          }
  953.  
  954.       // update the valuebar display
  955.       StatusTimer (hWndGraphStatus, TRUE) ;
  956.  
  957.       // change the Current highlighted line if necessary
  958.       if (pGraph && pGraph->HighLightOnOff)
  959.          {
  960.          WindowInvalidate (hWndGraphDisplay) ;
  961.          }
  962.       }
  963.    }  // OnSelectionChanged
  964.  
  965.  
  966. //==========================================================================//
  967. //                             Exported Functions                           //
  968. //==========================================================================//
  969.  
  970.  
  971. LRESULT APIENTRY GraphLegendWndProc (HWND hWnd,
  972.                                      WORD wMsg,
  973.                                      WPARAM wParam,
  974.                                      LONG lParam)
  975.    {  // GraphLegendWndProc
  976.    BOOL           bCallDefProc ;
  977.    LRESULT        lReturnValue ;
  978.  
  979.  
  980.    bCallDefProc = FALSE ;
  981.    lReturnValue = 0L ;
  982.  
  983.    switch (wMsg)
  984.       {  // switch
  985.       case WM_DELETEITEM:
  986.          break ;
  987.  
  988.       case WM_COMMAND:
  989.          switch (HIWORD (wParam))
  990.             {  // switch
  991.             case LBN_DBLCLK:
  992.                OnDoubleClick (hWnd) ;
  993.                break ;
  994.  
  995.             case LBN_SELCHANGE:
  996.                OnSelectionChanged (hWnd) ;
  997.                break ;
  998.  
  999.             default:
  1000.                break ;
  1001.             }  // switch
  1002.          break ;
  1003.  
  1004.       case WM_CREATE:
  1005.          OnLegendCreate (hWnd, (LPCREATESTRUCT) lParam) ;
  1006.          break ;
  1007.  
  1008.       case WM_DESTROY:
  1009.          OnDestroy (hWnd) ;
  1010.          break ;
  1011.  
  1012.       case WM_DRAWITEM:
  1013.          OnDrawLegendItem (hWnd, (LPDRAWITEMSTRUCT) lParam) ;
  1014.          break ;
  1015.  
  1016.       case WM_MEASUREITEM:
  1017.          OnMeasureItem (hWnd, (LPMEASUREITEMSTRUCT) lParam) ;
  1018.          break ;
  1019.  
  1020.       case WM_PAINT:
  1021.          OnPaint (hWnd) ;
  1022.          break ;
  1023.  
  1024.       case WM_SIZE:
  1025.          OnSize (hWnd, LOWORD (lParam), HIWORD (lParam)) ;
  1026.          break ;
  1027.  
  1028.       case WM_SETFOCUS:
  1029.          OnSetFocus (hWnd) ;
  1030.          break ;
  1031.  
  1032.       default:
  1033.          bCallDefProc = TRUE ;
  1034.       }  // switch
  1035.  
  1036.  
  1037.    if (bCallDefProc)
  1038.       lReturnValue = DefWindowProc (hWnd, wMsg, wParam, lParam) ;
  1039.  
  1040.    return (lReturnValue);
  1041.    }  // GraphLegendWndProc
  1042.  
  1043.  
  1044. int LegendMinWidth (HWND hWnd)
  1045.    {
  1046.    PLEGEND        pLegend ;
  1047.    int            iCol ;
  1048.    int            xMinWidth ;
  1049.  
  1050.    pLegend = LegendData (hWnd) ;
  1051.    xMinWidth = 0 ;
  1052.  
  1053.    for (iCol = 0 ;
  1054.         iCol < iLegendNumCols ;
  1055.         iCol++)
  1056.       {  // for
  1057.       xMinWidth += pLegend->aCols[iCol].xMinWidth ;
  1058.       }  // for
  1059.  
  1060.    return (xMinWidth) ;
  1061.    }
  1062.  
  1063.  
  1064. int LegendMinHeight (HWND hWnd)
  1065.    {
  1066.    PLEGEND        pLegend ;
  1067.  
  1068.    pLegend = LegendData (hWnd) ;
  1069.  
  1070.    if (IsLegendLabelVisible ())
  1071.       return (pLegend->yLabelHeight + pLegend->yItemHeight) ;
  1072.    else
  1073.       return (pLegend->yItemHeight) ;
  1074.    }
  1075.  
  1076.  
  1077. int LegendHeight (HWND hWnd, int yGraphHeight)
  1078. /*
  1079.    Effect:        Return the best height for the Legend window given the 
  1080.                   number of items and label visibility of the legend, as
  1081.                   well as the overall height of the graph.
  1082. */
  1083.    {  // LegendHeight
  1084.    PLEGEND        pLegend ;
  1085.    int            yPreferredHeight ;
  1086.  
  1087.    pLegend = LegendData (hWnd) ;
  1088.  
  1089.    yPreferredHeight = yLegendBorderHeight +
  1090.                       pLegend->yItemHeight * 
  1091.                       PinInclusive (LBNumItems (pLegend->hWndItems),
  1092.                                     1, iLegendMaxVisibleItems) ;
  1093.    if (IsLegendLabelVisible ())
  1094.       yPreferredHeight += pLegend->yLabelHeight ;
  1095.  
  1096.    return (min (yPreferredHeight, yGraphHeight / 2)) ;
  1097.    }  // LegendHeight
  1098.  
  1099.  
  1100.  
  1101. int LegendFullHeight (HWND hWnd, HDC hDC)
  1102. /*
  1103.    Effect:        Return the best height for the Legend window given the 
  1104.                   number of items and label visibility of the legend, as
  1105.                   well as the overall height of the graph.
  1106. */
  1107.    {  // LegendHeight
  1108.    PLEGEND        pLegend ;
  1109.    int            yPreferredHeight ;
  1110.  
  1111.    pLegend = LegendData (hWnd) ;
  1112.  
  1113.    yPreferredHeight = yLegendBorderHeight +
  1114.                       pLegend->yItemHeight * 
  1115.                       LBNumItems (pLegend->hWndItems) ;
  1116.    if (IsLegendLabelVisible ())
  1117.       yPreferredHeight += pLegend->yLabelHeight ;
  1118.  
  1119.    return (yPreferredHeight) ;
  1120.    }  // LegendFullHeight
  1121.  
  1122.  
  1123.  
  1124.  
  1125. HWND CreateGraphLegendWindow (HWND hWndGraph)
  1126.    {
  1127.    return (CreateWindow (szGraphLegendClass,       // class
  1128.                          NULL,                     // caption
  1129.                          dwGraphLegendWindowStyle, // window style
  1130.                          0, 0,                     // position
  1131.                          0, 0,                     // size
  1132.                          hWndGraph,                // parent window
  1133.                          NULL,                     // menu
  1134.                          hInstance,                // program instance
  1135.                          (LPVOID) TRUE)) ;         // user-supplied data
  1136.    }
  1137.  
  1138.  
  1139. BOOL GraphLegendInitializeApplication (void)
  1140. /*
  1141.    Called By:     GraphInitializeApplication only
  1142. */
  1143.    {
  1144.    WNDCLASS       wc ;
  1145.  
  1146.    wc.style          = dwGraphLegendClassStyle ;
  1147.    wc.lpfnWndProc    = (WNDPROC) GraphLegendWndProc ;
  1148.    wc.hInstance      = hInstance ;
  1149.    wc.cbClsExtra     = iGraphLegendClassExtra ;
  1150.    wc.cbWndExtra     = iGraphLegendWindowExtra ;
  1151.    wc.hIcon          = NULL ;
  1152.    wc.hCursor        = LoadCursor (NULL, IDC_ARROW) ;
  1153.    wc.hbrBackground  = hbLightGray ;
  1154.    wc.lpszMenuName   = NULL ;
  1155.    wc.lpszClassName  = szGraphLegendClass ;
  1156.  
  1157.    return (RegisterClass (&wc)) ;
  1158.    }
  1159.  
  1160.  
  1161. BOOL LegendAddItem (HWND hWnd, PLINESTRUCT pLine)
  1162. /*
  1163.    Effect:        Add a legend entry for the line pLine. Don't select
  1164.                   the line as current entry here, because this will cause
  1165.                   the scroll bar to unneccesarily appear for a moment.
  1166.                   If you want this line to be the current line, resize 
  1167.                   the legend first, then set as current line.
  1168.  
  1169.    See Also:      ChartInsertLine, AlertInsertLine.                  
  1170. */
  1171.    {  // LegendAddItem
  1172.    PLEGEND        pLegend ;
  1173.  
  1174.    pLegend = LegendData (hWnd) ;
  1175.    LBAdd (pLegend->hWndItems, pLine) ;
  1176.  
  1177.    return (TRUE) ;
  1178.    }  // LegendAddItem
  1179.  
  1180.  
  1181. void LegendDeleteItem (HWND hWndLegend, 
  1182.                        PLINE pLine)
  1183.    {  // LegendDeleteItem
  1184.    PLEGEND        pLegend ;
  1185.    int            iIndex ;
  1186.    int            iNextIndex ;
  1187.    int            iNumItems ;
  1188.    PGRAPHSTRUCT   pGraph ;
  1189.  
  1190.    pLegend = LegendData (hWndLegend) ;
  1191.    if (!pLegend)
  1192.       return ;
  1193.  
  1194.    iNumItems = LBNumItems (pLegend->hWndItems) ;
  1195.  
  1196.    iIndex = LBFind (pLegend->hWndItems, pLine) ;
  1197.  
  1198.    if (iIndex != LB_ERR)
  1199.       {
  1200.       LBDelete (pLegend->hWndItems, iIndex) ;
  1201.       }
  1202.  
  1203.    // no need to do anything if iNumItems is 1 to begin with
  1204.    if (iNumItems != LB_ERR && iNumItems > 1)
  1205.       {
  1206.       if (iIndex == iNumItems - 1)
  1207.          {
  1208.          // deleting the last line, then set selection
  1209.          // to the previous legend line
  1210.          iNextIndex = iIndex - 1 ;
  1211.          }
  1212.       else
  1213.          {
  1214.          // set the selection to the next legend line
  1215.          iNextIndex = iIndex ;
  1216.          }
  1217.  
  1218.       LBSetSelection (pLegend->hWndItems, iNextIndex) ;
  1219.       LegendSetCurrentLine (pLegend, iNextIndex) ;
  1220.  
  1221.       if (pLegend->iLineType == LineTypeChart)
  1222.          {
  1223.          // update the min, max, & avg of the current line
  1224.          pGraph = GraphData (hWndGraph) ;
  1225.  
  1226.          if (!PlayingBackLog())
  1227.             {
  1228.             // update the min, max, & avg of the current line
  1229.             UpdateValueBarData (pGraph) ;
  1230.             }
  1231.    
  1232.          // update the valuebar display
  1233.          StatusTimer (hWndGraphStatus, TRUE) ;
  1234.          }
  1235.       }
  1236.  
  1237.    }  // LegendDeleteItem
  1238.  
  1239.  
  1240. PLINE LegendCurrentLine (HWND hWndLegend)
  1241.    {  // LegendCurrentLine
  1242.    PLEGEND        pLegend ;
  1243.  
  1244.    pLegend = LegendData (hWndLegend) ;
  1245.  
  1246.    if (!pLegend)
  1247.       return (NULL) ;
  1248.  
  1249.    return (pLegend->pCurrentLine) ;
  1250.  
  1251.    }  // LegendCurrentLine
  1252.  
  1253.  
  1254.  
  1255. int LegendNumItems (HWND hWndLegend)
  1256.    {  // LegendNumItems
  1257.    PLEGEND        pLegend ;
  1258.  
  1259.    pLegend = LegendData (hWndLegend) ;
  1260.  
  1261.    return (LBNumItems (pLegend->hWndItems)) ;
  1262.    }  // LegendNumItems
  1263.  
  1264.  
  1265.  
  1266. void LegendSetSelection (HWND hWndLegend, int iIndex)
  1267.    {  // LegendSetSelection
  1268.    PLEGEND        pLegend ;
  1269.  
  1270.    pLegend = LegendData (hWndLegend) ;
  1271.    LBSetSelection (pLegend->hWndItems, iIndex) ;
  1272.    LegendSetCurrentLine (pLegend, iIndex) ;
  1273.    }  // LegendSetSelection   
  1274.  
  1275.  
  1276.  
  1277. #ifdef KEEP_PRINT
  1278.  
  1279. void PrintLegend (HDC hDC, PGRAPHSTRUCT pGraph, HWND hWndLegend,
  1280.                   RECT rectLegend)
  1281.    {
  1282.    PLEGEND        pLegend ;
  1283.    int            yItemHeight ;
  1284.    HFONT          hFontItems ;
  1285.    PLINE          pLine ;
  1286.    int            iIndex ;
  1287.    int            iIndexNum ;
  1288.  
  1289.  
  1290.    pLegend = LegendData (hWndLegend) ;
  1291.  
  1292.    yItemHeight = pLegend->yItemHeight ;
  1293.    hFontItems = pLegend->hFontItems ;
  1294.  
  1295.    pLegend->hFontItems = hFontPrinterScales ;
  1296.    SelectFont (hDC, pLegend->hFontItems) ;
  1297.  
  1298.    pLegend->yItemHeight = FontHeight (hDC, TRUE) ;
  1299.  
  1300.    iIndexNum = LBNumItems (pLegend->hWndItems) ;
  1301.    for (iIndex = 0 ;
  1302.         iIndex < iIndexNum ;
  1303.         iIndex++)
  1304.       {  // for
  1305.       pLine = (PLINE) LBData (pLegend->hWndItems, iIndex) ;
  1306.       DrawLegendItem (pLegend, pLine, iIndex * pLegend->yItemHeight, hDC) ;
  1307.       }  // for
  1308.  
  1309.    pLegend->hFontItems = hFontItems ;
  1310.    pLegend->yItemHeight = yItemHeight ;
  1311.  
  1312.  
  1313.    SelectBrush (hDC, GetStockObject (HOLLOW_BRUSH)) ;
  1314.    SelectPen (hDC, GetStockObject (BLACK_PEN)) ;
  1315.    Rectangle (hDC, 0, 0, 
  1316.               rectLegend.right - rectLegend.left,
  1317.               rectLegend.bottom - rectLegend.top) ;
  1318.    }
  1319. #endif
  1320.  
  1321.  
  1322. void ClearLegend (HWND hWndLegend)
  1323.    {
  1324.    PLEGEND        pLegend ;
  1325.  
  1326.    pLegend = LegendData (hWndLegend) ;
  1327.    if (!pLegend)
  1328.       return ;
  1329.  
  1330.    LBReset (pLegend->hWndItems) ;
  1331.    pLegend->pCurrentLine = NULL ;
  1332.    }
  1333.  
  1334. void LegendSetRedraw (HWND hWndLegend, BOOL bRedraw)
  1335.    {
  1336.    PLEGEND        pLegend ;
  1337.  
  1338.    pLegend = LegendData (hWndLegend) ;
  1339.    if (!pLegend)
  1340.       return ;
  1341.  
  1342.    LBSetRedraw (pLegend->hWndItems, bRedraw) ;
  1343. }
  1344.  
  1345.  
  1346.