Annotation of mstools/samples/sdktools/perfmon/grafdisp.c, revision 1.1.1.1

1.1       root        1: //==========================================================================//
                      2: //                                  Includes                                //
                      3: //==========================================================================//
                      4: 
                      5: 
                      6: #include <stdio.h>
                      7: #include "perfmon.h"
                      8: #include "grafdisp.h"      // external declarations for this file
                      9: 
                     10: #include "grafdata.h"      // for InsertGraph, et al.
                     11: #include "graph.h"
                     12: #include "legend.h"
                     13: #include "line.h"          // for LineCreatePen
                     14: #include "perfmops.h"      // for DoWindowDrag
                     15: #include "playback.h"      // for PlayingBackLog
                     16: #include "valuebar.h"
                     17: #include "utils.h"
                     18: #include "timeline.h"      // for IsTLineWindowUp & TLineRedraw 
                     19: 
                     20: //==========================================================================//
                     21: //                                  Constants                               //
                     22: //==========================================================================//
                     23: 
                     24: // this macro is used in doing a simple DDA (Digital Differential Analyzer)
                     25: // * 10 + 5 is to make the result round up with .5
                     26: #define DDA_DISTRIBUTE(TotalTics, numOfData) \
                     27:    ((TotalTics * 10 / numOfData) + 5) / 10
                     28: 
                     29: HDC   hGraphDisplayDC ;
                     30: //=============================//
                     31: // GraphDisplay Class          //
                     32: //=============================//
                     33: 
                     34: 
                     35: TCHAR   szGraphDisplayWindowClass[] = TEXT("PerfmonGraphDisplayClass") ;
                     36: #define dwGraphDisplayClassStyle    (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC)
                     37: #define iGraphDisplayClassExtra     (0)
                     38: #define iGraphDisplayWindowExtra    (0)
                     39: #define dwGraphDisplayWindowStyle   (WS_CHILD | WS_VISIBLE)
                     40: 
                     41: 
                     42: 
                     43: //==========================================================================//
                     44: //                              Local Functions                             //
                     45: //==========================================================================//
                     46: BOOL UpdateTimeLine (HDC hDC, PGRAPHSTRUCT pGraph, BOOL getLastTimeLocation) ;
                     47: 
                     48: #if 0
                     49: PGRAPHSTRUCT GraphData (HWND hWndGraphDisplay)
                     50: /*
                     51:    Effect:        Return the graph associated with graph display window
                     52:                   hWndGraphData. At the present time, we only have one
                     53:                   graph data window and one graph structure. In the
                     54:                   future, we may have several of each. The graph structure
                     55:                   is conceptually instance data of the graph display
                     56:                   window. Use of this function allows for easier additions
                     57:                   to the code.
                     58: */
                     59:    {
                     60:    return (pGraphs) ;
                     61:    }
                     62: #endif
                     63: 
                     64: INT ScaleAndInvertY (FLOAT ey, 
                     65:                      PLINESTRUCT pLineStruct,
                     66:                      PGRAPHSTRUCT pGraph)
                     67: /*
                     68:    Effect:        Given data value ey, scale and fit the value to fit
                     69:                   within the graph data area of the window, considering
                     70:                   the scale set for the line and the current size of the
                     71:                   data rectangle.
                     72: */   
                     73:    {  // ScaleAndInvertY
                     74:    INT     yGraphDataHeight,               // Height of graph area
                     75:            yInverted ;                     // Scaled & Inverted Y.
                     76:    FLOAT   eppd,
                     77:            eyScaled ;
                     78: 
                     79: 
                     80:    // Take care of any scaling now, at output time.
                     81:    ey *= pLineStruct->eScale ;
                     82: 
                     83:    // Calculate the Cy of the graph area.
                     84:    yGraphDataHeight = pGraph->rectData.bottom - pGraph->rectData.top ;
                     85: 
                     86:    // Calculate the pixels per data point.
                     87:    eppd = (FLOAT) ((FLOAT) yGraphDataHeight / (FLOAT) pGraph->gOptions.iVertMax) ;
                     88:    eyScaled = eppd * ey ;
                     89:    yInverted = (INT) (((FLOAT) yGraphDataHeight) - eyScaled) ;
                     90: 
                     91:    yInverted += pGraph->rectData.top ;
                     92:    
                     93:    // Clamp the range to fit with in the graph portion of the windows
                     94:    yInverted = PinInclusive (yInverted, 
                     95:                              pGraph->rectData.top, pGraph->rectData.bottom) ;
                     96:    return (yInverted) ;
                     97:    }  // ScaleAndInvertY
                     98: 
                     99: 
                    100: 
                    101: BOOL DrawGrid (HDC hDC, 
                    102:                PGRAPHSTRUCT pGraph,
                    103:                LPRECT lpRect,
                    104:                BOOL bForPaint)
                    105: /*
                    106:    Effect:        Draw the grid lines in the graph display window.
                    107:                   These grid lines are in the graph data area only,
                    108:                   which is indicated by pGraph->rectData.
                    109: 
                    110:    Called By:     OnPaint only.
                    111: */
                    112:    {  // DrawGrid
                    113:    int            iGrid, iLines ;
                    114:    int            xGrid, yGrid ;
                    115:    POINT          aPoints [4 * iGraphMaxTics] ;
                    116:    DWORD          aCounts [2 * iGraphMaxTics] ;
                    117:    HPEN           hPenPrevious ;
                    118:    int            bottomAdjust ;
                    119: 
                    120:    if (!pGraph->gOptions.bHorzGridChecked && 
                    121:        !pGraph->gOptions.bVertGridChecked)   
                    122:       return (FALSE) ;
                    123: 
                    124: 
                    125:    hPenPrevious = SelectPen (hDC, IsPrinterDC (hDC) ?
                    126:       GetStockObject (BLACK_PEN) : pGraph->hGridPen) ;
                    127: 
                    128:    iLines = 0 ;
                    129: 
                    130:    if (pGraph->gOptions.bHorzGridChecked)
                    131:       {
                    132:       for (iGrid = 1 ;
                    133:            iGrid < pGraph->yNumTics ;
                    134:            iGrid++)
                    135:          {  // for
                    136:          yGrid = pGraph->ayTics[iGrid] + pGraph->rectData.top ;
                    137:          if (yGrid >= lpRect->top &&
                    138:              yGrid <= lpRect->bottom)
                    139:             {  // if
                    140:             aPoints[2 * iLines].x = lpRect->left ;
                    141:             aPoints[2 * iLines].y = yGrid ;
                    142:             aPoints[2 * iLines + 1].x = lpRect->right ;
                    143:             aPoints[2 * iLines + 1].y = yGrid ;
                    144: 
                    145:             aCounts[iLines] = 2 ;
                    146:             iLines++ ;
                    147:             }  // if
                    148:          }  // for
                    149:       }  // if
                    150: 
                    151:    if (pGraph->gOptions.bVertGridChecked)
                    152:       {
                    153:       bottomAdjust = lpRect->bottom + (bForPaint ? 1 : 0) ;
                    154:       for (iGrid = 1 ;
                    155:            iGrid < pGraph->xNumTics ;
                    156:            iGrid++)
                    157:          {  // for
                    158:          xGrid = pGraph->axTics[iGrid] + pGraph->rectData.left ;
                    159:          if (xGrid >= lpRect->left &&
                    160:              xGrid <= lpRect->right)
                    161:             {  // if
                    162:             aPoints[2 * iLines].x = xGrid ;
                    163:             aPoints[2 * iLines].y = lpRect->top ;
                    164:             aPoints[2 * iLines + 1].x = xGrid ;
                    165:             aPoints[2 * iLines + 1].y = bottomAdjust ;
                    166: 
                    167:             aCounts[iLines] = 2 ;
                    168:             iLines++ ;
                    169:             }  // if
                    170:          }  // for
                    171:       }  // if
                    172: 
                    173:    if (iLines)
                    174:       PolyPolyline (hDC, aPoints, aCounts, iLines) ;
                    175: 
                    176:    SelectPen (hDC, hPenPrevious) ;
                    177: 
                    178:    return (TRUE) ;
                    179:    }  // DrawGrid
                    180: 
                    181: 
                    182: 
                    183: BOOL DrawBarChartData (HDC hDC, 
                    184:                        PGRAPHSTRUCT pGraph)
                    185:    {  // DrawBarChartData
                    186:    PLINESTRUCT pLineStruct ;
                    187:    PFLOAT      pDataPoints ;
                    188:    INT         nLegendItems,
                    189:                cx,
                    190:                cxBar,
                    191:                xDataPoint,
                    192:                y ;
                    193:    RECT        rectBar ;
                    194:    RECT        rectBkgrnd ;
                    195:    HBRUSH      hOldBrush ;
                    196:    FLOAT       eValue ;
                    197:    PLINESTRUCT pCurrentLine ;
                    198: 
                    199:    // Determine how many items are in the legend.
                    200: 
                    201:    nLegendItems = 0 ;
                    202: 
                    203:    for (pLineStruct = pGraph->pLineFirst ;
                    204:         pLineStruct ;
                    205:         pLineStruct = pLineStruct->pLineNext)
                    206:       {  // for
                    207:       nLegendItems++ ;
                    208:       }  // for
                    209: 
                    210:    if (nLegendItems == 0)
                    211:       return(FALSE) ;
                    212: 
                    213:    // get current select line for highlighting
                    214:    if (pGraph->HighLightOnOff)
                    215:       {
                    216:       pCurrentLine = CurrentGraphLine (hWndGraph) ;
                    217:       }
                    218:    else
                    219:       {
                    220:       pCurrentLine = NULL ;
                    221:       }
                    222: 
                    223:    // Determine the width of each bar.
                    224:    cx = pGraph->rectData.right - pGraph->rectData.left ;
                    225: 
                    226: 
                    227:    if (PlayingBackLog())
                    228:       {
                    229:       // get the average using the start and stop data point 
                    230:       // from the log file
                    231:       PlaybackLines (pGraph->pSystemFirst, 
                    232:                      pGraph->pLineFirst, 
                    233:                      PlaybackLog.StartIndexPos.iPosition) ;
                    234:       PlaybackLines (pGraph->pSystemFirst, 
                    235:                      pGraph->pLineFirst, 
                    236:                      PlaybackLog.StopIndexPos.iPosition) ;
                    237:       }
                    238:    else
                    239:       {
                    240:       // Loop through all the DataLines and draw a bar for
                    241:       // it's last value.
                    242:       xDataPoint = pGraph->gKnownValue % pGraph->gMaxValues ;
                    243:       }
                    244: 
                    245:    rectBar.bottom = pGraph->rectData.bottom + 1 ;
                    246: 
                    247:    rectBkgrnd = pGraph->rectData ;
                    248: 
                    249:    hOldBrush = SelectBrush (hDC, hBrushFace) ;
                    250: 
                    251:    PatBlt (hDC, 
                    252:            rectBkgrnd.left, rectBkgrnd.top,
                    253:            rectBkgrnd.right - rectBkgrnd.left,
                    254:            rectBkgrnd.bottom - rectBkgrnd.top + 1,
                    255:            PATCOPY) ;
                    256:    DrawGrid(hDC, pGraph, &(rectBkgrnd), FALSE) ;
                    257: 
                    258:    rectBar.right = pGraph->rectData.left ;
                    259:    for (pLineStruct = pGraph->pLineFirst ;
                    260:         pLineStruct ;
                    261:         pLineStruct = pLineStruct->pLineNext)
                    262:       {  // for
                    263:       pDataPoints = pLineStruct->lnValues ;
                    264: 
                    265:       if (PlayingBackLog())
                    266:          {
                    267:          eValue = (*(pLineStruct->valNext))(pLineStruct) ;
                    268:          }
                    269:       else
                    270:          {
                    271:          eValue = pDataPoints[xDataPoint] ;
                    272:          }
                    273: 
                    274: 
                    275:       y = ScaleAndInvertY (eValue,
                    276:                            pLineStruct,
                    277:                            pGraph) ;
                    278: 
                    279:       rectBar.left   = rectBar.right ;
                    280:       rectBar.top    = y ;
                    281: 
                    282:       // nomore line to draw
                    283:       if (nLegendItems == 0 )
                    284:          {
                    285:          break ;
                    286:          }
                    287: 
                    288:       cxBar = DDA_DISTRIBUTE (cx, nLegendItems) ;
                    289:       rectBar.right  = rectBar.left + cxBar ;
                    290: 
                    291:       // setup for next DDA
                    292:       nLegendItems-- ;
                    293:       cx -= cxBar ;
                    294: 
                    295:       // NOTE: this handle creation should be moved to line
                    296:       //       create time.
                    297: 
                    298:       if (pCurrentLine == pLineStruct)
                    299:          {
                    300:          SetBkColor (hDC, crWhite) ;
                    301:          }
                    302:       else
                    303:          {
                    304:          SetBkColor (hDC, pLineStruct->Visual.crColor) ;
                    305:          }
                    306:        ExtTextOut (hDC, rectBar.right, rectBar.top, ETO_OPAQUE,
                    307:          &rectBar, NULL, 0, NULL) ;
                    308:       }  // for
                    309: 
                    310:    return (TRUE) ;
                    311:    }
                    312: 
                    313: 
                    314: /***************************************************************************
                    315:  * DrawTLGraphData - Draw Time Line Graph Data.
                    316:  *
                    317:  *  Some notes about drawing the DataPoint graphs.
                    318:  *
                    319:  *      1]  It's real expensive to make a GDI call. So, we do not
                    320:  *          make a MoveToEx and LineTo call for each point.  Instead
                    321:  *          we create a polyline and send it down to GDI.
                    322:  *
                    323:  *      2]  The X coordinates for each point in the polyline is generated
                    324:  *          from our favorite xDataPoint to xWindows DDA.
                    325:  *
                    326:  *      3]  The Y coordinate is generated from the pLineStruct->lnValues[x]
                    327:  *          data associated with each line.
                    328:  ***************************************************************************/
                    329: BOOL DrawTLGraphData (HDC hDC, 
                    330:                       BOOL bForPaint,
                    331:                       PRECT prctPaint, 
                    332:                       PGRAPHSTRUCT pGraph)
                    333: /*
                    334:    Called By:     UpdateGraphDisplay only. 
                    335: */
                    336:    {
                    337:    PLINESTRUCT pLineStruct ;
                    338:    HPEN        hPen = 0 ;
                    339:    HPEN        hOldPen ;
                    340:    PFLOAT      pDataPoints ;
                    341:    INT         i, j,
                    342:                iValidValues,
                    343:                xDispDataPoint,
                    344:                xLeftLimit,
                    345:                xRightLimit ;
                    346:    PPOINT      pptDataPoints ;
                    347:    INT         numOfData, rectWidth, xPos ;
                    348:    PLINESTRUCT pCurrentLine ;
                    349:    INT         DrawZeroPoint = 0 ;
                    350: 
                    351: //   SetBkColor (hDC, crLightGray) ;
                    352: 
                    353:    if (!IsPrinterDC (hDC))
                    354:       {
                    355:       if (bForPaint)
                    356:          {
                    357:          IntersectClipRect (hDC, 
                    358:                             pGraph->rectData.left,
                    359:                             pGraph->rectData.top,
                    360:                             pGraph->rectData.right,
                    361:                             pGraph->rectData.bottom + 1) ;
                    362:          }
                    363:       else
                    364:          {
                    365:          IntersectClipRect (hDC, 
                    366:                             pGraph->rectData.left,
                    367:                             pGraph->rectData.top,
                    368:                             PlayingBackLog () ? 
                    369:                               pGraph->rectData.right :
                    370:                               min (pGraph->rectData.right,
                    371:                                    pGraph->gTimeLine.xLastTime + 2),
                    372:                             pGraph->rectData.bottom + 1) ;
                    373:          }
                    374:       }
                    375: 
                    376:    xLeftLimit  = prctPaint->left  - pGraph->gTimeLine.ppd - 1 ;
                    377: //   xRightLimit = prctPaint->right + pGraph->gTimeLine.ppd ;
                    378:    xRightLimit = prctPaint->right ;
                    379:    pptDataPoints  = pGraph->pptDataPoints ;
                    380: 
                    381:    iValidValues   = pGraph->gTimeLine.iValidValues ;
                    382: 
                    383:    if (!PlayingBackLog() &&
                    384:       pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
                    385:       {
                    386:       // drawing the 0th at the end of the chart.
                    387:       DrawZeroPoint = 1 ;
                    388:       if (iValidValues == pGraph->gMaxValues)
                    389:          {
                    390:          iValidValues++ ;
                    391:          }
                    392:       }
                    393: 
                    394:    // get current select line for highlighting
                    395:    if (pGraph->HighLightOnOff)
                    396:       {
                    397:       pCurrentLine = CurrentGraphLine (hWndGraph) ;
                    398:       }
                    399:    else
                    400:       {
                    401:       pCurrentLine = NULL ;
                    402:       }
                    403: 
                    404:    // loop through lines to plot
                    405:    for (pLineStruct = pGraph->pLineFirst ;
                    406:         pLineStruct || pCurrentLine;
                    407:         pLineStruct = pLineStruct->pLineNext)
                    408:       {  // for
                    409: 
                    410:       if (pLineStruct == NULL)
                    411:          {
                    412:          // now draw the current line
                    413:          pLineStruct = pCurrentLine ;
                    414:          }
                    415:       else if (pLineStruct == pCurrentLine)
                    416:          {
                    417:          // skip this line and draw it later
                    418:          continue ;
                    419:          }
                    420: 
                    421:       // "Localize" some variables from the line data structure.
                    422:       pDataPoints    = pLineStruct->lnValues ;
                    423: 
                    424: 
                    425:       rectWidth      = pGraph->rectData.right - pGraph->rectData.left ;
                    426:       numOfData      = pGraph->gMaxValues - 1 + DrawZeroPoint ;
                    427: 
                    428:       // Generate the polyline data.
                    429:       xDispDataPoint = pGraph->rectData.left ;
                    430: 
                    431:       // Only process points that lie within the update region.
                    432:       // Also only process points that have valid data.
                    433:       j = 0 ;
                    434: 
                    435:       for (i = 0 ; i < iValidValues ; i++)
                    436:          {  // for
                    437:          if (xDispDataPoint > xRightLimit)
                    438:             {
                    439:             // we are done!
                    440:             break ;
                    441:             }
                    442:          if (xDispDataPoint >= xLeftLimit)
                    443:             {
                    444:             // It is within the limits, plot the point
                    445:             pptDataPoints[j].x = xDispDataPoint ;
                    446:             pptDataPoints[j].y = ScaleAndInvertY (
                    447:                (i == pGraph->gMaxValues) ? pDataPoints[0] : pDataPoints[i],
                    448:                pLineStruct,
                    449:                pGraph) ;
                    450:             j++ ;
                    451:             }  // if
                    452: 
                    453:          // setup for the next point
                    454:          if (!numOfData)
                    455:             {
                    456:             // no more points to go
                    457:             break ;
                    458:             }
                    459: 
                    460:          xPos = DDA_DISTRIBUTE (rectWidth, numOfData) ;
                    461:          xDispDataPoint += xPos ;
                    462:          numOfData-- ;
                    463:          rectWidth -= xPos ;
                    464:          }  // for i
                    465: 
                    466:       // only need to draw the line if there is point to draw.
                    467:       if (j > 0)
                    468:          {
                    469:          // Set the pen color and draw the polyline.
                    470:          if (IsPrinterDC (hDC))
                    471:             {
                    472:             hPen = LineCreatePen (hDC, &(pLineStruct->Visual), TRUE) ;
                    473:             hOldPen = SelectObject (hDC, hPen) ;
                    474:             }
                    475:          else
                    476:             {
                    477:             if (pCurrentLine == pLineStruct)
                    478:                {
                    479:                // highlight this line by turning it into White color
                    480:                hOldPen = SelectObject (hDC, hWhitePen) ;
                    481:                }
                    482:             else
                    483:                {
                    484:                SelectObject (hDC, pLineStruct->hPen) ;
                    485:                }
                    486:             }
                    487: 
                    488:          Polyline(hDC, pptDataPoints, j) ;
                    489: 
                    490:          if (hPen)
                    491:             {
                    492:             SelectObject (hDC, hOldPen) ;
                    493: 
                    494:             if (hPen != hWhitePen)
                    495:                {
                    496:                DeletePen (hPen) ;
                    497:                }
                    498:             hPen = 0 ;
                    499:             }
                    500:          }
                    501: 
                    502:       if (pCurrentLine == pLineStruct)
                    503:          {
                    504:          // We are done...
                    505:          break ;
                    506:          }
                    507:       }  // for pLine
                    508: 
                    509:    if (IsTLineWindowUp())
                    510:       {
                    511:       // re-draw the timelines if need
                    512:       TLineRedraw (hDC, pGraph) ;
                    513:       }
                    514: 
                    515:    // reset the clipping region
                    516:    SelectClipRgn (hDC, pGraph->hGraphRgn) ;
                    517: 
                    518:    return (TRUE) ;
                    519:    }  // DrawTLGraphData
                    520: 
                    521: 
                    522: 
                    523: /***************************************************************************
                    524:  * bInitTimeLine - Initialize the fields of the time line structure.
                    525:  ***************************************************************************/
                    526: BOOL bInitTimeLine(PGRAPHSTRUCT pGraph)
                    527: {
                    528: 
                    529:         pGraph->gTimeLine.xLastTime      = 0 ;
                    530:         pGraph->gTimeLine.ppd            = 0 ;
                    531:         pGraph->gTimeLine.rppd           = 0 ;
                    532:         pGraph->gTimeLine.iValidValues   = 1 ;
                    533: 
                    534:         return (TRUE) ;
                    535: 
                    536: }
                    537: 
                    538: 
                    539: /***************************************************************************
                    540:  * Scale Time Line
                    541:  *
                    542:  *  This routine should be called from the WM_SIZE message.
                    543:  *  It does the scaling from the number of data points to the
                    544:  *  size of the window.
                    545:  ***************************************************************************/
                    546: void ScaleTimeLine (PGRAPHSTRUCT pGraph)
                    547:    {
                    548:    INT     nDataPoints,
                    549:            cxClient ;
                    550: 
                    551:    // Calculate the pels per data point.
                    552:    nDataPoints = pGraph->gMaxValues - 1 ;
                    553:    cxClient    = pGraph->rectData.right - pGraph->rectData.left ;
                    554: 
                    555:    // ppd  = Pixels per DataPoint.
                    556:    // rppd = Remaining Pixels per DataPoint.
                    557:    pGraph->gTimeLine.ppd  = cxClient / nDataPoints ;
                    558:    pGraph->gTimeLine.rppd = cxClient % nDataPoints ;
                    559:    }
                    560: 
                    561: 
                    562: void DisplayTimeLine(HDC hDC, PGRAPHSTRUCT pGraph)
                    563: /*
                    564:    Called By:     OnPaint only.
                    565: 
                    566:    Assert:        xDisplayPoint has been set by UpdateTimeLine on this
                    567:                   same timer tick.
                    568: */
                    569:    {  // DisplayTimeLine
                    570:    INT     xDisplayPoint ;
                    571:    RECT    rect ;
                    572: 
                    573:    if (pGraph->gTimeLine.xLastTime == -1)
                    574:       {
                    575:       UpdateTimeLine (hGraphDisplayDC, pGraph, TRUE) ;
                    576:       }
                    577: 
                    578:    // xDisplayPoint is X coordinate to display the time line at.
                    579:    if ((xDisplayPoint = pGraph->gTimeLine.xLastTime) == 0)
                    580:       return ;
                    581: 
                    582:    SelectBrush (hDC, pGraph->hbRed) ;
                    583: 
                    584:    if (xDisplayPoint >= pGraph->rectData.right)
                    585:       {
                    586:       rect.left   = pGraph->rectData.left ;
                    587:       }
                    588:    else
                    589:       {
                    590: //      rect.left   = xDisplayPoint++ ;
                    591:       rect.left   = xDisplayPoint ;
                    592:       }
                    593:    rect.top    = pGraph->rectData.top ;
                    594:    rect.right  = rect.left + 2 ;
                    595:    rect.bottom = pGraph->rectData.bottom ;
                    596: 
                    597: //   IntersectRect (&rect, &rect, &pGraph->rectData) ;
                    598:    if (rect.right > pGraph->rectData.right)
                    599:       {
                    600:       rect.right = pGraph->rectData.right ;
                    601:       }
                    602:    PatBlt (hDC, 
                    603:            rect.left, rect.top,
                    604:            rect.right - rect.left,
                    605:            rect.bottom - rect.top + 1 ,
                    606:            PATCOPY) ;
                    607:          
                    608:    }  // DisplayTimeLine
                    609: 
                    610: 
                    611: 
                    612: int SuggestedNumTics (int iRange)
                    613: /*
                    614:    Effect:        Return an appropriate number of tic marks to display
                    615:                   within iRange pixels.
                    616: 
                    617:                   These numbers are empirically chosen for pleasing 
                    618:                   results.
                    619: */
                    620:    {  // SuggestedNumTics
                    621:    if (iRange < 20)
                    622:       return (0) ;
                    623: 
                    624:    if (iRange < 50)
                    625:       return (2) ;
                    626: 
                    627:    if (iRange < 100)
                    628:       return (4) ;
                    629: 
                    630:    if (iRange < 150)
                    631:       return (5) ;
                    632: 
                    633:    if (iRange < 300)
                    634:       return (10) ;
                    635: 
                    636:    if (iRange < 500)
                    637:       return (20) ;
                    638: 
                    639:    return (25) ;
                    640:    }  // SuggestedNumTics
                    641: 
                    642: 
                    643: 
                    644: void SetGridPositions (PGRAPHSTRUCT pGraph)
                    645:    {  // SetGridPositions
                    646:    int            xDataWidth ;
                    647:    int            yDataHeight ;
                    648: 
                    649:    int            iCurrentTicPixels ;
                    650:    int            iNumTics ;
                    651: 
                    652:    int            i ;
                    653: 
                    654: 
                    655:    //=============================//
                    656:    // Set number of Tics          //
                    657:    //=============================//
                    658: 
                    659:    xDataWidth = pGraph->rectData.right - pGraph->rectData.left ;
                    660:    yDataHeight = pGraph->rectData.bottom - pGraph->rectData.top ;
                    661: 
                    662:    pGraph->xNumTics = PinInclusive (SuggestedNumTics (xDataWidth),
                    663:                                     0, iGraphMaxTics) ;
                    664:    pGraph->yNumTics = PinInclusive (SuggestedNumTics (yDataHeight),
                    665:                                     0, iGraphMaxTics) ;
                    666: 
                    667:    // if we have more tics than possible integral values, reduce the number
                    668:    // of tics.
                    669:    if (pGraph->gOptions.iVertMax < pGraph->yNumTics)
                    670:       pGraph->yNumTics = pGraph->gOptions.iVertMax ;
                    671: 
                    672: 
                    673:    //=============================//
                    674:    // Set X Tic Positions         //
                    675:    //=============================//
                    676: 
                    677:    if (pGraph->xNumTics)
                    678:       {
                    679:       iNumTics = pGraph->xNumTics ;
                    680: 
                    681:       pGraph->axTics[0] = 0 ;
                    682:       for (i = 1 ;
                    683:            i < pGraph->xNumTics ;
                    684:            i++)
                    685:          {  // for
                    686:          if (iNumTics == 0)
                    687:             {
                    688:             break ;
                    689:             }
                    690:          iCurrentTicPixels = DDA_DISTRIBUTE (xDataWidth, iNumTics) ;
                    691:          pGraph->axTics [i] = pGraph->axTics [i - 1] + iCurrentTicPixels ;
                    692: 
                    693:          xDataWidth -= iCurrentTicPixels ;
                    694:          iNumTics-- ;
                    695:          }  // for
                    696:       }  // if
                    697: 
                    698: 
                    699:    //=============================//
                    700:    // Set Y Tic Positions         //
                    701:    //=============================//
                    702: 
                    703:    if (pGraph->yNumTics)
                    704:       {
                    705:       iNumTics = pGraph->yNumTics ;
                    706: 
                    707:       pGraph->ayTics[0] = 0 ;
                    708:       for (i = 1 ;
                    709:            i < pGraph->yNumTics ;
                    710:            i++)
                    711:          {  // for
                    712:          if (iNumTics == 0)
                    713:             {
                    714:             break ;
                    715:             }
                    716:          iCurrentTicPixels = DDA_DISTRIBUTE (yDataHeight, iNumTics) ;
                    717:          pGraph->ayTics [i] = pGraph->ayTics [i- 1] + iCurrentTicPixels ;
                    718: 
                    719:          yDataHeight -= iCurrentTicPixels ;
                    720:          iNumTics-- ;
                    721:          }  // for
                    722:       }  // if
                    723:    }  // SetGridPositions
                    724: 
                    725: 
                    726: 
                    727: int GraphVerticalScaleWidth (HDC hDC,
                    728:                              PGRAPHSTRUCT pGraph)
                    729:    {
                    730:    TCHAR          szMaxValue [20] ;
                    731:    int            xWidth ;
                    732: 
                    733:    if (!pGraph->gOptions.bLabelsChecked)
                    734:       return (0) ;
                    735: 
                    736: 
                    737: //   SelectFont (hDC, IsPrinterDC (hDC) ? hFontPrinterScales : hFontScales) ;
                    738: 
                    739: 
                    740:    TSPRINTF (szMaxValue, TEXT(" %1d "),
                    741:             pGraph->gOptions.iVertMax * 10 ) ;
                    742: 
                    743:    xWidth = TextWidth (hDC, szMaxValue) ;
                    744: 
                    745:    return (xWidth) ;
                    746:    }
                    747: 
                    748: 
                    749: 
                    750: void DrawGraphScale (HDC hDC, 
                    751:                      PGRAPHSTRUCT pGraph)
                    752:    {
                    753:    TCHAR   szScale [20] ;
                    754: 
                    755:    INT     len,
                    756:            i,
                    757:            nLines,
                    758:            iUnitsPerLine ;
                    759:    FLOAT   ePercentOfTotal  ;
                    760:    FLOAT   eDiff ;
                    761:    BOOL    bUseFloatingPt = FALSE ;
                    762: 
                    763:    //=============================//
                    764:    // Draw Vertical Scale?        //
                    765:    //=============================//
                    766: 
                    767:    if (!pGraph->gOptions.bLabelsChecked)
                    768:        return ;
                    769: 
                    770:    // Get the number of lines.
                    771:    nLines = pGraph->yNumTics ;
                    772: 
                    773:    // Calculate what percentage of the total each line represents.
                    774:    ePercentOfTotal = ((FLOAT) 1.0) / ((FLOAT) nLines)  ;
                    775: 
                    776:    // Calculate the amount (number of units) of the Vertical max each
                    777:    // each line in the graph represents.
                    778:    iUnitsPerLine = (INT) ((FLOAT) pGraph->gOptions.iVertMax * ePercentOfTotal) ;
                    779:    ePercentOfTotal *= (FLOAT) pGraph->gOptions.iVertMax ;
                    780:    eDiff = (FLOAT)iUnitsPerLine - ePercentOfTotal ;
                    781:    if (eDiff < (FLOAT) 0.0)
                    782:       eDiff = -eDiff ;
                    783: 
                    784:    if (eDiff > (FLOAT) 0.1)
                    785:       bUseFloatingPt = TRUE ;
                    786: 
                    787:    //=============================//
                    788:    // Set Drawing Attributes      //
                    789:    //=============================//
                    790: 
                    791: //   SelectFont (hDC, IsPrinterDC (hDC) ? hFontPrinterScales : hFontScales) ;
                    792:    SetBkMode(hDC, TRANSPARENT) ;
                    793:    SetTextAlign (hDC, TA_TOP | TA_RIGHT) ;
                    794:    SelectObject(hDC, GetStockObject (BLACK_PEN)) ;
                    795: 
                    796:    // Set the background color to gray
                    797:    if (!IsPrinterDC (hDC))
                    798:       FillRect (hDC, &(pGraph->rectVertScale), hbLightGray) ;
                    799: 
                    800:    // Now Output each string.
                    801:    for (i = 0 ; 
                    802:         i < nLines ; 
                    803:         i++)
                    804:       {  // for
                    805:       if (bUseFloatingPt)
                    806:          {
                    807:          len = TSPRINTF (szScale, TEXT("%1.1f"),
                    808:             (FLOAT)pGraph->gOptions.iVertMax - ((FLOAT)i *
                    809:              ePercentOfTotal)) ;
                    810:          TextOut (hDC,
                    811:                   pGraph->rectVertScale.right,
                    812:                   pGraph->ayTics[i] +
                    813:                   pGraph->rectData.top - HalfTextHeight,
                    814:                   szScale,
                    815:                   lstrlen(szScale)) ;
                    816:          }
                    817:       else
                    818:          {
                    819:          len = TSPRINTF (szScale, TEXT("%d"),
                    820:                          pGraph->gOptions.iVertMax - (i * iUnitsPerLine)) ;
                    821:          TextOut (hDC,
                    822:                   pGraph->rectVertScale.right,
                    823:                   pGraph->ayTics[i] +
                    824:                   pGraph->rectData.top - HalfTextHeight,
                    825:                   szScale,
                    826:                   lstrlen(szScale)) ;
                    827:          }
                    828:       }  // for
                    829: 
                    830:    // Output the "min value" separately.
                    831:    TextOut (hDC, 
                    832:             pGraph->rectVertScale.right,
                    833:             pGraph->rectData.bottom - HalfTextHeight,
                    834:             TEXT("0"),
                    835:             1) ;
                    836:    }  // DrawGraphScale
                    837: 
                    838: 
                    839: 
                    840: void SizeGraphDisplayComponentsRect (HDC hDC,
                    841:                                      PGRAPHSTRUCT pGraph,
                    842:                                      RECT rectDisplay)
                    843:    {  // SizeGraphDisplayComponentsRect
                    844:    int            xScaleWidth ;
                    845: 
                    846:    if (!rectDisplay.right || !rectDisplay.bottom)
                    847:       return ;
                    848: 
                    849:    //=============================//
                    850:    // Size the Vertical Scale     //
                    851:    //=============================//
                    852: 
                    853:    xScaleWidth = GraphVerticalScaleWidth (hDC, pGraph) ;
                    854:    pGraph->rectVertScale.left = rectDisplay.left ;
                    855:    pGraph->rectVertScale.top = rectDisplay.top ;
                    856:    pGraph->rectVertScale.right = rectDisplay.left + xScaleWidth ;
                    857:    pGraph->rectVertScale.bottom = rectDisplay.bottom ;
                    858: 
                    859:    //=============================//
                    860:    // Size the Horizontal Scale   //
                    861:    //=============================//
                    862: 
                    863:    pGraph->rectHorzScale.left = 0 ;
                    864:    pGraph->rectHorzScale.top = 0 ;
                    865:    pGraph->rectHorzScale.right = 0 ;
                    866:    pGraph->rectHorzScale.bottom = 0 ;
                    867: 
                    868:    //=============================//
                    869:    // Size the Data Area          //
                    870:    //=============================//
                    871: 
                    872:    pGraph->rectData.left = pGraph->rectVertScale.right + 3 + ThreeDPad ;
                    873:    pGraph->rectData.right = rectDisplay.right - 5 - ThreeDPad ;
                    874:    pGraph->rectData.top = rectDisplay.top + 5 + ThreeDPad ;
                    875:    pGraph->rectData.bottom = rectDisplay.bottom - 5 - ThreeDPad ;
                    876: 
                    877:    SetGridPositions (pGraph) ;
                    878:    ScaleTimeLine (pGraph) ;
                    879: 
                    880:    //==========================================//
                    881:    // Invalidate the last time line poisition  //
                    882:    //==========================================//
                    883:    pGraph->gTimeLine.xLastTime = -1 ;
                    884: 
                    885:    if (pGraph->hGraphRgn)
                    886:       {
                    887:       DeleteObject (pGraph->hGraphRgn) ;
                    888:       }
                    889: 
                    890:    pGraph->hGraphRgn = CreateRectRgn (rectDisplay.left,
                    891:       rectDisplay.top,
                    892:       rectDisplay.right,
                    893:       rectDisplay.bottom) ;
                    894: 
                    895:    SelectClipRgn (hDC, pGraph->hGraphRgn) ;
                    896: 
                    897:    }  // SizeGraphDisplayComponentsRect
                    898: 
                    899: 
                    900: void SizeGraphDisplayComponents (HWND hWnd)
                    901: /*
                    902:    Effect:        Given the graph display window hWnd, of size 
                    903:                   (xWidth x yHeight), determine the size and position
                    904:                   of the various graph display components: the vertical
                    905:                   scale, the horizontal scale, and the data area.
                    906: 
                    907:    Called By:     OnSize, any other routine that changes the visibility
                    908:                   of a vertical or horizontal scale.
                    909: 
                    910:    Note:          This function has multiple return points.
                    911: */
                    912:    {  // SizeGraphDisplayComponents
                    913:    PGRAPHSTRUCT   pGraph ;
                    914:    RECT           rectClient ;
                    915: 
                    916:    pGraph = GraphData (hWnd) ;
                    917:    GetClientRect (hWnd, &rectClient) ;
                    918: 
                    919:    SizeGraphDisplayComponentsRect (hGraphDisplayDC, pGraph, rectClient) ;
                    920:    }
                    921: 
                    922: 
                    923: void UpdateGraphDisplay (HDC hDC,
                    924:                          BOOL bForPaint,
                    925:                          LPRECT lpRect,
                    926:                          PGRAPHSTRUCT pGraph)
                    927: /*
                    928:    Effect:        Draw the portions of the graph that change as the
                    929:                   graph's values change. This includes the background,
                    930:                   the grid, the lines, and the timeline.
                    931: */
                    932:    {  // UpdateGraphDisplay
                    933:    RECT           rectUpdate ;
                    934: 
                    935:    if (!bForPaint && !IsPrinterDC (hDC) && 
                    936:        pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
                    937:       {
                    938:       HBRUSH         hOldBrush ;
                    939: 
                    940:       rectUpdate = pGraph->rectData ;
                    941:       rectUpdate.bottom += 1 ;
                    942: 
                    943:       IntersectRect (&rectUpdate, lpRect, &rectUpdate) ;
                    944:       hOldBrush = SelectBrush (hDC, hBrushFace) ;
                    945: 
                    946:       PatBlt (hDC, 
                    947:               rectUpdate.left, rectUpdate.top,
                    948:               rectUpdate.right - rectUpdate.left,
                    949:               rectUpdate.bottom - rectUpdate.top,
                    950:               PATCOPY) ;
                    951:       }
                    952:    else
                    953:       {
                    954:       IntersectRect (&rectUpdate, lpRect, &pGraph->rectData) ;
                    955:       }
                    956:    
                    957:    if (pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
                    958:       {
                    959:       DrawGrid(hDC, pGraph, &rectUpdate, bForPaint) ;
                    960:       if (pGraph->pLineFirst != NULL)
                    961:           {
                    962:           DrawTLGraphData(hDC, bForPaint, &rectUpdate, pGraph) ;
                    963:           if (!PlayingBackLog ())
                    964:              DisplayTimeLine(hDC, pGraph) ;
                    965:           }
                    966:       }
                    967:    else
                    968:       {
                    969:       DrawBarChartData (hDC, pGraph) ;
                    970:       }
                    971:    }  // UpdateGraphDisplay
                    972: 
                    973:                     
                    974: BOOL UpdateTimeLine (HDC hDC, 
                    975:                      PGRAPHSTRUCT pGraph,
                    976:                      BOOL getLastTimeLocation)
                    977: /*
                    978:    Called By:     GraphTimer only.
                    979: 
                    980:    See Also:      UpdateGraphDisplay.
                    981: */
                    982:    {
                    983:    INT     i,
                    984:            xDisplayPoint,
                    985:            xDataPoint ;
                    986:    RECT    rctUpdate ;
                    987:    INT     xLastTime ;
                    988:    INT     rectWidth,
                    989:            xPos,
                    990:            numOfPoints ;
                    991: 
                    992: 
                    993:    if ((xLastTime = pGraph->gTimeLine.xLastTime) != 0)
                    994:       {
                    995:       if ((pGraph->gKnownValue % pGraph->gMaxValues) == 1)
                    996:          {
                    997:          // Data wrap around case
                    998:          rctUpdate.left   = pGraph->rectData.left ;
                    999:          rctUpdate.right  = pGraph->rectData.left +
                   1000:              pGraph->gTimeLine.ppd + 1 ;
                   1001:          }
                   1002:       else
                   1003:          {
                   1004:          rctUpdate.left   = xLastTime - pGraph->gTimeLine.ppd ;
                   1005:          rctUpdate.right  = xLastTime +
                   1006:              pGraph->gTimeLine.ppd + 1 ;
                   1007:          }
                   1008:       rctUpdate.top    = pGraph->rectData.top ;
                   1009:       rctUpdate.bottom = pGraph->rectData.bottom + 1 ;
                   1010:       }
                   1011: 
                   1012:    // Calculate where to draw the time line.
                   1013:    // This is done by running a simple DDA (Digital Differential Analyzer)
                   1014:    // We have to position the time depending upon the size of the
                   1015:    // graph window.  In essence we need to calculate the x display
                   1016:    // coordinate.
                   1017: 
                   1018:    // Note we should wrap Known Value in UpdateGLData.
                   1019:    // We should also use a data buffer of 256 bytes so we can
                   1020:    // wrap with and AND.
                   1021: 
                   1022:    // xDataPoint =  pGraph->gKnownValue ;
                   1023:    xDataPoint =  pGraph->gKnownValue % pGraph->gMaxValues ;
                   1024: 
                   1025:    xDisplayPoint = pGraph->rectData.left ;
                   1026: 
                   1027:    numOfPoints = pGraph->gMaxValues - 1 ;
                   1028: 
                   1029:    if (!PlayingBackLog() &&
                   1030:       pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
                   1031:       {
                   1032:       // drawing the 0th at the end of the chart.
                   1033:       // So, we do have gMaxValues points
                   1034:       numOfPoints++ ;
                   1035:       if ((pGraph->gKnownValue % pGraph->gMaxValues) == 0)
                   1036:          {
                   1037:          xDataPoint = pGraph->gMaxValues ;
                   1038:          }
                   1039:       }
                   1040: 
                   1041:    rectWidth = pGraph->rectData.right - pGraph->rectData.left ;
                   1042: 
                   1043:    for (i = 0 ; i < xDataPoint ; i++)
                   1044:       {
                   1045:       if (numOfPoints == 0)
                   1046:          {
                   1047:          break ;
                   1048:          }
                   1049:       xPos = DDA_DISTRIBUTE (rectWidth, numOfPoints) ;
                   1050:       xDisplayPoint += xPos ;
                   1051:       rectWidth -= xPos ;
                   1052:       numOfPoints-- ;
                   1053:       }  // for
                   1054: 
                   1055:    pGraph->gTimeLine.xLastTime = xDisplayPoint ;
                   1056: 
                   1057:    if (!getLastTimeLocation && iPerfmonView == IDM_VIEWCHART && !bPerfmonIconic)
                   1058:       {
                   1059:       UpdateGraphDisplay (hDC, FALSE, &rctUpdate, pGraph) ;
                   1060:       }
                   1061: 
                   1062:    return(TRUE) ;
                   1063:    }
                   1064: 
                   1065: 
                   1066: //==========================================================================//
                   1067: //                              Message Handlers                            //
                   1068: //==========================================================================//
                   1069: 
                   1070: 
                   1071: void /*static*/ OnCreate (HWND hWnd)
                   1072: /*
                   1073:    Effect:        Perform all actions needed when a GraphDisplay window is 
                   1074:                   created.
                   1075:                   In particular, initialize the graph instance data and
                   1076:                   create the child windows.
                   1077: 
                   1078:    Called By:     GraphDisplayWndProc, in response to a WM_CREATE message.
                   1079: */
                   1080:    {  // OnCreate
                   1081:    LOGBRUSH       LogBrush ;
                   1082:    TEXTMETRIC     tmScales ;
                   1083: 
                   1084:    hGraphDisplayDC = GetDC(hWnd) ;
                   1085: 
                   1086:    SelectFont(hGraphDisplayDC, hFontScales) ;
                   1087:    GetTextMetrics(hGraphDisplayDC, &tmScales) ;
                   1088:    HalfTextHeight = tmScales.tmHeight / 2 ;
                   1089: 
                   1090:    SetBkColor (hGraphDisplayDC, crLightGray) ;
                   1091: 
                   1092: 
                   1093:    InsertGraph(hWnd) ;
                   1094:    bInitTimeLine(pGraphs) ;
                   1095: 
                   1096:    pGraphs->hWnd = hWnd ;
                   1097: 
                   1098:    // Create the brush and pen used by the time line.
                   1099:    // We don't want to create these on every timer tick.
                   1100: 
                   1101:    LogBrush.lbStyle = BS_SOLID ;
                   1102:    LogBrush.lbColor = RGB(0xff, 0, 0) ;
                   1103:    LogBrush.lbHatch = 0 ;
                   1104: 
                   1105:    // Now get the system resources we use "all the time"
                   1106:    pGraphs->hbRed = CreateBrushIndirect(&LogBrush) ;
                   1107:    pGraphs->hGridPen = CreatePen (PS_SOLID, 1, crGray) ;
                   1108: 
                   1109:    pGraphs->xNumTics = 0 ;
                   1110:    pGraphs->yNumTics = 0 ;
                   1111:    }  // OnCreate
                   1112: 
                   1113: 
                   1114: void /*static*/ OnSize (HWND hWnd,
                   1115:                     WORD xWidth,
                   1116:                     WORD yHeight)
                   1117:    {  // OnSize
                   1118:    PGRAPHSTRUCT   pGraph ;
                   1119: 
                   1120:    pGraph = GraphData (hWnd) ;
                   1121: 
                   1122:    SizeGraphDisplayComponents (hWnd) ;
                   1123:    }  // OnSize
                   1124: 
                   1125: 
                   1126: void /*static*/ OnPaint (HWND hWnd)
                   1127:    {
                   1128:    HDC            hDC ;
                   1129:    PAINTSTRUCT    ps ;
                   1130:    PGRAPHSTRUCT   pGraph ;
                   1131: 
                   1132:    pGraph = GraphData (hWnd) ;
                   1133:    hDC = BeginPaint(hWnd, &ps) ;
                   1134: 
                   1135:    DrawGraphDisplay (hDC, ps.rcPaint, pGraph) ;
                   1136: 
                   1137:    EndPaint(hWnd, &ps) ;
                   1138:    }  // OnPaint
                   1139: 
                   1140: 
                   1141: //==========================================================================//
                   1142: //                             Exported Functions                           //
                   1143: //==========================================================================//
                   1144: 
                   1145: #ifdef KEEP_PRINT
                   1146: void PrintGraphDisplay (HDC hDC,
                   1147:                         PGRAPHSTRUCT pGraph)
                   1148:    {
                   1149:    DrawGraphScale (hDC, pGraph) ;
                   1150: 
                   1151: 
                   1152: //!!   UpdateGraphDisplay (hDC, TRUE, &(pGraph->rectData), pGraph) ;
                   1153: 
                   1154:    IntersectClipRect (hDC, 0, 0, 10000, 10000) ;
                   1155:    SelectBrush (hDC, GetStockObject (HOLLOW_BRUSH)) ;
                   1156:    SelectPen (hDC, GetStockObject (BLACK_PEN)) ;
                   1157:    Rectangle (hDC, 
                   1158:               pGraph->rectData.left,
                   1159:               pGraph->rectData.top,
                   1160:               pGraph->rectData.right,
                   1161:               pGraph->rectData.bottom) ;
                   1162:    }  // PrintGraphDisplay
                   1163: #endif
                   1164: 
                   1165: 
                   1166: 
                   1167: void DrawGraphDisplay (HDC hDC,
                   1168:                        RECT rectDraw,
                   1169:                        PGRAPHSTRUCT pGraph)
                   1170:    {
                   1171:    BOOL        bPaintScale ;
                   1172:    INT         LocalThreeDPad = ThreeDPad - 1 ;
                   1173: 
                   1174:    // Only draw the vertical labels if the paint rectangle
                   1175:    // any portion of the window to the left of the graph area.
                   1176: 
                   1177:    bPaintScale = (rectDraw.left <= pGraph->rectVertScale.right) ;
                   1178:    if (bPaintScale)
                   1179:       DrawGraphScale (hDC, pGraph) ;
                   1180:    if (IsPrinterDC (hDC))
                   1181:       Rectangle (hDC, 
                   1182:                  pGraph->rectData.left,
                   1183:                  pGraph->rectData.top,
                   1184:                  pGraph->rectData.right,
                   1185:                  pGraph->rectData.bottom) ;
                   1186:    else
                   1187:       ThreeDConcave1 (hDC, 
                   1188:                      pGraph->rectData.left - LocalThreeDPad,
                   1189:                      pGraph->rectData.top - LocalThreeDPad,
                   1190:                      pGraph->rectData.right + LocalThreeDPad,
                   1191:                      pGraph->rectData.bottom + LocalThreeDPad + 1) ;
                   1192: 
                   1193:    UpdateGraphDisplay (hDC, TRUE, &(rectDraw), pGraph) ;
                   1194:    }  // DrawGraphDisplay
                   1195: 
                   1196: 
                   1197: LRESULT APIENTRY GraphDisplayWndProc (HWND hWnd, 
                   1198:                                       UINT uMsg, 
                   1199:                                       WPARAM wParam,
                   1200:                                       LPARAM lParam)
                   1201:    {  // GraphDisplayWndProc
                   1202:    LONG        lret = 0L ;
                   1203:    BOOL        bCallDefProc = FALSE ;
                   1204: 
                   1205:    switch (LOWORD (uMsg))
                   1206:       {
                   1207:       case WM_LBUTTONDOWN:
                   1208:          DoWindowDrag (lParam) ;
                   1209:          break ;
                   1210: 
                   1211:       case WM_LBUTTONDBLCLK:
                   1212:          SendMessage (hWndMain, uMsg, wParam, lParam) ;
                   1213:          break ;
                   1214: 
                   1215:       case WM_CREATE:
                   1216:          OnCreate (hWnd) ;
                   1217:          break ;
                   1218: 
                   1219:       case WM_SIZE:
                   1220:          OnSize (hWnd, LOWORD (lParam), HIWORD (lParam)) ;
                   1221:          break ;
                   1222: 
                   1223:       case WM_DESTROY:
                   1224:          KillTimer(hWndMain, GRAPH_TIMER_ID) ;
                   1225:          break ;
                   1226: 
                   1227:       case WM_PAINT:
                   1228:          OnPaint (hWnd) ;
                   1229:          break ;
                   1230: 
                   1231:       case WM_TIMER:
                   1232:          GraphTimer (hWnd, FALSE) ;
                   1233:          break ;
                   1234: 
                   1235:       default:
                   1236:          bCallDefProc = TRUE ;
                   1237:          break ;
                   1238:       }  // switch
                   1239: 
                   1240: 
                   1241:    if (bCallDefProc)
                   1242:       {
                   1243:       lret = DefWindowProc(hWnd, uMsg, wParam, lParam) ;
                   1244:       }
                   1245:    return (lret) ;
                   1246:    }
                   1247: 
                   1248: 
                   1249: BOOL GraphDisplayInitializeApplication (void)
                   1250:    {  // GraphDisplayInitializeApplication
                   1251:    WNDCLASS       wc ;
                   1252: 
                   1253:    wc.style         = dwGraphDisplayClassStyle ;
                   1254:    wc.lpfnWndProc   = (WNDPROC) GraphDisplayWndProc ;
                   1255:    wc.hInstance     = hInstance ;
                   1256:    wc.cbClsExtra    = iGraphDisplayWindowExtra ;
                   1257:    wc.cbWndExtra    = iGraphDisplayClassExtra ;
                   1258:    wc.hIcon         = NULL ;
                   1259:    wc.hCursor       = LoadCursor(NULL, IDC_ARROW) ;
                   1260:    wc.hbrBackground = hbLightGray ;
                   1261:    wc.lpszMenuName  = NULL ;
                   1262:    wc.lpszClassName = (LPTSTR) szGraphDisplayWindowClass ;
                   1263: 
                   1264:    return (RegisterClass (&wc)) ;
                   1265:    }  // GraphDisplayInitializeApplication
                   1266: 
                   1267: 
                   1268: 
                   1269: HWND CreateGraphDisplayWindow (HWND hWndGraph)
                   1270:    {
                   1271:    return (CreateWindow (szGraphDisplayWindowClass,   // class
                   1272:                          NULL,                        // caption
                   1273:                          dwGraphDisplayWindowStyle,   // window style
                   1274:                          0, 0,                        // position
                   1275:                          0, 0,                        // size
                   1276:                          hWndGraph,                   // parent window
                   1277:                          NULL,                        // menu
                   1278:                          hInstance,                  // program instance
                   1279:                          NULL)) ;                     // user-supplied data
                   1280:    }
                   1281: 
                   1282: 
                   1283: 
                   1284: BOOL ToggleGraphRefresh (HWND hWnd)
                   1285:    {  // ToggleGraphRefresh
                   1286:    PGRAPHSTRUCT   pGraph ;
                   1287: 
                   1288:    pGraph = GraphData (hWnd) ;
                   1289: 
                   1290:    if (pGraph->bManualRefresh)
                   1291:       SetGraphTimer (pGraph) ;
                   1292:    else
                   1293:       ClearGraphTimer (pGraph) ;
                   1294: 
                   1295:    pGraph->bManualRefresh = !pGraph->bManualRefresh ;
                   1296:    return (pGraph->bManualRefresh) ;
                   1297:    }  // ToggleGraphRefresh
                   1298: 
                   1299: BOOL GraphRefresh (HWND hWnd)
                   1300:    {  // GraphRefresh
                   1301:    PGRAPHSTRUCT   pGraph ;
                   1302: 
                   1303:    pGraph = GraphData (hWnd) ;
                   1304: 
                   1305:    return (pGraph->bManualRefresh) ;
                   1306:    }  // GraphRefresh
                   1307: 
                   1308: 
                   1309: void GraphTimer (HWND hWnd, 
                   1310:                  BOOL bForce)
                   1311: /*
                   1312:    Effect:        Handle any actions necessary when the graph display
                   1313:                   window hWnd receives a timer tick. In particular,
                   1314:                   update the graph display and update the status bar
                   1315:                   if it is showing.
                   1316: 
                   1317:    Called By:     GraphDisplayWndProc, in response to a WM_TIMER message.
                   1318: */
                   1319:    {  // GraphTimer
                   1320:    PGRAPHSTRUCT         pGraph ;
                   1321: 
                   1322:    pGraph = GraphData (hWnd) ;
                   1323: 
                   1324:    if (!pGraph->pLineFirst)
                   1325:       return ;
                   1326: 
                   1327: 
                   1328:    if (bForce || !pGraph->bManualRefresh)
                   1329:       {
                   1330: 
                   1331:    
                   1332:       HandleGraphTimer () ;
                   1333: 
                   1334:       // If we are displaying a time-line graph then do the
                   1335:       // calculations for the minimal update region.
                   1336:       // If were doing a bar graph, then draw the
                   1337:       // whole graph area.
                   1338: 
                   1339:       if (pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
                   1340:          UpdateTimeLine (hGraphDisplayDC, pGraph, FALSE) ;
                   1341:       else
                   1342:          DrawBarChartData (hGraphDisplayDC, pGraph) ;
                   1343: 
                   1344:       // Take care of the status bar window
                   1345:       StatusTimer (hWndGraphStatus, FALSE) ;
                   1346: 
                   1347:       }  // if
                   1348:    }  // GraphTimer
                   1349: 
                   1350: // this routine set/reset the line highlight mode
                   1351: void ChartHighlight (void)
                   1352:    {
                   1353:    PGRAPHSTRUCT         pGraph ;
                   1354: 
                   1355: 
                   1356:    if (pGraph = GraphData (hWndGraph))
                   1357:       {
                   1358:       if (pGraph->pLineFirst)
                   1359:          {
                   1360:          // toggle the HightlightOnOff mode
                   1361:          pGraph->HighLightOnOff = !pGraph->HighLightOnOff ;
                   1362:          WindowInvalidate (hWndGraphDisplay) ;
                   1363:          }
                   1364:       else
                   1365:          {
                   1366:          // no line availble, just turn it off
                   1367:          pGraph->HighLightOnOff = FALSE ;
                   1368:          }
                   1369:       }
                   1370:    }  // ChartHighlight
                   1371: 
                   1372: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.