|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.