mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
702 lines
17 KiB
702 lines
17 KiB
/*****************************************************************************
|
|
*
|
|
* Grafdata.c - This module handles the non-drawing functions of the graph,
|
|
* such as allocating linked structures and their memory, freeing it,
|
|
* unlinking, starting and stopping the timer,
|
|
* setting up the first graph (CPU), and all the numeric functions for
|
|
* the different counter types.
|
|
*
|
|
* Microsoft Confidential
|
|
* Copyright (c) 1992-1993 Microsoft Corporation
|
|
*
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
//==========================================================================//
|
|
// Includes //
|
|
//==========================================================================//
|
|
|
|
#include <stdio.h> // for sprintf
|
|
|
|
#include "setedit.h" // main perfmon declarations
|
|
#include "grafdata.h" // external declarations for this file
|
|
#include <float.h> // for FLT_MAX constant
|
|
|
|
#include "addline.h" // for AddLine, EditLine
|
|
#include "counters.h" // for Counter_Counter, et al.
|
|
#include "graph.h" // for SizeGraphComponents
|
|
#include "pmemory.h" // for MemoryXXX (mallloc-type) routines
|
|
#include "perfdata.h" // for UpdateLines
|
|
#include "legend.h"
|
|
#include "system.h" // for SystemGet
|
|
#include "utils.h"
|
|
#include "line.h" // for LineFree
|
|
// #include "valuebar.h" // for StatusTimer
|
|
|
|
#include "fileopen.h" // for FileGetName
|
|
#include "fileutil.h" // for FileRead...
|
|
#include "menuids.h" // for IDM_VIEWCHART
|
|
#include "perfmops.h" // for ExportFileHeader
|
|
#include "status.h" // for StatusLineReady
|
|
|
|
extern BOOL SaveFileHandler(HWND hWnd,DWORD type) ;
|
|
|
|
// 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
|
|
|
|
#define szSmallValueFormat TEXT("%10.3f")
|
|
#define szLargeValueFormat TEXT("%10.0f")
|
|
|
|
//==========================================================================//
|
|
// Local Data //
|
|
//==========================================================================//
|
|
|
|
|
|
|
|
|
|
//==========================================================================//
|
|
// Local Functions //
|
|
//==========================================================================//
|
|
|
|
|
|
/****************************************************************************
|
|
* eUpdateMinMaxAve -
|
|
****************************************************************************/
|
|
void eUpdateMinMaxAve (FLOAT eValue, PLINESTRUCT pLineStruct, INT iValidValues,
|
|
INT iTotalValidPoints, INT iDataPoint, INT gMaxPoints)
|
|
{
|
|
INT i ;
|
|
INT iDataNum = iTotalValidPoints ;
|
|
FLOAT eMin,
|
|
eMax,
|
|
eSum,
|
|
eNewValue ;
|
|
|
|
|
|
eMax = eMin = eValue ;
|
|
|
|
eSum = eValue ;
|
|
|
|
if (iValidValues == iTotalValidPoints)
|
|
{
|
|
for (i=0 ; i < iValidValues ; i++)
|
|
{
|
|
if (i == iDataPoint)
|
|
{
|
|
// skip the data point we are going to replace
|
|
continue ;
|
|
}
|
|
|
|
eNewValue = pLineStruct->lnValues[i] ;
|
|
|
|
eSum += eNewValue ;
|
|
|
|
if (eNewValue > eMax)
|
|
{
|
|
eMax = eNewValue ;
|
|
}
|
|
|
|
if (eNewValue < eMin)
|
|
{
|
|
eMin = eNewValue ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// special case when we start the new line in the middle of the chart
|
|
for (i = iDataPoint, iTotalValidPoints-- ;
|
|
iTotalValidPoints > 0 ;
|
|
iTotalValidPoints-- )
|
|
{
|
|
i-- ;
|
|
if (i < 0)
|
|
{
|
|
// for the wrap-around case..
|
|
i = gMaxPoints - 1 ;
|
|
}
|
|
|
|
if (i == iDataPoint)
|
|
{
|
|
// skip the data point we are going to replace
|
|
continue ;
|
|
}
|
|
eNewValue = pLineStruct->lnValues[i] ;
|
|
|
|
eSum += eNewValue ;
|
|
|
|
if (eNewValue > eMax)
|
|
{
|
|
eMax = eNewValue ;
|
|
}
|
|
|
|
if (eNewValue < eMin)
|
|
{
|
|
eMin = eNewValue ;
|
|
}
|
|
}
|
|
}
|
|
|
|
pLineStruct->lnMinValue = eMin ;
|
|
pLineStruct->lnMaxValue = eMax ;
|
|
|
|
if (iDataNum)
|
|
{
|
|
pLineStruct->lnAveValue = eSum / (FLOAT) iDataNum ;
|
|
}
|
|
else
|
|
{
|
|
pLineStruct->lnAveValue = (FLOAT) 0.0 ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOL HandleGraphTimer (void)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
VOID GetGraphConfig(PGRAPHSTRUCT pGraph)
|
|
{
|
|
|
|
LoadRefreshSettings(pGraph);
|
|
LoadLineGraphSettings(pGraph);
|
|
|
|
|
|
// Init the structure
|
|
pGraph->pLineFirst = NULL;
|
|
|
|
//NOTE: put the rest of this in Config
|
|
|
|
pGraph->gOptions.bLegendChecked = TRUE;
|
|
pGraph->gOptions.bMenuChecked = TRUE;
|
|
pGraph->gOptions.bLabelsChecked = TRUE;
|
|
pGraph->gOptions.bVertGridChecked = FALSE;
|
|
pGraph->gOptions.bHorzGridChecked = FALSE;
|
|
pGraph->gOptions.bStatusBarChecked = TRUE;
|
|
pGraph->gOptions.GraphVGrid = TRUE;
|
|
pGraph->gOptions.GraphHGrid = TRUE;
|
|
pGraph->gOptions.HistVGrid = TRUE;
|
|
pGraph->gOptions.HistHGrid = TRUE;
|
|
|
|
pGraph->gOptions.iGraphOrHistogram = LINE_GRAPH; // vs. BAR_GRAPH
|
|
pGraph->gOptions.iVertMax = DEF_GRAPH_VMAX;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL InsertGraph (HWND hWnd)
|
|
{
|
|
PGRAPHSTRUCT pGraph;
|
|
|
|
pGraph = MemoryAllocate (sizeof (GRAPHSTRUCT)) ;
|
|
if (!pGraph)
|
|
return (FALSE) ;
|
|
|
|
|
|
pGraphs = pGraph;
|
|
|
|
|
|
GetGraphConfig(pGraph);
|
|
pGraph->bManualRefresh = FALSE ;
|
|
|
|
pGraph->gMaxValues = DEFAULT_MAX_VALUES;
|
|
pGraph->pptDataPoints = NULL ;
|
|
|
|
pGraph->pDataTime = NULL ;
|
|
|
|
pGraph->hWnd = hWnd ;
|
|
pGraph->bModified = TRUE ; // creating a graph means it's been modified
|
|
|
|
pGraph->Visual.iColorIndex = 0 ;
|
|
pGraph->Visual.iWidthIndex = 0 ;
|
|
pGraph->Visual.iStyleIndex = 0 ;
|
|
|
|
return(TRUE) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL ChartInsertLine (PGRAPHSTRUCT pGraph,
|
|
PLINE pLine)
|
|
/*
|
|
Effect: Insert the line pLine into the graph pGraph and
|
|
allocate space for the graph's number of values.
|
|
|
|
Returns: Whether the line could be added and space allocated.
|
|
|
|
See Also: LineAllocate (line.c), ChartDeleteLine.
|
|
*/
|
|
{ // ChartInsertLine
|
|
PLINE pLineEquivalent ;
|
|
INT i ;
|
|
FLOAT *pTempPts;
|
|
HPEN tempPen ;
|
|
|
|
pGraph->bModified = TRUE ;
|
|
|
|
pLineEquivalent = FindEquivalentLine (pLine, pGraph->pLineFirst) ;
|
|
if (pLineEquivalent)
|
|
{
|
|
if (bMonitorDuplicateInstances) {
|
|
pLine->dwInstanceIndex = pLineEquivalent->dwInstanceIndex + 1;
|
|
} else {
|
|
pLineEquivalent->Visual = pLine->Visual ;
|
|
pLineEquivalent->iScaleIndex = pLine->iScaleIndex ;
|
|
pLineEquivalent->eScale = pLine->eScale ;
|
|
|
|
tempPen = pLineEquivalent->hPen ;
|
|
pLineEquivalent->hPen = pLine->hPen ;
|
|
pLine->hPen = tempPen ;
|
|
return FALSE ;
|
|
}
|
|
}
|
|
|
|
LineAppend (&pGraph->pLineFirst, pLine) ;
|
|
|
|
// Add the line to the legend, resize the legend window, and then
|
|
// select the new line as the current legend item. Do it in this
|
|
// sequence to avoid the legend scroll bar momentarily appearing and
|
|
// then disappearing, since the resize will obviate the scroll bar.
|
|
|
|
LegendAddItem (hWndGraphLegend, pLine) ;
|
|
|
|
if (!bDelayAddAction)
|
|
{
|
|
SizeGraphComponents (hWndGraph) ;
|
|
LegendSetSelection (hWndGraphLegend,
|
|
LegendNumItems (hWndGraphLegend) - 1) ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
} // ChartInsertLine
|
|
|
|
|
|
VOID ChartDeleteLine (PGRAPHSTRUCT pGraph,
|
|
PLINESTRUCT pLine)
|
|
{
|
|
PLINESTRUCT npLine;
|
|
|
|
|
|
pGraph->bModified = TRUE ;
|
|
|
|
if (pGraph->pLineFirst == pLine)
|
|
pGraph->pLineFirst = pLine->pLineNext;
|
|
else
|
|
{
|
|
for (npLine = pGraph->pLineFirst; npLine; npLine = npLine->pLineNext)
|
|
{
|
|
if (npLine->pLineNext == pLine)
|
|
npLine->pLineNext = pLine->pLineNext;
|
|
}
|
|
}
|
|
|
|
if (!pGraph->pLineFirst)
|
|
{
|
|
ResetGraph (pGraph) ;
|
|
}
|
|
else
|
|
{
|
|
// BuildNewValueListForGraph () ;
|
|
}
|
|
|
|
// Delete the legend entry for this line.
|
|
// If the line was highlighted then this will undo the highlight.
|
|
|
|
LegendDeleteItem (hWndGraphLegend, pLine) ;
|
|
|
|
LineFree (pLine) ;
|
|
|
|
SizeGraphComponents (hWndGraph) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
FLOAT Counter_Queuelen(PLINESTRUCT pLine)
|
|
{
|
|
|
|
return((FLOAT)0.0);
|
|
// pLine;
|
|
}
|
|
|
|
|
|
void ClearGraphDisplay (PGRAPHSTRUCT pGraph)
|
|
{
|
|
PLINESTRUCT pLine;
|
|
|
|
// reset the timeline data
|
|
// pGraph->gKnownValue = -1 ;
|
|
// pGraph->gTimeLine.iValidValues = 0 ;
|
|
// pGraph->gTimeLine.xLastTime = 0 ;
|
|
// memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
|
|
|
|
// loop through lines,
|
|
// If one of the lines is highlighted then do the calculations
|
|
// for average, min, & max on that line.
|
|
|
|
// for (pLine=pGraph->pLineFirst; pLine; pLine=pLine->pLineNext)
|
|
// { // for
|
|
|
|
// pLine->bFirstTime = 2 ;
|
|
// pLine->lnMinValue = FLT_MAX ;
|
|
// pLine->lnMaxValue = - FLT_MAX ;
|
|
// pLine->lnAveValue = 0.0F ;
|
|
// pLine->lnValidValues = 0 ;
|
|
// memset (pLine->lnValues, 0, sizeof(FLOAT) * pGraph->gMaxValues) ;
|
|
// }
|
|
|
|
// StatusTimer (hWndGraphStatus, TRUE) ;
|
|
}
|
|
|
|
void ResetGraphView (HWND hWndGraph)
|
|
{
|
|
PGRAPHSTRUCT pGraph ;
|
|
|
|
pGraph = GraphData (hWndGraph) ;
|
|
|
|
|
|
if (!pGraph)
|
|
{
|
|
return ;
|
|
}
|
|
|
|
ChangeSaveFileName (NULL, IDM_VIEWCHART) ;
|
|
|
|
if (pGraph->pSystemFirst)
|
|
{
|
|
ResetGraph (pGraph) ;
|
|
}
|
|
} // ResetGraphView
|
|
|
|
void ResetGraph (PGRAPHSTRUCT pGraph)
|
|
{
|
|
ClearLegend (hWndGraphLegend) ;
|
|
if (pGraph->pLineFirst)
|
|
{
|
|
FreeLines (pGraph->pLineFirst) ;
|
|
pGraph->pLineFirst = NULL ;
|
|
}
|
|
|
|
if (pGraph->pSystemFirst)
|
|
{
|
|
FreeSystems (pGraph->pSystemFirst) ;
|
|
pGraph->pSystemFirst = NULL ;
|
|
}
|
|
|
|
pGraph->gKnownValue = -1 ;
|
|
pGraph->gTimeLine.iValidValues = 0 ;
|
|
pGraph->gTimeLine.xLastTime = 0 ;
|
|
|
|
// reset visual data
|
|
pGraph->Visual.iColorIndex = 0 ;
|
|
pGraph->Visual.iWidthIndex = 0 ;
|
|
pGraph->Visual.iStyleIndex = 0 ;
|
|
|
|
// memset (pGraph->pDataTime, 0, sizeof(SYSTEMTIME) * pGraph->gMaxValues) ;
|
|
|
|
SizeGraphComponents (hWndGraph) ;
|
|
InvalidateRect(hWndGraph, NULL, TRUE) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL AddChart (HWND hWndParent)
|
|
{
|
|
PLINE pCurrentLine = CurrentGraphLine (hWndGraph) ;
|
|
|
|
return (AddLine (hWndParent,
|
|
&(pGraphs->pSystemFirst),
|
|
&(pGraphs->Visual),
|
|
pCurrentLine ? pCurrentLine->lnSystemName : NULL,
|
|
LineTypeChart)) ;
|
|
}
|
|
|
|
|
|
BOOL EditChart (HWND hWndParent)
|
|
{ // EditChart
|
|
return (EditLine (hWndParent,
|
|
&(pGraphs->pSystemFirst),
|
|
CurrentGraphLine (hWndGraph),
|
|
LineTypeChart)) ;
|
|
}
|
|
|
|
|
|
BOOL QuerySaveChart (HWND hWndParent, PGRAPHSTRUCT pGraph)
|
|
/*
|
|
Effect: If the graph pGraph is modified, put up a message
|
|
box allowing the user to save the current graph.
|
|
|
|
Return whether the caller should proceed to load in
|
|
a new or otherwise trash the current graph.
|
|
*/
|
|
{ // QuerySaveChart
|
|
#ifdef KEEP_QUERY
|
|
int iReturn ;
|
|
|
|
if (!pGraph->bModified)
|
|
return (TRUE) ;
|
|
|
|
iReturn = MessageBoxResource (hWndParent,
|
|
IDS_SAVECHART, IDS_MODIFIEDCHART,
|
|
MB_YESNOCANCEL | MB_ICONASTERISK) ;
|
|
|
|
if (iReturn == IDCANCEL)
|
|
return (FALSE) ;
|
|
|
|
if (iReturn == IDYES)
|
|
SaveChart (hWndGraph, 0, 0) ;
|
|
return (TRUE) ;
|
|
#endif
|
|
return (TRUE) ; // we don't want to query nor save change
|
|
|
|
} // QuerySaveChart
|
|
|
|
void GraphAddAction ()
|
|
{
|
|
PGRAPHSTRUCT pGraph ;
|
|
|
|
pGraph = GraphData (hWndGraph) ;
|
|
|
|
SizeGraphComponents (hWndGraph) ;
|
|
|
|
LegendSetSelection (hWndGraphLegend,
|
|
LegendNumItems (hWndGraphLegend) - 1) ;
|
|
|
|
}
|
|
|
|
BOOL OpenChartVer1 (HANDLE hFile,
|
|
DISKCHART *pDiskChart,
|
|
PGRAPHSTRUCT pGraph)
|
|
{ // OpenChartVer1
|
|
bDelayAddAction = TRUE ;
|
|
pGraph->Visual = pDiskChart->Visual ;
|
|
pGraph->gOptions = pDiskChart->gOptions ;
|
|
pGraph->gMaxValues = pDiskChart->gMaxValues ;
|
|
pGraph->bManualRefresh = pDiskChart->bManualRefresh ;
|
|
pGraphs->gInterval = (INT) (pGraph->gOptions.eTimeInterval * (FLOAT) 1000.0) ;
|
|
ReadLines (hFile, pDiskChart->dwNumLines,
|
|
&(pGraph->pSystemFirst), &(pGraph->pLineFirst), IDM_VIEWCHART) ;
|
|
|
|
bDelayAddAction = FALSE ;
|
|
|
|
GraphAddAction () ;
|
|
|
|
return (TRUE) ;
|
|
} // OpenChartVer1
|
|
|
|
|
|
|
|
BOOL OpenChart (HWND hWndGraph,
|
|
HANDLE hFile,
|
|
DWORD dwMajorVersion,
|
|
DWORD dwMinorVersion,
|
|
BOOL bChartFile)
|
|
{ // OpenChart
|
|
PGRAPHSTRUCT pGraph ;
|
|
DISKCHART DiskChart ;
|
|
BOOL bSuccess = TRUE ;
|
|
|
|
pGraph = pGraphs ;
|
|
if (!pGraph)
|
|
{
|
|
bSuccess = FALSE ;
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (!FileRead (hFile, &DiskChart, sizeof (DISKCHART)))
|
|
{
|
|
bSuccess = FALSE ;
|
|
goto Exit0 ;
|
|
}
|
|
|
|
|
|
switch (dwMajorVersion)
|
|
{
|
|
case (1):
|
|
|
|
SetHourglassCursor() ;
|
|
|
|
ResetGraphView (hWndGraph) ;
|
|
|
|
OpenChartVer1 (hFile, &DiskChart, pGraph) ;
|
|
|
|
// change to chart view if we are opening a
|
|
// chart file
|
|
if (bChartFile && iPerfmonView != IDM_VIEWCHART)
|
|
{
|
|
SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWCHART, 0L) ;
|
|
}
|
|
|
|
if (iPerfmonView == IDM_VIEWCHART)
|
|
{
|
|
SetPerfmonOptions (&DiskChart.perfmonOptions) ;
|
|
}
|
|
|
|
SetArrowCursor() ;
|
|
|
|
break ;
|
|
} // switch
|
|
|
|
Exit0:
|
|
|
|
if (bChartFile)
|
|
{
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
return (bSuccess) ;
|
|
} // OpenChart
|
|
|
|
BOOL SaveChart (HWND hWndGraph, HANDLE hInputFile, BOOL bGetFileName)
|
|
{
|
|
PGRAPHSTRUCT pGraph ;
|
|
PLINE pLine ;
|
|
HANDLE hFile ;
|
|
DISKCHART DiskChart ;
|
|
PERFFILEHEADER FileHeader ;
|
|
TCHAR szFileName [256] ;
|
|
BOOL newFileName = FALSE ;
|
|
|
|
if (hInputFile)
|
|
{
|
|
// use the input file handle if it is available
|
|
// this is the case for saving workspace data
|
|
hFile = hInputFile ;
|
|
}
|
|
else
|
|
{
|
|
if (pChartFullFileName)
|
|
{
|
|
lstrcpy (szFileName, pChartFullFileName) ;
|
|
}
|
|
if (bGetFileName || pChartFullFileName == NULL)
|
|
{
|
|
// if (!pChartFullFileName)
|
|
// {
|
|
// StringLoad (IDS_GRAPH_FNAME, szFileName) ;
|
|
// }
|
|
|
|
if (!FileGetName (hWndGraph, IDS_CHARTFILE, szFileName))
|
|
{
|
|
return (FALSE) ;
|
|
}
|
|
newFileName = TRUE ;
|
|
}
|
|
|
|
hFile = FileHandleCreate (szFileName) ;
|
|
|
|
if (hFile && hFile != INVALID_HANDLE_VALUE && newFileName)
|
|
{
|
|
ChangeSaveFileName (szFileName, IDM_VIEWCHART) ;
|
|
}
|
|
else if (!hFile || hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
DlgErrorBox (hWndGraph, ERR_CANT_OPEN, szFileName) ;
|
|
}
|
|
}
|
|
|
|
if (!hFile || hFile == INVALID_HANDLE_VALUE)
|
|
return (FALSE) ;
|
|
|
|
pGraph = pGraphs ;
|
|
if (!pGraph)
|
|
{
|
|
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle (hFile) ;
|
|
}
|
|
return (FALSE) ;
|
|
}
|
|
|
|
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
// only need to write file header if not workspace
|
|
memset (&FileHeader, 0, sizeof (FileHeader)) ;
|
|
lstrcpy (FileHeader.szSignature, szPerfChartSignature) ;
|
|
FileHeader.dwMajorVersion = ChartMajorVersion ;
|
|
FileHeader.dwMinorVersion = ChartMinorVersion ;
|
|
|
|
if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
|
|
{
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
DiskChart.Visual = pGraph->Visual ;
|
|
DiskChart.gOptions = pGraph->gOptions ;
|
|
DiskChart.gMaxValues = pGraph->gMaxValues ;
|
|
DiskChart.dwNumLines = NumLines (pGraph->pLineFirst) ;
|
|
DiskChart.bManualRefresh = pGraph->bManualRefresh ;
|
|
DiskChart.perfmonOptions = Options ;
|
|
|
|
if (!FileWrite (hFile, &DiskChart, sizeof (DISKCHART)))
|
|
{
|
|
goto Exit0 ;
|
|
}
|
|
|
|
for (pLine = pGraph->pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineNext)
|
|
{ // for
|
|
if (!WriteLine (pLine, hFile))
|
|
{
|
|
goto Exit0 ;
|
|
}
|
|
} // for
|
|
|
|
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
Exit0:
|
|
if (!hInputFile || hInputFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle (hFile) ;
|
|
|
|
// only need to report error if not workspace
|
|
DlgErrorBox (hWndGraph, ERR_SETTING_FILE, szFileName) ;
|
|
}
|
|
return (FALSE) ;
|
|
|
|
} // SaveChart
|
|
|
|
#define TIME_TO_WRITE 6
|
|
|
|
typedef struct CHARTDATAPOINTSTRUCT
|
|
{
|
|
int iLogIndex ;
|
|
int xDispDataPoint ;
|
|
} CHARTDATAPOINT, *PCHARTDATAPOINT ;
|
|
|
|
|
|
BOOL ToggleGraphRefresh (HWND hWnd)
|
|
{ // ToggleGraphRefresh
|
|
PGRAPHSTRUCT pGraph ;
|
|
pGraph = GraphData (hWnd) ;
|
|
|
|
pGraph->bManualRefresh = !pGraph->bManualRefresh ;
|
|
return (pGraph->bManualRefresh) ;
|
|
} // ToggleGraphRefresh
|
|
|
|
BOOL GraphRefresh (HWND hWnd)
|
|
{ // GraphRefresh
|
|
PGRAPHSTRUCT pGraph ;
|
|
|
|
pGraph = GraphData (hWnd) ;
|
|
|
|
return (pGraph->bManualRefresh) ;
|
|
} // GraphRefresh
|
|
|
|
|