home *** CD-ROM | disk | FTP | other *** search
- //==========================================================================//
- // Includes //
- //==========================================================================//
-
-
- #include <stdio.h>
- #include "perfmon.h"
- #include "grafdisp.h" // external declarations for this file
-
- #include "grafdata.h" // for InsertGraph, et al.
- #include "graph.h"
- #include "legend.h"
- #include "line.h" // for LineCreatePen
- #include "perfmops.h" // for DoWindowDrag
- #include "playback.h" // for PlayingBackLog
- #include "valuebar.h"
- #include "utils.h"
- #include "timeline.h" // for IsTLineWindowUp & TLineRedraw
- #include "counters.h" // for CounterEntry
-
- //==========================================================================//
- // Constants //
- //==========================================================================//
-
- // this macro is used in doing a simple DDA (Digital Differential Analyzer)
- // * 10 + 5 is to make the result round up with .5
- #define DDA_DISTRIBUTE(TotalTics, numOfData) \
- ((TotalTics * 10 / numOfData) + 5) / 10
-
- HDC hGraphDisplayDC ;
- //=============================//
- // GraphDisplay Class //
- //=============================//
-
-
- TCHAR szGraphDisplayWindowClass[] = TEXT("PerfChart") ;
- #define dwGraphDisplayClassStyle (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC)
- #define iGraphDisplayClassExtra (0)
- #define iGraphDisplayWindowExtra (0)
- #define dwGraphDisplayWindowStyle (WS_CHILD | WS_VISIBLE)
-
-
-
- //==========================================================================//
- // Local Functions //
- //==========================================================================//
- BOOL UpdateTimeLine (HDC hDC, PGRAPHSTRUCT pGraph, BOOL getLastTimeLocation) ;
-
- #if 0
- PGRAPHSTRUCT GraphData (HWND hWndGraphDisplay)
- /*
- Effect: Return the graph associated with graph display window
- hWndGraphData. At the present time, we only have one
- graph data window and one graph structure. In the
- future, we may have several of each. The graph structure
- is conceptually instance data of the graph display
- window. Use of this function allows for easier additions
- to the code.
- */
- {
- return (pGraphs) ;
- }
- #endif
-
- INT ScaleAndInvertY (FLOAT ey,
- PLINESTRUCT pLineStruct,
- PGRAPHSTRUCT pGraph)
- /*
- Effect: Given data value ey, scale and fit the value to fit
- within the graph data area of the window, considering
- the scale set for the line and the current size of the
- data rectangle.
- */
- { // ScaleAndInvertY
- INT yGraphDataHeight, // Height of graph area
- yInverted ; // Scaled & Inverted Y.
- FLOAT eppd,
- eyScaled ;
-
-
- // Take care of any scaling now, at output time.
- ey *= pLineStruct->eScale ;
-
- // Calculate the Cy of the graph area.
- yGraphDataHeight = pGraph->rectData.bottom - pGraph->rectData.top ;
-
- // Calculate the pixels per data point.
- eppd = (FLOAT) ((FLOAT) yGraphDataHeight / (FLOAT) pGraph->gOptions.iVertMax) ;
- eyScaled = eppd * ey ;
- yInverted = (INT) (((FLOAT) yGraphDataHeight) - eyScaled) ;
-
- yInverted += pGraph->rectData.top ;
-
- // Clamp the range to fit with in the graph portion of the windows
- yInverted = PinInclusive (yInverted,
- pGraph->rectData.top, pGraph->rectData.bottom) ;
- return (yInverted) ;
- } // ScaleAndInvertY
-
-
-
- BOOL DrawGrid (HDC hDC,
- PGRAPHSTRUCT pGraph,
- LPRECT lpRect,
- BOOL bForPaint)
- /*
- Effect: Draw the grid lines in the graph display window.
- These grid lines are in the graph data area only,
- which is indicated by pGraph->rectData.
-
- Called By: OnPaint only.
- */
- { // DrawGrid
- int iGrid, iLines ;
- int xGrid, yGrid ;
- POINT aPoints [4 * iGraphMaxTics] ;
- DWORD aCounts [2 * iGraphMaxTics] ;
- HPEN hPenPrevious ;
- int bottomAdjust ;
-
- if (!pGraph->gOptions.bHorzGridChecked &&
- !pGraph->gOptions.bVertGridChecked)
- return (FALSE) ;
-
-
- hPenPrevious = SelectPen (hDC, IsPrinterDC (hDC) ?
- GetStockObject (BLACK_PEN) : pGraph->hGridPen) ;
-
- iLines = 0 ;
-
- if (pGraph->gOptions.bHorzGridChecked)
- {
- for (iGrid = 1 ;
- iGrid < pGraph->yNumTics ;
- iGrid++)
- { // for
- yGrid = pGraph->ayTics[iGrid] + pGraph->rectData.top ;
- if (yGrid >= lpRect->top &&
- yGrid <= lpRect->bottom)
- { // if
- aPoints[2 * iLines].x = lpRect->left ;
- aPoints[2 * iLines].y = yGrid ;
- aPoints[2 * iLines + 1].x = lpRect->right ;
- aPoints[2 * iLines + 1].y = yGrid ;
-
- aCounts[iLines] = 2 ;
- iLines++ ;
- } // if
- } // for
- } // if
-
- if (pGraph->gOptions.bVertGridChecked)
- {
- bottomAdjust = lpRect->bottom + (bForPaint ? 1 : 0) ;
- for (iGrid = 1 ;
- iGrid < pGraph->xNumTics ;
- iGrid++)
- { // for
- xGrid = pGraph->axTics[iGrid] + pGraph->rectData.left ;
- if (xGrid >= lpRect->left &&
- xGrid <= lpRect->right)
- { // if
- aPoints[2 * iLines].x = xGrid ;
- aPoints[2 * iLines].y = lpRect->top ;
- aPoints[2 * iLines + 1].x = xGrid ;
- aPoints[2 * iLines + 1].y = bottomAdjust ;
-
- aCounts[iLines] = 2 ;
- iLines++ ;
- } // if
- } // for
- } // if
-
- if (iLines)
- PolyPolyline (hDC, aPoints, aCounts, iLines) ;
-
- SelectPen (hDC, hPenPrevious) ;
-
- return (TRUE) ;
- } // DrawGrid
-
-
-
- BOOL DrawBarChartData (HDC hDC,
- PGRAPHSTRUCT pGraph)
- { // DrawBarChartData
- PLINESTRUCT pLineStruct ;
- PFLOAT pDataPoints ;
- INT nLegendItems,
- cx,
- cxBar,
- xDataPoint,
- y ;
- RECT rectBar ;
- RECT rectBkgrnd ;
- HBRUSH hOldBrush ;
- FLOAT eValue ;
- PLINESTRUCT pCurrentLine ;
-
- // Determine how many items are in the legend.
-
- nLegendItems = 0 ;
-
- for (pLineStruct = pGraph->pLineFirst ;
- pLineStruct ;
- pLineStruct = pLineStruct->pLineNext)
- { // for
- nLegendItems++ ;
- } // for
-
- if (nLegendItems == 0)
- return(FALSE) ;
-
- // get current select line for highlighting
- if (pGraph->HighLightOnOff)
- {
- pCurrentLine = CurrentGraphLine (hWndGraph) ;
- }
- else
- {
- pCurrentLine = NULL ;
- }
-
- // Determine the width of each bar.
- cx = pGraph->rectData.right - pGraph->rectData.left ;
-
-
- if (PlayingBackLog())
- {
- // get the average using the start and stop data point
- // from the log file
- PlaybackLines (pGraph->pSystemFirst,
- pGraph->pLineFirst,
- PlaybackLog.StartIndexPos.iPosition) ;
- PlaybackLines (pGraph->pSystemFirst,
- pGraph->pLineFirst,
- PlaybackLog.StopIndexPos.iPosition) ;
- }
- else
- {
- // Loop through all the DataLines and draw a bar for
- // it's last value.
- xDataPoint = pGraph->gKnownValue % pGraph->gMaxValues ;
- }
-
- rectBar.bottom = pGraph->rectData.bottom + 1 ;
-
- rectBkgrnd = pGraph->rectData ;
-
- hOldBrush = SelectBrush (hDC, hBrushFace) ;
-
- PatBlt (hDC,
- rectBkgrnd.left, rectBkgrnd.top,
- rectBkgrnd.right - rectBkgrnd.left,
- rectBkgrnd.bottom - rectBkgrnd.top + 1,
- PATCOPY) ;
- DrawGrid(hDC, pGraph, &(rectBkgrnd), FALSE) ;
-
- rectBar.right = pGraph->rectData.left ;
- for (pLineStruct = pGraph->pLineFirst ;
- pLineStruct ;
- pLineStruct = pLineStruct->pLineNext)
- { // for
- pDataPoints = pLineStruct->lnValues ;
-
- if (PlayingBackLog())
- {
- eValue = CounterEntry (pLineStruct) ;
- }
- else
- {
- eValue = pDataPoints[xDataPoint] ;
- }
-
-
- y = ScaleAndInvertY (eValue,
- pLineStruct,
- pGraph) ;
-
- rectBar.left = rectBar.right ;
- rectBar.top = y ;
-
- // nomore line to draw
- if (nLegendItems == 0 )
- {
- break ;
- }
-
- cxBar = DDA_DISTRIBUTE (cx, nLegendItems) ;
- rectBar.right = rectBar.left + cxBar ;
-
- // setup for next DDA
- nLegendItems-- ;
- cx -= cxBar ;
-
- // NOTE: this handle creation should be moved to line
- // create time.
-
- if (pCurrentLine == pLineStruct)
- {
- SetBkColor (hDC, crWhite) ;
- }
- else
- {
- SetBkColor (hDC, pLineStruct->Visual.crColor) ;
- }
- ExtTextOut (hDC, rectBar.right, rectBar.top, ETO_OPAQUE,
- &rectBar, NULL, 0, NULL) ;
- } // for
-
- return (TRUE) ;
- }
-
-
- /***************************************************************************
- * DrawTLGraphData - Draw Time Line Graph Data.
- *
- * Some notes about drawing the DataPoint graphs.
- *
- * 1] It's real expensive to make a GDI call. So, we do not
- * make a MoveToEx and LineTo call for each point. Instead
- * we create a polyline and send it down to GDI.
- *
- * 2] The X coordinates for each point in the polyline is generated
- * from our favorite xDataPoint to xWindows DDA.
- *
- * 3] The Y coordinate is generated from the pLineStruct->lnValues[x]
- * data associated with each line.
- ***************************************************************************/
- BOOL DrawTLGraphData (HDC hDC,
- BOOL bForPaint,
- PRECT prctPaint,
- PGRAPHSTRUCT pGraph)
- /*
- Called By: UpdateGraphDisplay only.
- */
- {
- PLINESTRUCT pLineStruct ;
- HPEN hPen = 0 ;
- HPEN hOldPen ;
- PFLOAT pDataPoints ;
- INT i, j,
- iValidValues,
- xDispDataPoint,
- xLeftLimit,
- xRightLimit ;
- PPOINT pptDataPoints ;
- INT numOfData, rectWidth, xPos ;
- PLINESTRUCT pCurrentLine ;
- INT DrawZeroPoint = 0 ;
-
- // SetBkColor (hDC, crLightGray) ;
-
- if (!IsPrinterDC (hDC))
- {
- if (bForPaint)
- {
- IntersectClipRect (hDC,
- pGraph->rectData.left,
- pGraph->rectData.top,
- pGraph->rectData.right,
- pGraph->rectData.bottom + 1) ;
- }
- else
- {
- IntersectClipRect (hDC,
- pGraph->rectData.left,
- pGraph->rectData.top,
- PlayingBackLog () ?
- pGraph->rectData.right :
- min (pGraph->rectData.right,
- pGraph->gTimeLine.xLastTime + 2),
- pGraph->rectData.bottom + 1) ;
- }
- }
-
- xLeftLimit = prctPaint->left - pGraph->gTimeLine.ppd - 1 ;
-
- if (bForPaint)
- xRightLimit = prctPaint->right + pGraph->gTimeLine.ppd ;
- else
- xRightLimit = prctPaint->right ;
-
- pptDataPoints = pGraph->pptDataPoints ;
-
- iValidValues = pGraph->gTimeLine.iValidValues ;
-
- if (!PlayingBackLog() &&
- pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
- {
- // drawing the 0th at the end of the chart.
- DrawZeroPoint = 1 ;
- if (iValidValues == pGraph->gMaxValues)
- {
- iValidValues++ ;
- }
- }
-
- // get current select line for highlighting
- if (pGraph->HighLightOnOff)
- {
- pCurrentLine = CurrentGraphLine (hWndGraph) ;
- }
- else
- {
- pCurrentLine = NULL ;
- }
-
- // loop through lines to plot
- for (pLineStruct = pGraph->pLineFirst ;
- pLineStruct || pCurrentLine;
- pLineStruct = pLineStruct->pLineNext)
- { // for
-
- if (pLineStruct == NULL)
- {
- // now draw the current line
- pLineStruct = pCurrentLine ;
- }
- else if (pLineStruct == pCurrentLine)
- {
- // skip this line and draw it later
- continue ;
- }
-
- // "Localize" some variables from the line data structure.
- pDataPoints = pLineStruct->lnValues ;
-
-
- rectWidth = pGraph->rectData.right - pGraph->rectData.left ;
- numOfData = pGraph->gMaxValues - 1 + DrawZeroPoint ;
-
- // Generate the polyline data.
- xDispDataPoint = pGraph->rectData.left ;
-
- // Only process points that lie within the update region.
- // Also only process points that have valid data.
- j = 0 ;
-
- for (i = 0 ; i < iValidValues ; i++)
- { // for
- if (xDispDataPoint > xRightLimit)
- {
- // we are done!
- break ;
- }
- if (xDispDataPoint >= xLeftLimit)
- {
- // It is within the limits, plot the point
- pptDataPoints[j].x = xDispDataPoint ;
- pptDataPoints[j].y = ScaleAndInvertY (
- (i == pGraph->gMaxValues) ? pDataPoints[0] : pDataPoints[i],
- pLineStruct,
- pGraph) ;
- j++ ;
- } // if
-
- // setup for the next point
- if (!numOfData)
- {
- // no more points to go
- break ;
- }
-
- xPos = DDA_DISTRIBUTE (rectWidth, numOfData) ;
- xDispDataPoint += xPos ;
- numOfData-- ;
- rectWidth -= xPos ;
- } // for i
-
- // only need to draw the line if there is point to draw.
- if (j > 0)
- {
- // Set the pen color and draw the polyline.
- if (IsPrinterDC (hDC))
- {
- hPen = LineCreatePen (hDC, &(pLineStruct->Visual), TRUE) ;
- hOldPen = SelectObject (hDC, hPen) ;
- }
- else
- {
- if (pCurrentLine == pLineStruct)
- {
- // highlight this line by turning it into White color
- hOldPen = SelectObject (hDC, hWhitePen) ;
- }
- else
- {
- SelectObject (hDC, pLineStruct->hPen) ;
- }
- }
-
- Polyline(hDC, pptDataPoints, j) ;
-
- if (hPen)
- {
- SelectObject (hDC, hOldPen) ;
-
- if (hPen != hWhitePen)
- {
- DeletePen (hPen) ;
- }
- hPen = 0 ;
- }
- }
-
- if (pCurrentLine == pLineStruct)
- {
- // We are done...
- break ;
- }
- } // for pLine
-
- if (IsTLineWindowUp())
- {
- // re-draw the timelines if need
- TLineRedraw (hDC, pGraph) ;
- }
-
- // reset the clipping region
- SelectClipRgn (hDC, pGraph->hGraphRgn) ;
-
- return (TRUE) ;
- } // DrawTLGraphData
-
-
-
- /***************************************************************************
- * bInitTimeLine - Initialize the fields of the time line structure.
- ***************************************************************************/
- BOOL bInitTimeLine(PGRAPHSTRUCT pGraph)
- {
-
- pGraph->gTimeLine.xLastTime = 0 ;
- pGraph->gTimeLine.ppd = 0 ;
- pGraph->gTimeLine.rppd = 0 ;
- pGraph->gTimeLine.iValidValues = 1 ;
-
- return (TRUE) ;
-
- }
-
-
- /***************************************************************************
- * Scale Time Line
- *
- * This routine should be called from the WM_SIZE message.
- * It does the scaling from the number of data points to the
- * size of the window.
- ***************************************************************************/
- void ScaleTimeLine (PGRAPHSTRUCT pGraph)
- {
- INT nDataPoints,
- cxClient ;
-
- // Calculate the pels per data point.
- nDataPoints = pGraph->gMaxValues - 1 ;
- cxClient = pGraph->rectData.right - pGraph->rectData.left ;
-
- // ppd = Pixels per DataPoint.
- // rppd = Remaining Pixels per DataPoint.
- pGraph->gTimeLine.ppd = cxClient / nDataPoints ;
- pGraph->gTimeLine.rppd = cxClient % nDataPoints ;
- }
-
-
- void DisplayTimeLine(HDC hDC, PGRAPHSTRUCT pGraph)
- /*
- Called By: OnPaint only.
-
- Assert: xDisplayPoint has been set by UpdateTimeLine on this
- same timer tick.
- */
- { // DisplayTimeLine
- INT xDisplayPoint ;
- RECT rect ;
-
- if (pGraph->gTimeLine.xLastTime == -1)
- {
- UpdateTimeLine (hGraphDisplayDC, pGraph, TRUE) ;
- }
-
- // xDisplayPoint is X coordinate to display the time line at.
- if ((xDisplayPoint = pGraph->gTimeLine.xLastTime) == 0)
- return ;
-
- SelectBrush (hDC, pGraph->hbRed) ;
-
- if (xDisplayPoint >= pGraph->rectData.right)
- {
- rect.left = pGraph->rectData.left ;
- }
- else
- {
- // rect.left = xDisplayPoint++ ;
- rect.left = xDisplayPoint ;
- }
- rect.top = pGraph->rectData.top ;
- rect.right = rect.left + 2 ;
- rect.bottom = pGraph->rectData.bottom ;
-
- // IntersectRect (&rect, &rect, &pGraph->rectData) ;
- if (rect.right > pGraph->rectData.right)
- {
- rect.right = pGraph->rectData.right ;
- }
- PatBlt (hDC,
- rect.left, rect.top,
- rect.right - rect.left,
- rect.bottom - rect.top + 1 ,
- PATCOPY) ;
-
- } // DisplayTimeLine
-
-
-
- int SuggestedNumTics (int iRange)
- /*
- Effect: Return an appropriate number of tic marks to display
- within iRange pixels.
-
- These numbers are empirically chosen for pleasing
- results.
- */
- { // SuggestedNumTics
- if (iRange < 20)
- return (0) ;
-
- if (iRange < 50)
- return (2) ;
-
- if (iRange < 100)
- return (4) ;
-
- if (iRange < 150)
- return (5) ;
-
- if (iRange < 300)
- return (10) ;
-
- if (iRange < 500)
- return (20) ;
-
- return (25) ;
- } // SuggestedNumTics
-
-
-
- void SetGridPositions (PGRAPHSTRUCT pGraph)
- { // SetGridPositions
- int xDataWidth ;
- int yDataHeight ;
-
- int iCurrentTicPixels ;
- int iNumTics ;
-
- int i ;
-
-
- //=============================//
- // Set number of Tics //
- //=============================//
-
- xDataWidth = pGraph->rectData.right - pGraph->rectData.left ;
- yDataHeight = pGraph->rectData.bottom - pGraph->rectData.top ;
-
- pGraph->xNumTics = PinInclusive (SuggestedNumTics (xDataWidth),
- 0, iGraphMaxTics) ;
- pGraph->yNumTics = PinInclusive (SuggestedNumTics (yDataHeight),
- 0, iGraphMaxTics) ;
-
- // if we have more tics than possible integral values, reduce the number
- // of tics.
- if (pGraph->gOptions.iVertMax < pGraph->yNumTics)
- pGraph->yNumTics = pGraph->gOptions.iVertMax ;
-
-
- //=============================//
- // Set X Tic Positions //
- //=============================//
-
- if (pGraph->xNumTics)
- {
- iNumTics = pGraph->xNumTics ;
-
- pGraph->axTics[0] = 0 ;
- for (i = 1 ;
- i < pGraph->xNumTics ;
- i++)
- { // for
- if (iNumTics == 0)
- {
- break ;
- }
- iCurrentTicPixels = DDA_DISTRIBUTE (xDataWidth, iNumTics) ;
- pGraph->axTics [i] = pGraph->axTics [i - 1] + iCurrentTicPixels ;
-
- xDataWidth -= iCurrentTicPixels ;
- iNumTics-- ;
- } // for
- } // if
-
-
- //=============================//
- // Set Y Tic Positions //
- //=============================//
-
- if (pGraph->yNumTics)
- {
- iNumTics = pGraph->yNumTics ;
-
- pGraph->ayTics[0] = 0 ;
- for (i = 1 ;
- i < pGraph->yNumTics ;
- i++)
- { // for
- if (iNumTics == 0)
- {
- break ;
- }
- iCurrentTicPixels = DDA_DISTRIBUTE (yDataHeight, iNumTics) ;
- pGraph->ayTics [i] = pGraph->ayTics [i- 1] + iCurrentTicPixels ;
-
- yDataHeight -= iCurrentTicPixels ;
- iNumTics-- ;
- } // for
- } // if
- } // SetGridPositions
-
-
-
- int GraphVerticalScaleWidth (HDC hDC,
- PGRAPHSTRUCT pGraph)
- {
- TCHAR szMaxValue [20] ;
- int xWidth ;
-
- if (!pGraph->gOptions.bLabelsChecked)
- return (0) ;
-
-
- // SelectFont (hDC, IsPrinterDC (hDC) ? hFontPrinterScales : hFontScales) ;
-
-
- TSPRINTF (szMaxValue, TEXT(" %1d "),
- pGraph->gOptions.iVertMax * 10 ) ;
-
- xWidth = TextWidth (hDC, szMaxValue) ;
-
- return (xWidth) ;
- }
-
-
-
- void DrawGraphScale (HDC hDC,
- PGRAPHSTRUCT pGraph)
- {
- TCHAR szScale [20] ;
-
- INT len,
- i,
- nLines,
- iUnitsPerLine ;
- FLOAT ePercentOfTotal ;
- FLOAT eDiff ;
- BOOL bUseFloatingPt = FALSE ;
-
- //=============================//
- // Draw Vertical Scale? //
- //=============================//
-
- if (!pGraph->gOptions.bLabelsChecked)
- return ;
-
- // Get the number of lines.
- nLines = pGraph->yNumTics ;
-
- // nLines may be zero if the screen size if getting too small
- if (nLines > 0)
- {
- // Calculate what percentage of the total each line represents.
- ePercentOfTotal = ((FLOAT) 1.0) / ((FLOAT) nLines) ;
-
- // Calculate the amount (number of units) of the Vertical max each
- // each line in the graph represents.
- iUnitsPerLine = (INT) ((FLOAT) pGraph->gOptions.iVertMax * ePercentOfTotal) ;
- ePercentOfTotal *= (FLOAT) pGraph->gOptions.iVertMax ;
- eDiff = (FLOAT)iUnitsPerLine - ePercentOfTotal ;
- if (eDiff < (FLOAT) 0.0)
- eDiff = -eDiff ;
-
- if (eDiff > (FLOAT) 0.1)
- bUseFloatingPt = TRUE ;
- }
-
- //=============================//
- // Set Drawing Attributes //
- //=============================//
-
- // SelectFont (hDC, IsPrinterDC (hDC) ? hFontPrinterScales : hFontScales) ;
- SetBkMode(hDC, TRANSPARENT) ;
- SetTextAlign (hDC, TA_TOP | TA_RIGHT) ;
- SelectObject(hDC, GetStockObject (BLACK_PEN)) ;
-
- // Set the background color to gray
- if (!IsPrinterDC (hDC))
- FillRect (hDC, &(pGraph->rectVertScale), hbLightGray) ;
-
- // TESTING TESTING
- #ifdef PERFMON_DEBUG
- GdiSetBatchLimit(1) ; // disable Batching
- #endif
-
- // Now Output each string.
- for (i = 0 ;
- i < nLines ;
- i++)
- { // for
- if (bUseFloatingPt)
- {
- len = TSPRINTF (szScale, TEXT("%1.1f"),
- (FLOAT)pGraph->gOptions.iVertMax - ((FLOAT)i *
- ePercentOfTotal)) ;
- ConvertDecimalPoint (szScale) ;
- }
- else
- {
- len = TSPRINTF (szScale, TEXT("%d"),
- pGraph->gOptions.iVertMax - (i * iUnitsPerLine)) ;
- }
- TextOut (hDC,
- pGraph->rectVertScale.right,
- pGraph->ayTics[i] +
- pGraph->rectData.top - HalfTextHeight,
- szScale,
- len) ;
- } // for
-
- // Output the "min value" separately.
- TextOut (hDC,
- pGraph->rectVertScale.right,
- pGraph->rectData.bottom - HalfTextHeight,
- TEXT("0"),
- 1) ;
-
- #ifdef PERFMON_DEBUG
- // TESTING TESTING
- GdiSetBatchLimit(0) ; // enable default Batching
- #endif
-
-
- } // DrawGraphScale
-
-
-
- void SizeGraphDisplayComponentsRect (HDC hDC,
- PGRAPHSTRUCT pGraph,
- RECT rectDisplay)
- { // SizeGraphDisplayComponentsRect
- int xScaleWidth ;
-
- if (!rectDisplay.right || !rectDisplay.bottom)
- return ;
-
- //=============================//
- // Size the Vertical Scale //
- //=============================//
-
- xScaleWidth = GraphVerticalScaleWidth (hDC, pGraph) ;
- pGraph->rectVertScale.left = rectDisplay.left ;
- pGraph->rectVertScale.top = rectDisplay.top ;
- pGraph->rectVertScale.right = rectDisplay.left + xScaleWidth ;
- pGraph->rectVertScale.bottom = rectDisplay.bottom ;
-
- //=============================//
- // Size the Horizontal Scale //
- //=============================//
-
- pGraph->rectHorzScale.left = 0 ;
- pGraph->rectHorzScale.top = 0 ;
- pGraph->rectHorzScale.right = 0 ;
- pGraph->rectHorzScale.bottom = 0 ;
-
- //=============================//
- // Size the Data Area //
- //=============================//
-
- pGraph->rectData.left = pGraph->rectVertScale.right + 3 + ThreeDPad ;
- pGraph->rectData.right = rectDisplay.right - 5 - ThreeDPad ;
- pGraph->rectData.top = rectDisplay.top + 5 + ThreeDPad ;
- pGraph->rectData.bottom = rectDisplay.bottom - 5 - ThreeDPad ;
-
- SetGridPositions (pGraph) ;
- ScaleTimeLine (pGraph) ;
-
- //==========================================//
- // Invalidate the last time line poisition //
- //==========================================//
- pGraph->gTimeLine.xLastTime = -1 ;
-
- if (pGraph->hGraphRgn)
- {
- DeleteObject (pGraph->hGraphRgn) ;
- }
-
- pGraph->hGraphRgn = CreateRectRgn (rectDisplay.left,
- rectDisplay.top,
- rectDisplay.right,
- rectDisplay.bottom) ;
-
- SelectClipRgn (hDC, pGraph->hGraphRgn) ;
-
- } // SizeGraphDisplayComponentsRect
-
-
- void SizeGraphDisplayComponents (HWND hWnd)
- /*
- Effect: Given the graph display window hWnd, of size
- (xWidth x yHeight), determine the size and position
- of the various graph display components: the vertical
- scale, the horizontal scale, and the data area.
-
- Called By: OnSize, any other routine that changes the visibility
- of a vertical or horizontal scale.
-
- Note: This function has multiple return points.
- */
- { // SizeGraphDisplayComponents
- PGRAPHSTRUCT pGraph ;
- RECT rectClient ;
-
- pGraph = GraphData (hWnd) ;
- GetClientRect (hWnd, &rectClient) ;
-
- SizeGraphDisplayComponentsRect (hGraphDisplayDC, pGraph, rectClient) ;
- }
-
-
- void UpdateGraphDisplay (HDC hDC,
- BOOL bForPaint,
- LPRECT lpRect,
- PGRAPHSTRUCT pGraph)
- /*
- Effect: Draw the portions of the graph that change as the
- graph's values change. This includes the background,
- the grid, the lines, and the timeline.
- */
- { // UpdateGraphDisplay
- RECT rectUpdate ;
-
- if (!bForPaint && !IsPrinterDC (hDC) &&
- pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
- {
- HBRUSH hOldBrush ;
-
- rectUpdate = pGraph->rectData ;
- rectUpdate.bottom += 1 ;
-
- IntersectRect (&rectUpdate, lpRect, &rectUpdate) ;
- hOldBrush = SelectBrush (hDC, hBrushFace) ;
-
- PatBlt (hDC,
- rectUpdate.left, rectUpdate.top,
- rectUpdate.right - rectUpdate.left,
- rectUpdate.bottom - rectUpdate.top,
- PATCOPY) ;
- }
- else
- {
- IntersectRect (&rectUpdate, lpRect, &pGraph->rectData) ;
- }
-
- if (pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
- {
- DrawGrid(hDC, pGraph, &rectUpdate, bForPaint) ;
- if (pGraph->pLineFirst != NULL)
- {
- DrawTLGraphData(hDC, bForPaint, &rectUpdate, pGraph) ;
- if (!PlayingBackLog ())
- DisplayTimeLine(hDC, pGraph) ;
- }
- }
- else
- {
- DrawBarChartData (hDC, pGraph) ;
- }
- } // UpdateGraphDisplay
-
-
- BOOL UpdateTimeLine (HDC hDC,
- PGRAPHSTRUCT pGraph,
- BOOL getLastTimeLocation)
- /*
- Called By: GraphTimer only.
-
- See Also: UpdateGraphDisplay.
- */
- {
- INT i,
- xDisplayPoint,
- xDataPoint ;
- RECT rctUpdate ;
- INT xLastTime ;
- INT rectWidth,
- xPos,
- numOfPoints ;
-
-
- if ((xLastTime = pGraph->gTimeLine.xLastTime) != 0)
- {
- if ((pGraph->gKnownValue % pGraph->gMaxValues) == 1)
- {
- // Data wrap around case
- rctUpdate.left = pGraph->rectData.left ;
- rctUpdate.right = pGraph->rectData.left +
- pGraph->gTimeLine.ppd + 1 ;
- }
- else
- {
- rctUpdate.left = xLastTime - pGraph->gTimeLine.ppd ;
- rctUpdate.right = xLastTime +
- pGraph->gTimeLine.ppd + 1 ;
- }
- rctUpdate.top = pGraph->rectData.top ;
- rctUpdate.bottom = pGraph->rectData.bottom + 1 ;
- }
-
- // Calculate where to draw the time line.
- // This is done by running a simple DDA (Digital Differential Analyzer)
- // We have to position the time depending upon the size of the
- // graph window. In essence we need to calculate the x display
- // coordinate.
-
- // Note we should wrap Known Value in UpdateGLData.
- // We should also use a data buffer of 256 bytes so we can
- // wrap with and AND.
-
- // xDataPoint = pGraph->gKnownValue ;
- xDataPoint = pGraph->gKnownValue % pGraph->gMaxValues ;
-
- xDisplayPoint = pGraph->rectData.left ;
-
- numOfPoints = pGraph->gMaxValues - 1 ;
-
- if (!PlayingBackLog() &&
- pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
- {
- // drawing the 0th at the end of the chart.
- // So, we do have gMaxValues points
- numOfPoints++ ;
- if ((pGraph->gKnownValue % pGraph->gMaxValues) == 0)
- {
- xDataPoint = pGraph->gMaxValues ;
- }
- }
-
- rectWidth = pGraph->rectData.right - pGraph->rectData.left ;
-
- for (i = 0 ; i < xDataPoint ; i++)
- {
- if (numOfPoints == 0)
- {
- break ;
- }
- xPos = DDA_DISTRIBUTE (rectWidth, numOfPoints) ;
- xDisplayPoint += xPos ;
- rectWidth -= xPos ;
- numOfPoints-- ;
- } // for
-
- pGraph->gTimeLine.xLastTime = xDisplayPoint ;
-
- if (!getLastTimeLocation && iPerfmonView == IDM_VIEWCHART && !bPerfmonIconic)
- {
- UpdateGraphDisplay (hDC, FALSE, &rctUpdate, pGraph) ;
- }
-
- return(TRUE) ;
- }
-
-
- //==========================================================================//
- // Message Handlers //
- //==========================================================================//
-
-
- void /*static*/ OnCreate (HWND hWnd)
- /*
- Effect: Perform all actions needed when a GraphDisplay window is
- created.
- In particular, initialize the graph instance data and
- create the child windows.
-
- Called By: GraphDisplayWndProc, in response to a WM_CREATE message.
- */
- { // OnCreate
- LOGBRUSH LogBrush ;
- TEXTMETRIC tmScales ;
-
- hGraphDisplayDC = GetDC(hWnd) ;
-
- SelectFont(hGraphDisplayDC, hFontScales) ;
- GetTextMetrics(hGraphDisplayDC, &tmScales) ;
- HalfTextHeight = tmScales.tmHeight / 2 ;
-
- SetBkColor (hGraphDisplayDC, crLightGray) ;
-
-
- InsertGraph(hWnd) ;
- bInitTimeLine(pGraphs) ;
-
- pGraphs->hWnd = hWnd ;
-
- // Create the brush and pen used by the time line.
- // We don't want to create these on every timer tick.
-
- LogBrush.lbStyle = BS_SOLID ;
- LogBrush.lbColor = RGB(0xff, 0, 0) ;
- LogBrush.lbHatch = 0 ;
-
- // Now get the system resources we use "all the time"
- pGraphs->hbRed = CreateBrushIndirect(&LogBrush) ;
- pGraphs->hGridPen = CreatePen (PS_SOLID, 1, crGray) ;
-
- pGraphs->xNumTics = 0 ;
- pGraphs->yNumTics = 0 ;
- } // OnCreate
-
-
- void /*static*/ OnSize (HWND hWnd,
- WORD xWidth,
- WORD yHeight)
- { // OnSize
- PGRAPHSTRUCT pGraph ;
-
- pGraph = GraphData (hWnd) ;
-
- SizeGraphDisplayComponents (hWnd) ;
- } // OnSize
-
-
- void /*static*/ OnPaint (HWND hWnd)
- {
- HDC hDC ;
- PAINTSTRUCT ps ;
- PGRAPHSTRUCT pGraph ;
-
- pGraph = GraphData (hWnd) ;
- hDC = BeginPaint(hWnd, &ps) ;
-
- DrawGraphDisplay (hDC, ps.rcPaint, pGraph) ;
-
- EndPaint(hWnd, &ps) ;
- } // OnPaint
-
-
- //==========================================================================//
- // Exported Functions //
- //==========================================================================//
-
- #ifdef KEEP_PRINT
- void PrintGraphDisplay (HDC hDC,
- PGRAPHSTRUCT pGraph)
- {
- DrawGraphScale (hDC, pGraph) ;
-
-
- //!! UpdateGraphDisplay (hDC, TRUE, &(pGraph->rectData), pGraph) ;
-
- IntersectClipRect (hDC, 0, 0, 10000, 10000) ;
- SelectBrush (hDC, GetStockObject (HOLLOW_BRUSH)) ;
- SelectPen (hDC, GetStockObject (BLACK_PEN)) ;
- Rectangle (hDC,
- pGraph->rectData.left,
- pGraph->rectData.top,
- pGraph->rectData.right,
- pGraph->rectData.bottom) ;
- } // PrintGraphDisplay
- #endif
-
-
-
- void DrawGraphDisplay (HDC hDC,
- RECT rectDraw,
- PGRAPHSTRUCT pGraph)
- {
- BOOL bPaintScale ;
- INT LocalThreeDPad = ThreeDPad - 1 ;
-
- // Only draw the vertical labels if the paint rectangle
- // any portion of the window to the left of the graph area.
-
- bPaintScale = (rectDraw.left <= pGraph->rectVertScale.right) ;
- if (bPaintScale)
- DrawGraphScale (hDC, pGraph) ;
- if (IsPrinterDC (hDC))
- Rectangle (hDC,
- pGraph->rectData.left,
- pGraph->rectData.top,
- pGraph->rectData.right,
- pGraph->rectData.bottom) ;
- else
- ThreeDConcave1 (hDC,
- pGraph->rectData.left - LocalThreeDPad,
- pGraph->rectData.top - LocalThreeDPad,
- pGraph->rectData.right + LocalThreeDPad,
- pGraph->rectData.bottom + LocalThreeDPad + 1) ;
-
- UpdateGraphDisplay (hDC, TRUE, &(rectDraw), pGraph) ;
- } // DrawGraphDisplay
-
-
- LRESULT APIENTRY GraphDisplayWndProc (HWND hWnd,
- UINT uMsg,
- WPARAM wParam,
- LPARAM lParam)
- { // GraphDisplayWndProc
- LONG lret = 0L ;
- BOOL bCallDefProc = FALSE ;
-
- switch (LOWORD (uMsg))
- {
- case WM_LBUTTONDOWN:
- DoWindowDrag (hWnd, lParam) ;
- break ;
-
- case WM_LBUTTONDBLCLK:
- SendMessage (hWndMain, uMsg, wParam, lParam) ;
- break ;
-
- case WM_CREATE:
- OnCreate (hWnd) ;
- break ;
-
- case WM_SIZE:
- OnSize (hWnd, LOWORD (lParam), HIWORD (lParam)) ;
- break ;
-
- case WM_DESTROY:
- KillTimer(hWndMain, GRAPH_TIMER_ID) ;
- break ;
-
- case WM_PAINT:
- OnPaint (hWnd) ;
- break ;
-
- case WM_TIMER:
- GraphTimer (hWnd, FALSE) ;
- break ;
-
- default:
- bCallDefProc = TRUE ;
- break ;
- } // switch
-
-
- if (bCallDefProc)
- {
- lret = DefWindowProc(hWnd, uMsg, wParam, lParam) ;
- }
- return (lret) ;
- }
-
-
- BOOL GraphDisplayInitializeApplication (void)
- { // GraphDisplayInitializeApplication
- WNDCLASS wc ;
-
- wc.style = dwGraphDisplayClassStyle ;
- wc.lpfnWndProc = (WNDPROC) GraphDisplayWndProc ;
- wc.hInstance = hInstance ;
- wc.cbClsExtra = iGraphDisplayWindowExtra ;
- wc.cbWndExtra = iGraphDisplayClassExtra ;
- wc.hIcon = NULL ;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
- wc.hbrBackground = hbLightGray ;
- wc.lpszMenuName = NULL ;
- wc.lpszClassName = (LPTSTR) szGraphDisplayWindowClass ;
-
- return (RegisterClass (&wc)) ;
- } // GraphDisplayInitializeApplication
-
-
-
- HWND CreateGraphDisplayWindow (HWND hWndGraph)
- {
- return (CreateWindow (szGraphDisplayWindowClass, // class
- NULL, // caption
- dwGraphDisplayWindowStyle, // window style
- 0, 0, // position
- 0, 0, // size
- hWndGraph, // parent window
- NULL, // menu
- hInstance, // program instance
- NULL)) ; // user-supplied data
- }
-
-
-
- BOOL ToggleGraphRefresh (HWND hWnd)
- { // ToggleGraphRefresh
- PGRAPHSTRUCT pGraph ;
-
- pGraph = GraphData (hWnd) ;
-
- if (pGraph->bManualRefresh)
- SetGraphTimer (pGraph) ;
- else
- ClearGraphTimer (pGraph) ;
-
- pGraph->bManualRefresh = !pGraph->bManualRefresh ;
- return (pGraph->bManualRefresh) ;
- } // ToggleGraphRefresh
-
- BOOL GraphRefresh (HWND hWnd)
- { // GraphRefresh
- PGRAPHSTRUCT pGraph ;
-
- pGraph = GraphData (hWnd) ;
-
- return (pGraph->bManualRefresh) ;
- } // GraphRefresh
-
-
- void GraphTimer (HWND hWnd,
- BOOL bForce)
- /*
- Effect: Handle any actions necessary when the graph display
- window hWnd receives a timer tick. In particular,
- update the graph display and update the status bar
- if it is showing.
-
- Called By: GraphDisplayWndProc, in response to a WM_TIMER message.
- */
- { // GraphTimer
- PGRAPHSTRUCT pGraph ;
-
- pGraph = GraphData (hWnd) ;
-
- if (!pGraph->pLineFirst)
- return ;
-
-
- if (bForce || !pGraph->bManualRefresh)
- {
-
-
- HandleGraphTimer () ;
-
- // If we are displaying a time-line graph then do the
- // calculations for the minimal update region.
- // If were doing a bar graph, then draw the
- // whole graph area.
-
- if (pGraph->gOptions.iGraphOrHistogram == LINE_GRAPH)
- UpdateTimeLine (hGraphDisplayDC, pGraph, FALSE) ;
- else
- DrawBarChartData (hGraphDisplayDC, pGraph) ;
-
- // Take care of the status bar window
- StatusTimer (hWndGraphStatus, FALSE) ;
-
- } // if
- } // GraphTimer
-
- // this routine set/reset the line highlight mode
- void ChartHighlight (void)
- {
- PGRAPHSTRUCT pGraph ;
-
-
- if (pGraph = GraphData (hWndGraph))
- {
- if (pGraph->pLineFirst)
- {
- // toggle the HightlightOnOff mode
- pGraph->HighLightOnOff = !pGraph->HighLightOnOff ;
- WindowInvalidate (hWndGraphDisplay) ;
- }
- else
- {
- // no line availble, just turn it off
- pGraph->HighLightOnOff = FALSE ;
- }
- }
- } // ChartHighlight
-