// zoomscrolltrackDlg.cpp : implementation file
//
#include "stdafx.h"
#include "ChartDirSample.h"
#include "ChartDirControl.h"
#include "chartdir.h"
#include <math.h>
#include <vector>
#include <sstream>
#include <algorithm>
#include "Strmif.h"
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////////////
// CChartDirControl dialog
//
// Constructor
//
CChartDirControl::CChartDirControl(CWnd* pParent /*=NULL*/)
: CDialog(CChartDirControl::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_dYScale = m_dYScale2 = 0;
m_eChartType = CHART_LINE;
m_eChartType2 = CHART_LINE;
//m_szTitleY = "Byte In & Out";
//m_szTitleY2 = "Total Byte";
m_szTitleY.Empty();
m_szTitleY2.Empty();
m_bIsIsAxisY2InUse = 0;
m_colorY1 = RGB(0,0,255);
m_colorY2 = RGB(255,0,0);
m_eSeries1 = MERTRIC_SERIES_NONE;
m_eSeries2 = MERTRIC_SERIES_NONE;
}
//
// Destructor
//
CChartDirControl::~CChartDirControl()
{
delete m_ranSeries;
delete m_ChartViewer.getChart();
}
void CChartDirControl::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CChartDirControl)
//DDX_Control(pDX, IDC_PointerPB, m_PointerPB);
DDX_Control(pDX, IDC_HScrollBar, m_HScrollBar);
DDX_Control(pDX, IDC_ChartViewer, m_ChartViewer);
//}}AFX_DATA_MAP
DDX_Control(pDX, IDC_MFCLINK_AVG_RESPONSE, m_cAvgResponse);
DDX_Control(pDX, IDC_MFCLINK_MIN, m_cMinLinkButton);
DDX_Control(pDX, IDC_MFCLINK_LINE, m_cLineLinkButton);
DDX_Control(pDX, IDC_MFCLINK_SERVER, m_cServerLinkButton);
DDX_Control(pDX, IDC_MFCLINK_AVG_RESPONSE2, m_cAvgResponse2);
DDX_Control(pDX, IDC_MFCLINK_MIN2, m_cMinLinkButton2);
DDX_Control(pDX, IDC_MFCLINK_LINE2, m_cLineLinkButton2);
DDX_Control(pDX, IDC_MFCLINK_SERVER2, m_cServerLinkButton2);
}
BEGIN_MESSAGE_MAP(CChartDirControl, CDialog)
//{{AFX_MSG_MAP(CChartDirControl)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_DESTROY()
ON_WM_HSCROLL()
ON_WM_MOUSEWHEEL()
ON_CONTROL(CVN_ViewPortChanged, IDC_ChartViewer, OnViewPortChanged)
ON_CONTROL(CVN_MouseMovePlotArea, IDC_ChartViewer, OnMouseMovePlotArea)
//}}AFX_MSG_MAP
//ON_BN_CLICKED(IDC_BUTTON_SCALEUP, &CChartDirControl::OnBnClickedButtonScaleup)
//ON_BN_CLICKED(IDC_BUTTON_SCALEDOWN, &CChartDirControl::OnBnClickedButtonScaledown)
ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SCALEY1, &CChartDirControl::OnDeltaposSpinScaleY1)
ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_SCALEY2, &CChartDirControl::OnDeltaposSpinScaleY2)
ON_WM_SIZE()
ON_BN_CLICKED(IDC_MFCLINK_AVG_RESPONSE, &CChartDirControl::OnBnClickedMfclinkAvgResponse)
ON_BN_CLICKED(IDC_MFCLINK_AVG_RESPONSE2, &CChartDirControl::OnBnClickedMfclinkAvgResponse2)
ON_WM_CTLCOLOR()
ON_WM_ERASEBKGND()
ON_NOTIFY(BCN_DROPDOWN, IDC_MFCLINK_AVG_RESPONSE2, &CChartDirControl::OnBnDropDownMfclinkAvgResponse2)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChartDirControl message handlers
//
// Initialization
//
BOOL CChartDirControl::OnInitDialog()
{
CDialog::OnInitDialog();
// *** code automatically generated by VC++ MFC AppWizard ***
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
//// Load icons to mouse usage buttons
//loadButtonIcon(IDC_PointerPB, IDI_PointerPB, 100, 20);
//loadButtonIcon(IDC_ZoomInPB, IDI_ZoomInPB, 100, 20);
//loadButtonIcon(IDC_ZoomOutPB, IDI_ZoomOutPB, 100, 20);
ResizeControls();
return TRUE;
}
void CChartDirControl::InitChart()
{
//// Load the data
// loadData();
// Initialize the CChartViewer
initChartViewer(&m_ChartViewer);
// Trigger the ViewPortChanged event to draw the chart
m_ChartViewer.updateViewPort(true, true);
SetTimeDuration();
return;
}
// *** code automatically generated by VC++ MFC AppWizard ***
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CChartDirControl::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
//CDialog::OnPaint();
CRect rcClient;
GetClientRect(&rcClient);
CPaintDC dc(this); // device context for painting
dc.FillSolidRect(&rcClient,RGB(255,255,255));
CRect rcChart;
m_ChartViewer.GetWindowRect(&rcChart);
ScreenToClient(&rcChart);
rcChart.InflateRect(1,1);
dc.Draw3dRect(&rcChart,RGB(122,122,122),RGB(122,122,122));
}
}
// *** code automatically generated by VC++ MFC AppWizard ***
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CChartDirControl::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//
// The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in or
// out the chart by dragging or clicking on the chart. It can also be triggered by calling
// CChartViewer.updateViewPort.
//
void CChartDirControl::OnViewPortChanged()
{
// In addition to updating the chart, we may also need to update other controls that
// changes based on the view port.
updateControls(&m_ChartViewer);
// Update the chart if necessary
if (m_ChartViewer.needUpdateChart())
drawChart(&m_ChartViewer);
// We need to update the track line too. If the mouse is moving on the chart (eg. if
// the user drags the mouse on the chart to scroll it), the track line will be updated
// in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
if (!m_ChartViewer.isInMouseMoveEvent())
{
trackLineLegend((XYChart *)m_ChartViewer.getChart(), m_ChartViewer.getPlotAreaMouseX());
m_ChartViewer.updateDisplay();
}
}
//
// User clicks on the the horizontal scroll bar
//
void CChartDirControl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
double newViewPortLeft = moveScrollBar(nSBCode, nPos, pScrollBar);
// Update the view port if the scroll bar has really moved
if (newViewPortLeft != m_ChartViewer.getViewPortLeft())
{
m_ChartViewer.setViewPortLeft(moveScrollBar(nSBCode, nPos, pScrollBar));
m_ChartViewer.updateViewPort(true, false);
}
}
//
// The mouse wheel handler
//
BOOL CChartDirControl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
// Process the mouse wheel only if the mouse is over the plot area
if (!m_ChartViewer.isMouseOnPlotArea())
return FALSE;
// We zoom in or out by 10% depending on the mouse wheel direction.
double newVpWidth = m_ChartViewer.getViewPortWidth() * (zDelta > 0 ? 0.9 : 1 / 0.9);
double newVpHeight = m_ChartViewer.getViewPortHeight() * (zDelta > 0 ? 0.9 : 1 / 0.9);
// We do not zoom beyond the zoom width or height limits.
newVpWidth = max(m_ChartViewer.getZoomInWidthLimit(), min(newVpWidth,
m_ChartViewer.getZoomOutWidthLimit()));
newVpHeight = max(m_ChartViewer.getZoomInHeightLimit(), min(newVpWidth,
m_ChartViewer.getZoomOutHeightLimit()));
if ((newVpWidth != m_ChartViewer.getViewPortWidth()) ||
(newVpHeight != m_ChartViewer.getViewPortHeight()))
{
// Set the view port position and size so that the point under the mouse remains under
// the mouse after zooming.
double deltaX = (m_ChartViewer.getPlotAreaMouseX() - m_ChartViewer.getPlotAreaLeft()) *
(m_ChartViewer.getViewPortWidth() - newVpWidth) / m_ChartViewer.getPlotAreaWidth();
m_ChartViewer.setViewPortLeft(m_ChartViewer.getViewPortLeft() + deltaX);
m_ChartViewer.setViewPortWidth(newVpWidth);
double deltaY = (m_ChartViewer.getPlotAreaMouseY() - m_ChartViewer.getPlotAreaTop()) *
(m_ChartViewer.getViewPortHeight() - newVpHeight) / m_ChartViewer.getPlotAreaHeight();
m_ChartViewer.setViewPortTop(m_ChartViewer.getViewPortTop() + deltaY);
m_ChartViewer.setViewPortHeight(newVpHeight);
m_ChartViewer.updateViewPort(true, false);
}
return TRUE;
}
//
// Draw track cursor when mouse is moving over plotarea
//
void CChartDirControl::OnMouseMovePlotArea()
{
// Get the focus to ensure being able to receive mouse wheel events
m_ChartViewer.SetFocus();
trackLineLegend((XYChart *)m_ChartViewer.getChart(), m_ChartViewer.getPlotAreaMouseX());
m_ChartViewer.updateDisplay();
}
/////////////////////////////////////////////////////////////////////////////
// CChartDirControl methods
//
// Load the data
//
std::vector<std::string> buffer;
std::vector<const char *>labels;
//void CChartDirControl::loadData()
//{
// // In this example, we just use random numbers as data.
// m_ranSeries = new RanSeries(127);
//
// strStorage.resize(1827);
// ptrStorage.resize(1827);
// for (int i = 0; i < 1827; ++i)
// {
// ostringstream legendEntry;
// legendEntry << "label " << i;
// strStorage[i] = legendEntry.str();
// ptrStorage[i] = strStorage[i].c_str();
// }
// m_timeStamps = StringArray(&(ptrStorage[0]), 1827);
// m_dataSeriesA = m_ranSeries->getSeries(1827, 150, -10, 10);
// m_dataSeriesB = m_ranSeries->getSeries(1827, 200, -10, 10);
// m_dataSeriesC = m_ranSeries->getSeries(1827, 250, -8, 8);
//}
void CChartDirControl::loadData()
{
// In this example, we just use random numbers as data.
m_ranSeries = new RanSeries(127);
map<CString,structByteInOut> mapData;
ReadFile("F:\\\\Samples\\\\VC++\\\\AdvSoft Chart\\\\chartdir_cpp_win64\\\\ChartDirector\\\\ChartDirSample\\\\x64\\\\Debug\\\\DML4.txt",mapData);
int nSize = mapData.size();
map<CString,structByteInOut>::iterator it;
int i = 0;
CString szVerify;
CString szTime;
for ( it=mapData.begin() ; it != mapData.end(); it++,i++ )
{
structByteInOut stByteInOut;
CString szDateTime = (*it).first;
stByteInOut = (*it).second;
m_dataSeriesA.push_back(stByteInOut.m_nByteIn);
m_dataSeriesB.push_back(stByteInOut.m_nbyteOut);
m_dataSeriesC.push_back((stByteInOut.m_nbyteOut + stByteInOut.m_nByteIn)/2);
double dTime = atof(szDateTime);
CTime t;
t = dTime;
CString sz;
sz = t.FormatGmt("%A, %B %d, %Y %H:%M:%S \\n");
OutputDebugString(sz);
REFERENCE_TIME rt = static_cast<REFERENCE_TIME>(dTime);
//dTime = Chart::chartTime(t.GetYear(),t.GetMonth(),t.GetDay(),t.GetHour(),t.GetMinute(),t.GetSecond());
//dTime = Chart::chartTime2((int)dTime);
m_timeStamps.push_back(dTime);
m_timeStamps2.push_back(dTime);
}
m_eSeries1 = MERTRIC_SERIES_Y1;
m_eSeries2 = MERTRIC_SERIES_Y2;
}
BOOL CChartDirControl::ReadFile(CString szFilePath,map<CString,structByteInOut> &mapData)
{
CFile cFile(szFilePath,CFile::modeRead);
CArchive ar(&cFile,CArchive::load);
CString szText;
ar.ReadString(szText);
CString szTime,szByteIn,szByteOut;
while(!szText.IsEmpty())
{
ar.ReadString(szText);
int Position = 0;
if(!szText.IsEmpty())
{
szTime = szText.Tokenize("\\t",Position);
szByteIn = szText.Tokenize("\\t",Position);
szByteOut = szText.Tokenize("\\t",Position);
structByteInOut stByteInOut;
stByteInOut.m_nByteIn = atoi(szByteIn);
stByteInOut.m_nbyteOut = atoi(szByteOut);
mapData.insert ( make_pair(szTime,stByteInOut) );
}
}
ar.Flush();
ar.Close();
return TRUE;
}
//
// Initialize the CChartViewer
//
void CChartDirControl::initChartViewer(CChartViewer *viewer)
{
// Set the full x range to be the duration of the data
if(m_eSeries1 == MERTRIC_SERIES_Y1)
{
viewer->setFullRange("x", 0, m_timeStamps/*m_sztimeArray*/.size() - 1);
}
if(m_eSeries2 == MERTRIC_SERIES_Y2)
viewer->setFullRange("x2", 0, m_timeStamps2/*m_sztimeArray*/.size() - 1);
// Initialize the view port to show the latest 20% of the time range
//viewer->setViewPortWidth(0.1);
viewer->setViewPortWidth(1.0);
viewer->setViewPortLeft(1 - viewer->getViewPortWidth());
// Set the maximum zoom to 10 points
viewer->setZoomInWidthLimit(10.0 / m_timeStamps/*m_sztimeArray*/.size());
// Initially set the mouse to drag to scroll mode.
//m_PointerPB.SetCheck(1);
viewer->setMouseUsage(Chart::MouseUsageScroll);
}
//
// Initialize the CChartViewer
//
void CChartDirControl::updateControls(CChartViewer *viewer)
{
// In this demo, we need to update the scroll bar to reflect the view port position and
// width of the view port.
m_HScrollBar.EnableWindow(viewer->getViewPortWidth() < 1);
if (viewer->getViewPortWidth() < 1)
{
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
info.nMin = 0;
info.nMax = 0x1fffffff;
info.nPage = (int)ceil(viewer->getViewPortWidth() * (info.nMax - info.nMin));
info.nPos = (int)(0.5 + viewer->getViewPortLeft() * (info.nMax - info.nMin)) + info.nMin;
m_HScrollBar.SetScrollInfo(&info);
}
}
//
// Handle scroll bar events
//
double CChartDirControl::moveScrollBar(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
//
// Get current scroll bar position
//
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_ALL;
pScrollBar->GetScrollInfo(&info);
//
// Compute new position based on the type of scroll bar events
//
int newPos = info.nPos;
switch (nSBCode)
{
case SB_LEFT:
newPos = info.nMin;
break;
case SB_RIGHT:
newPos = info.nMax;
break;
case SB_LINELEFT:
newPos -= (info.nPage > 10) ? info.nPage / 10 : 1;
break;
case SB_LINERIGHT:
newPos += (info.nPage > 10) ? info.nPage / 10 : 1;
break;
case SB_PAGELEFT:
newPos -= info.nPage;
break;
case SB_PAGERIGHT:
newPos += info.nPage;
break;
case SB_THUMBTRACK:
newPos = info.nTrackPos;
break;
}
if (newPos < info.nMin) newPos = info.nMin;
if (newPos > info.nMax) newPos = info.nMax;
// Update the scroll bar with the new position
pScrollBar->SetScrollPos(newPos);
// Returns the position of the scroll bar as a ratio of its total length
return ((double)(newPos - info.nMin)) / (info.nMax - info.nMin);
}
//
// Draw the chart and display it in the given viewer
//
void CChartDirControl::drawChart(CChartViewer *viewer)
{
// Get the array indexes that corresponds to the visible start and end dates
int startIndex = (int)floor(viewer->getValueAtViewPort("x", viewer->getViewPortLeft()));
int endIndex = (int)ceil(viewer->getValueAtViewPort("x", viewer->getViewPortLeft() +
viewer->getViewPortWidth()));
int noOfPoints = endIndex - startIndex + 1;
int nScroll = m_HScrollBar.GetScrollPos();
// Extract the part of the data array that are visible.
DoubleArray viewPortTimeStamps,viewPortTimeStamps2;
DoubleArray viewPortDataSeriesA,viewPortDataSeriesB;
if(m_eSeries1 == MERTRIC_SERIES_Y1)
{
viewPortTimeStamps = DoubleArray(&m_timeStamps[0]/*m_sztimeArray*/ + startIndex, noOfPoints);
viewPortDataSeriesA = DoubleArray(&m_dataSeriesA[0] + startIndex, noOfPoints);
}
if(m_eSeries2 == MERTRIC_SERIES_Y2)
{
viewPortTimeStamps2 = DoubleArray(&m_timeStamps2[0]/*m_sztimeArray*/ + startIndex, noOfPoints);
viewPortDataSeriesB = DoubleArray(&m_dataSeriesB[0] + startIndex, noOfPoints);
}
///////////////////////////////////////////////////////////////////////////////////////
// Configure overall chart appearance.
///////////////////////////////////////////////////////////////////////////////////////
CRect rcClient;
m_ChartViewer.GetClientRect(&rcClient);
// Create an XYChart object of size 650 x 350 pixels, with a white (ffffff) background and grey
// XYChart *c = new XYChart(rcClient.Width(), rcClient.Height(), 0xffffff, 0xaaaaaa);
XYChart *c = new XYChart(rcClient.Width(), rcClient.Height(), RGB(255,255,255)/*Chart::brushedSilverColor()*/,
Chart::Transparent,0);
// Set the plotarea at (55, 50) with width 90 pixels less than chart width, and height 115 pixels
// less than chart height. Use a vertical gradient from light blue (f0f6ff) to sky blue (a0c0ff)
// as background. Set border to transparent and grid lines to white (ffffff).
// c->setPlotArea(55, 50, c->getWidth() - 90 - 20, c->getHeight() - 115 - 20, c->linearGradientColor(0, 55, 0,
//c->getHeight() - 35, 0xf0f6ff, 0xa0c0ff), -1, Chart::Transparent, 0xffffff, 0xffffff);
c->setPlotArea(55, 25, c->getWidth() - 90 - 20, c->getHeight() - 75, RGB(255,255,255), -1, Chart::Transparent, RGB(200,200,200), RGB(200,200,200));
// As the data can lie outside the plotarea in a zoomed chart, we need enable clipping.
c->setClipping();
// Add a title to the chart using 18 pts Times New Roman Bold Italic font
//c->addTitle(" Zooming & Scrolling Sample", "timesbi.ttf", 18);<<
// Set legend icon style to use line style icon, sized for 8pt font
c->getLegend()->setLineStyleKey();
c->getLegend()->setFontSize(8);
//if(m_eSeries1 == MERTRIC_SERIES_Y1)
// drawChart(viewer,c,c->xAxis(),c->yAxis(),MERTRIC_SERIES_Y1);
//if(m_eSeries2 == MERTRIC_SERIES_Y2)
// drawChart(viewer,c,c->xAxis(),c->yAxis2(),MERTRIC_SERIES_Y2);
////////////////////**************************
if(m_eSeries1 == MERTRIC_SERIES_Y1)
{
// Set the axis stem to transparent
c->xAxis()->setColors(Chart::Transparent);
c->yAxis()->setColors(Chart::Transparent);
// Add axis title using 10pts Arial Bold Italic font
c->yAxis()->setTitle(m_szTitleY, "arialbi.ttf", 8);
}
if(m_eSeries2 == MERTRIC_SERIES_Y2)
{
// Set the axis stem to transparent
c->xAxis2()->setColors(Chart::Transparent);
c->yAxis2()->setColors(Chart::Transparent);
// Add axis title using 10pts Arial Bold Italic font
c->yAxis2()->setTitle(m_szTitleY2, "arialbi.ttf", 8);
}
///////////////////////////////////////////////////////////////////////////////////////
// Add data to chart
///////////////////////////////////////////////////////////////////////////////////////
//
// In this example, we represent the data by lines. You may modify the code below to use other
// representations (areas, scatter plot, etc).
//
Layer *pBaseLayer = NULL,*pBaseLayer2 = NULL;
if(m_eSeries1 == MERTRIC_SERIES_Y1)
{
pBaseLayer = CreateChartLayer(c,m_eChartType);
pBaseLayer->addDataSet(viewPortDataSeriesA, m_colorY1);//0xff3333
pBaseLayer->setXData(viewPortTimeStamps);
}
if(m_eSeries2 == MERTRIC_SERIES_Y2)
{
pBaseLayer2 = CreateChartLayer(c,m_eChartType2);
pBaseLayer2->addDataSet(viewPortDataSeriesB, m_colorY2);
pBaseLayer2->setUseYAxis2();
pBaseLayer2->setXData(viewPortTimeStamps2);
}
// In this demo, we do not have too many data points. In real code, the chart may contain a lot
// of data points when fully zoomed out - much more than the number of horizontal pixels in this
// plot area. So it is a good idea to use fast line mode.
// Now we add the 3 data series to a line layer, using the color red (ff0000), green
// (00cc00) and blue (0000ff)
//pBaseLayer2->addDataSet(viewPortDataSeriesC, 0x3333CC);
///////////////////////////////////////////////////////////////////////////////////////
// Configure axis scale and labelling
///////////////////////////////////////////////////////////////////////////////////////
//<<
if(m_eSeries1 == MERTRIC_SERIES_Y1)
{
c->xAxis()->setDateScale(viewPortTimeStamps[0], viewPortTimeStamps[noOfPoints-1]);
c->xAxis()->setFormatCondition("align", 24*60*60);
c->xAxis()->setLabelFormat("{value|mmm dd}");
//tick is hourly aligned, so no need to show the nn:ss
c->xAxis()->setFormatCondition("align", 60*60);
c->xAxis()->setMultiFormat(Chart::StartOfDayFilter(),
"<*font=bold*>{value|mmm dd}", Chart::AllPassFilter(), "{value|hh}");
c->xAxis()->setFormatCondition("align", 20*60);
c->xAxis()->setMultiFormat(Chart::StartOfHourFilter(), "<*font=bold*> {value|hh:nn}", Chart::AllPassFilter(), "{value|hh:nn:ss}");
c->xAxis()->setFormatCondition("else");
c->xAxis()->setMultiFormat(Chart::StartOfHourFilter(), "<*font=bold*> {value|hh:nn:ss}", Chart::AllPassFilter(), "{value|nn:ss}");
}
if(m_eSeries2 == MERTRIC_SERIES_Y2)
{
c->xAxis2()->setDateScale(viewPortTimeStamps2[0], viewPortTimeStamps2[noOfPoints-1]);
c->xAxis2()->setFormatCondition("align", 24*60*60);
c->xAxis2()->setLabelFormat("{value|mmm dd}");
//tick is hourly aligned, so no need to show the nn:ss
c->xAxis2()->setFormatCondition("align", 60*60);
c->xAxis2()->setMultiFormat(Chart::StartOfDayFilter(),
"<*font=bold*>{value|mmm dd}", Chart::AllPassFilter(), "{value|hh}");
c->xAxis2()->setFormatCondition("align", 20*60);
c->xAxis2()->setMultiFormat(Chart::StartOfHourFilter(), "<*font=bold*> {value|hh:nn}", Chart::AllPassFilter(), "{value|hh:nn:ss}");
c->xAxis2()->setFormatCondition("else");
c->xAxis2()->setMultiFormat(Chart::StartOfHourFilter(), "<*font=bold*> {value|hh:nn:ss}", Chart::AllPassFilter(), "{value|nn:ss}");
}
//<<
if(m_eSeries1 == MERTRIC_SERIES_Y1)
{
c->yAxis()->setWidth(2);
c->yAxis()->setColors(m_colorY1,m_colorY1);
if(m_dYScale)
c->yAxis()->setLinearScale(0,m_dYScale);
CustomizeLabelOfYaxis(c,c->yAxis());
}
if(m_eSeries2 == MERTRIC_SERIES_Y2)
{
c->yAxis2()->setWidth(2);
c->yAxis2()->setColors(m_colorY2,m_colorY2);
if(m_dYScale2)
c->yAxis2()->setLinearScale(0,m_dYScale2);
CustomizeLabelOfYaxis(c,c->yAxis2());
}
///////////////////////////////////////////////////////////////////////////////////////
// Output the chart
///////////////////////////////////////////////////////////////////////////////////////
// Include tool tip for the chart
////////////////////**************************
delete viewer->getChart();
viewer->setChart(c);
m_ChartViewer.setImageMap(c->getHTMLImageMap("", "", "title='{x|hh:nn:ss}: {value|P4}'"));
}
//New DrawChart
void CChartDirControl::drawChart(CChartViewer *viewer,XYChart *pXYChart,Axis* pAxisX,Axis* pAxisY,MERTRIC_SERIES eSeries)
{
// Get the array indexes that corresponds to the visible start and end dates
int startIndex = (int)floor(viewer->getValueAtViewPort(eSeries == MERTRIC_SERIES_Y1 ? "x" :"x2", viewer->getViewPortLeft()));
int endIndex = (int)ceil(viewer->getValueAtViewPort(eSeries == MERTRIC_SERIES_Y1 ? "x" :"x2", viewer->getViewPortLeft() +
viewer->getViewPortWidth()));
int noOfPoints = endIndex - startIndex + 1;
// Extract the part of the data array that are visible.
DoubleArray viewPortTimeStamps;
DoubleArray viewPortDataSeriesA;
if(eSeries == MERTRIC_SERIES_Y1)
{
viewPortTimeStamps = DoubleArray(&m_timeStamps[0] + startIndex, noOfPoints);
viewPortDataSeriesA = DoubleArray(&m_dataSeriesA[0] + startIndex, noOfPoints);
}
if(eSeries == MERTRIC_SERIES_Y2)
{
viewPortTimeStamps = DoubleArray(&m_timeStamps2[0] + startIndex, noOfPoints);
viewPortDataSeriesA = DoubleArray(&m_dataSeriesB[0] + startIndex, noOfPoints);
}
//
// At this stage, we have extracted the visible data. We can use those data to plot the chart.
//
///////////////////////////////////////////////////////////////////////////////////////
// Configure overall chart appearance.
///////////////////////////////////////////////////////////////////////////////////////
// Set the axis stem to transparent
pAxisX->setColors(Chart::Transparent);
pAxisY->setColors(Chart::Transparent);
// Add axis title using 10pts Arial Bold Italic font
pAxisY->setTitle(m_szTitleY, "arialbi.ttf", 8);
///////////////////////////////////////////////////////////////////////////////////////
// Add data to chart
///////////////////////////////////////////////////////////////////////////////////////
//
// In this example, we represent the data by lines. You may modify the code below to use other
// representations (areas, scatter plot, etc).
//
Layer *pBaseLayer = NULL;
pBaseLayer = CreateChartLayer(pXYChart,eSeries == MERTRIC_SERIES_Y1 ? m_eChartType : m_eChartType2);
if(eSeries == MERTRIC_SERIES_Y2)
{
pBaseLayer->setUseYAxis2();
}
pBaseLayer->addDataSet(viewPortDataSeriesA, eSeries == MERTRIC_SERIES_Y2 ? m_colorY2 : m_colorY1);//0xff3333
pBaseLayer->setXData(viewPortTimeStamps);
// In this demo, we do not have too many data points. In real code, the chart may contain a lot
// of data points when fully zoomed out - much more than the number of horizontal pixels in this
// plot area. So it is a good idea to use fast line mode.
// Now we add the 3 data series to a line layer, using the color red (ff0000), green
// (00cc00) and blue (0000ff)
//pBaseLayer2->addDataSet(viewPortDataSeriesC, 0x3333CC);
///////////////////////////////////////////////////////////////////////////////////////
// Configure axis scale and labelling
///////////////////////////////////////////////////////////////////////////////////////
//<<
pAxisX->setDateScale(viewPortTimeStamps[0], viewPortTimeStamps[noOfPoints-1]);
pAxisX->setFormatCondition("align", 24*60*60);
pAxisX->setLabelFormat("{value|mmm dd}");
//tick is hourly aligned, so no need to show the nn:ss
pAxisX->setFormatCondition("align", 60*60);
pAxisX->setMultiFormat(Chart::StartOfDayFilter(),
"<*font=bold*>{value|mmm dd}", Chart::AllPassFilter(), "{value|hh}");
pAxisX->setFormatCondition("align", 20*60);
pAxisX->setMultiFormat(Chart::StartOfHourFilter(), "<*font=bold*> {value|hh:nn}", Chart::AllPassFilter(), "{value|hh:nn:ss}");
pAxisX->setFormatCondition("else");
pAxisX->setMultiFormat(Chart::StartOfHourFilter(), "<*font=bold*> {value|hh:nn:ss}", Chart::AllPassFilter(), "{value|nn:ss}");
//<<
pAxisY->setWidth(2);
if(eSeries == MERTRIC_SERIES_Y1)
{
pAxisY->setColors(m_colorY1,m_colorY1);
if(m_dYScale)
pAxisY->setLinearScale(0,m_dYScale);
}
else
{
pAxisY->setColors(m_colorY2,m_colorY2);
if(m_dYScale)
pAxisY->setLinearScale(0,m_dYScale2);
}
CustomizeLabelOfYaxis(pXYChart,pAxisY);
}
//
// Customize label formatting for Y/Y2 Axis
//
void CChartDirControl::CustomizeLabelOfYaxis(BaseChart* pBaseChart,Axis* pAxisY)
{
pAxisY->setFormatCondition(">", 1000*1000);
pAxisY->setLabelFormat("{={value}/1000000}M");
pAxisY->setFormatCondition(">", 1000);
pAxisY->setLabelFormat("{={value}/1000}K");
pAxisY->setFormatCondition("else");
pAxisY->setLabelFormat("{={value}}");
pBaseChart->layout();
DoubleArray ticks = pAxisY->getTicks();
for (int i = 0; i < ticks.len; i++)
{
double AbsTick = ticks[i];
CString szLable;
if (AbsTick < 1000)
{
szLable.Format("%d",(UINT)(AbsTick));
pAxisY->addLabel(AbsTick, szLable);
}
else if (AbsTick < (1000*1000))
{
if(!((UINT)AbsTick%1000))
szLable.Format("%0.0fK",AbsTick/1000);
else
szLable.Format("%0.1fK",AbsTick/1000.0);
pAxisY->addLabel(AbsTick, szLable);
}
else if(AbsTick < (1000*1000*1000))
{
if(!((UINT)AbsTick%1000000))
szLable.Format("%0.0fM",AbsTick/1000000);
else
szLable.Format("%0.1fM",AbsTick/1000000.0);
pAxisY->addLabel(AbsTick, szLable);
}
}
}
//
// Add layer to chart
//
Layer * CChartDirControl::CreateChartLayer(XYChart *pXYChart,CHART_TYPE eChartType)
{
Layer *pBaseLayer = NULL;
// Add a line layer for the lines, using a line width of 2 pixels
if(eChartType == CHART_LINE)
{
LineLayer *layer = pXYChart->addLineLayer();
pBaseLayer = layer;
layer->setLineWidth(1);
layer->setFastLineMode();
}
else if(eChartType == CHART_BAR)
{
BarLayer *layer = pXYChart->addBarLayer();
pBaseLayer = layer;
layer->setLineWidth(1);
layer->setBarShape(Chart::CircleShape);
}
else if(eChartType == CHART_SPINE)
{
SplineLayer *layer = pXYChart->addSplineLayer();
pBaseLayer = layer;
layer->setLineWidth(1);
layer->setFastLineMode();
}
return pBaseLayer;
}
//
// Draw the track line with legend
//
void CChartDirControl::trackLineLegend(XYChart *c, int mouseX)
{
// Clear the current dynamic layer and get the DrawArea object to draw on it.
DrawArea *d = c->initDynamicLayer();
// The plot area object
PlotArea *plotArea = c->getPlotArea();
// Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
double xValue = c->getNearestXValue(mouseX);
int xCoor = c->getXCoor(xValue);
// Draw a vertical track line at the x-position
d->vline(plotArea->getTopY(), plotArea->getBottomY(), xCoor, d->dashLineColor(0x000000, 0x0101));
// Container to hold the legend entries
vector<string> legendEntries;
// Iterate through all layers to build the legend array
for (int i = 0; i < c->getLayerCount(); ++i) {
Layer *layer = c->getLayerByZ(i);
// The data array index of the x-value
int xIndex = layer->getXIndexOf(xValue);
// Iterate through all the data sets in the layer
for (int j = 0; j < layer->getDataSetCount(); ++j) {
DataSet *dataSet = layer->getDataSetByZ(j);
// We are only interested in visible data sets with names
const char *dataName = dataSet->getDataName();
int color = dataSet->getDataColor();
if (dataName && *dataName && (color != Chart::Transparent)) {
// Build the legend entry, consist of the legend icon, name and data value.
double dataValue = dataSet->getValue(xIndex);
ostringstream legendEntry;
legendEntry << "<*block*>" << dataSet->getLegendIcon() << " " << dataName << ": " <<
((dataValue == Chart::NoValue) ? "N/A" : c->formatValue(dataValue, "{value|P4}"))
<< "<*/*>";
legendEntries.push_back(legendEntry.str());
// Draw a track dot for data points within the plot area
int yCoor = c->getYCoor(dataSet->getPosition(xIndex), dataSet->getUseYAxis());
if ((yCoor >= plotArea->getTopY()) && (yCoor <= plotArea->getBottomY())) {
d->circle(xCoor, yCoor, 4, 4, color, color);
}
}
}
}
// Create the legend by joining the legend entries
ostringstream legendText;
legendText << "<*block,maxWidth=" << plotArea->getWidth() << "*><*block*><*font=arialbd.ttf*>["
<< c->xAxis()->getFormattedLabel(xValue, "mmm dd") << "]<*/*>";
for (int i = ((int)legendEntries.size()) - 1; i >= 0; --i)
legendText << " " << legendEntries[i];
// Display the legend on the top of the plot area
TTFText *t = d->text(legendText.str().c_str(), "arial.ttf", 8);
t->draw(plotArea->getLeftX() + 5, plotArea->getTopY() - 13, 0x000000, Chart::BottomLeft);
t->destroy();
}
/////////////////////////////////////////////////////////////////////////////
// General utilities
//
// Load an icon resource into a button
//
void CChartDirControl::loadButtonIcon(int buttonId, int iconId, int width, int height)
{
GetDlgItem(buttonId)->SendMessage(BM_SETIMAGE, IMAGE_ICON, (LPARAM)::LoadImage(
AfxGetResourceHandle(), MAKEINTRESOURCE(iconId), IMAGE_ICON, width, height,
LR_DEFAULTCOLOR));
}
void CChartDirControl::OnBnClickedButtonScaleup()
{
// TODO: Add your control notification handler code here
}
void CChartDirControl::OnBnClickedButtonScaledown()
{
// TODO: Add your control notification handler code here
XYChart *pXYChart = dynamic_cast<XYChart*>( m_ChartViewer.getChart());
//pXYChart->layoutAxes();
m_dYScale = pXYChart->yAxis()->getMaxValue();
double dYScale = m_dYScale;
m_dYScale -= (m_dYScale * .20);
if(m_dYScale < 1)
m_dYScale = dYScale;
m_ChartViewer.updateViewPort(true, true);
}
void CChartDirControl::OnDeltaposSpinScaleY1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
// TODO: Add your control notification handler code here
XYChart *pXYChart = dynamic_cast<XYChart*>( m_ChartViewer.getChart());
if(!m_dYScale)
{
pXYChart->layoutAxes();
m_dYScale = pXYChart->yAxis()->getMaxValue();
}
if(pNMUpDown->iDelta < 0)
{
//m_dYScale = pXYChart->yAxis()->getMaxValue();
m_dYScale += (m_dYScale * .10);
}
else
{
//m_dYScale = pXYChart->yAxis()->getMaxValue();
m_dYScale -= (m_dYScale * .20);
}
m_ChartViewer.updateViewPort(true, true);
*pResult = 0;
}
void CChartDirControl::OnDeltaposSpinScaleY2(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
// TODO: Add your control notification handler code here
XYChart *pXYChart = dynamic_cast<XYChart*>( m_ChartViewer.getChart());
if(!m_dYScale2)
{
pXYChart->layoutAxes();
m_dYScale2 = pXYChart->yAxis2()->getMaxValue();
}
if(pNMUpDown->iDelta < 0)
{
//m_dYScale2 = pXYChart->yAxis2()->getMaxValue();
m_dYScale2 += (m_dYScale2 * .10);
}
else
{
//m_dYScale2 = pXYChart->yAxis2()->getMaxValue();
m_dYScale2 -= (m_dYScale2 * .20);
}
m_ChartViewer.updateViewPort(true, true);
*pResult = 0;
}
void CChartDirControl::ResizeControls()
{
CWnd *pWnd = GetDlgItem(IDC_ChartViewer);
CRect rcWndRect,rcParent;
int nSpace = 3;
if(pWnd->GetSafeHwnd())
{
int nX = rcParent.left + nSpace;
int nY = rcParent.top + nSpace;
GetClientRect(&rcParent);
//<<
pWnd = GetDlgItem(IDC_SPIN_SCALEY1);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
nX += rcWndRect.Width();
pWnd = GetDlgItem(IDC_MFCLINK_AVG_RESPONSE);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
nX += rcWndRect.Width();
pWnd = GetDlgItem(IDC_STATIC1);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
nX += rcWndRect.Width();
pWnd = GetDlgItem(IDC_MFCLINK_MIN);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
nX += rcWndRect.Width();
pWnd = GetDlgItem(IDC_STATIC2);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
nX += rcWndRect.Width();
pWnd = GetDlgItem(IDC_MFCLINK_LINE);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
nX += rcWndRect.Width() + 0;
pWnd = GetDlgItem(IDC_MFCLINK_TIMEPERIOD);
pWnd->GetWindowRect(&rcWndRect);
nX = rcParent.Width() / 2 - rcWndRect.Width() / 2;
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
nX += rcWndRect.Width() + 50;
//***
pWnd = GetDlgItem(IDC_SPIN_SCALEY2);
pWnd->GetWindowRect(&rcWndRect);
nX = rcParent.right - nSpace - rcWndRect.Width();
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
pWnd = GetDlgItem(IDC_MFCLINK_LINE2);
pWnd->GetWindowRect(&rcWndRect);
nX -= rcWndRect.Width();
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
pWnd = GetDlgItem(IDC_STATIC4);
pWnd->GetWindowRect(&rcWndRect);
nX -= rcWndRect.Width();
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
pWnd = GetDlgItem(IDC_MFCLINK_MIN2);
pWnd->GetWindowRect(&rcWndRect);
nX -= rcWndRect.Width();
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
pWnd = GetDlgItem(IDC_STATIC3);
pWnd->GetWindowRect(&rcWndRect);
nX -= rcWndRect.Width();
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
pWnd = GetDlgItem(IDC_MFCLINK_AVG_RESPONSE2);
pWnd->GetWindowRect(&rcWndRect);
nX -= rcWndRect.Width();
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
pWnd->GetWindowRect(&rcWndRect);
ScreenToClient(&rcWndRect);
nX = rcWndRect.left;
nY = rcWndRect.bottom;
pWnd = GetDlgItem(IDC_MFCLINK_SERVER2);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
pWnd = GetDlgItem(IDC_MFCLINK_AVG_RESPONSE);
pWnd->GetWindowRect(&rcWndRect);
ScreenToClient(&rcWndRect);
nX = rcWndRect.left;
nY = rcWndRect.bottom;
pWnd = GetDlgItem(IDC_MFCLINK_SERVER);
pWnd->GetWindowRect(&rcWndRect);
pWnd->MoveWindow(nX,nY,rcWndRect.Width(),rcWndRect.Height());
//>>
rcParent.DeflateRect(5,10+rcWndRect.Height()*2,5,25);
pWnd = GetDlgItem(IDC_ChartViewer);
pWnd->MoveWindow(rcParent);
CRect rcChartView;
m_ChartViewer.GetClientRect(&rcChartView);
m_ChartViewer.MoveWindow(rcParent);
pWnd = GetDlgItem(IDC_HScrollBar);
pWnd->GetClientRect(&rcWndRect);
pWnd->MoveWindow(rcParent.left,rcParent.bottom + nSpace,rcParent.Width(),rcWndRect.Height());
if(m_ChartViewer.getChart())
m_ChartViewer.updateViewPort(true, true);
}
return;
}
void CChartDirControl::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
ResizeControls();
}
void CChartDirControl::SetChartType(CHART_TYPE eChartType)
{
m_eChartType = eChartType;
m_ChartViewer.updateViewPort(1,1);
}
void CChartDirControl::SetTitleAxixY(CString szTitle)
{
m_szTitleY = szTitle;
}
void CChartDirControl::SetTitleAxixY2(CString szTitle)
{
m_szTitleY2 = szTitle;
}
void CChartDirControl::SetChartTitle(CString szTitle)
{
m_szChartTitle = szTitle;
}
void CChartDirControl::OnBnClickedMfclinkAvgResponse()
{
// TODO: Add your control notification handler code here m_szChartTitle
AfxMessageBox("What To do in OnBnClickedMfclinkAvgResponse()");
}
void CChartDirControl::OnBnClickedMfclinkAvgResponse2()
{
// TODO: Add your control notification handler code here
AfxMessageBox("What To do in OnBnClickedMfclinkAvgResponse2()");
}
HBRUSH CChartDirControl::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
if(pWnd->GetDlgCtrlID() == IDC_STATIC1 || pWnd->GetDlgCtrlID() == IDC_STATIC2 || pWnd->GetDlgCtrlID() == IDC_STATIC3
|| pWnd->GetDlgCtrlID() == IDC_STATIC4)
{
pDC->SetBkMode(TRANSPARENT);
return reinterpret_cast<HBRUSH>(::GetStockObject(NULL_BRUSH));
}
else if(pWnd->GetDlgCtrlID() == IDC_MFCLINK_AVG_RESPONSE || pWnd->GetDlgCtrlID() == IDC_MFCLINK_MIN
|| pWnd->GetDlgCtrlID() == IDC_MFCLINK_LINE
|| pWnd->GetDlgCtrlID() == IDC_MFCLINK_AVG_RESPONSE2 || pWnd->GetDlgCtrlID() == IDC_MFCLINK_MIN2
|| pWnd->GetDlgCtrlID() == IDC_MFCLINK_LINE2)
{
pDC->SetBkMode(TRANSPARENT);
return reinterpret_cast<HBRUSH>(::GetStockObject(NULL_BRUSH));
}
return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Return a different brush if the default is not desired
return hbr;
}
BOOL CChartDirControl::OnEraseBkgnd(CDC* pDC)
{
//// TODO: Add your message handler code here and/or call default
return CDialog::OnEraseBkgnd(pDC);
}
void CChartDirControl::OnBnDropDownMfclinkAvgResponse2(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMBCDROPDOWN pDropDown = reinterpret_cast<LPNMBCDROPDOWN>(pNMHDR);
// TODO: Add your control notification handler code here
*pResult = 0;
}
void CChartDirControl::AddRealTimeData(double dTime,double dDataY,double dDataY2)
{
dTime = *m_timeStamps.rbegin() + 500;
dDataY = 999999 %rand();
dDataY2 = 999999 %rand();
m_timeStamps.push_back(dTime);
m_dataSeriesA.push_back(dDataY);
m_dataSeriesB.push_back(dDataY2);
//m_dataSeriesC.push_back(dDataY2);
m_ChartViewer.setFullRange("x", 0, m_timeStamps/*m_sztimeArray*/.size() - 1);
m_ChartViewer.setZoomInWidthLimit(10.0 / m_timeStamps/*m_sztimeArray*/.size());
m_ChartViewer.setMouseUsage(Chart::MouseUsageScroll);
m_ChartViewer.updateViewPort(true, true);
SetTimeDuration();
return;
}
void CChartDirControl::AddData(double dTime,double dDataY,MERTRIC_SERIES eSeries)
{
//dTime = Chart::chartTime2((int)time((time_t*)&dTime));
if(eSeries == MERTRIC_SERIES_Y1)
{
m_timeStamps.push_back(dTime);
m_dataSeriesA.push_back(dDataY);
}
if(eSeries == MERTRIC_SERIES_Y2)
{
m_timeStamps2.push_back(dTime);
m_dataSeriesB.push_back(dDataY);
}
//m_dataSeriesC.push_back(dDataY2);
return;
}
void CChartDirControl::SetTimeDuration()
{
CWnd *pWnd = GetDlgItem(IDC_MFCLINK_TIMEPERIOD);
if(m_eSeries1 == MERTRIC_SERIES_Y1)
{
double dTime = m_timeStamps[0];
CTime tm;
tm = dTime;
CString sz;
sz = tm.FormatGmt("%d-%m-%Y %H:%M:%S");
dTime = *m_timeStamps.rbegin();
tm = dTime;
sz = sz + " - " + tm.FormatGmt("%H:%M:%S");
pWnd->SetWindowText(sz);
}
if(m_eSeries1 == MERTRIC_SERIES_Y2)
{
double dTime = m_timeStamps2[0];
CTime tm;
tm = dTime;
CString sz;
sz = tm.FormatGmt("%d-%m-%Y %H:%M:%S");
dTime = *m_timeStamps2.rbegin();
tm = dTime;
sz = sz + " - " + tm.FormatGmt("%H:%M:%S");
pWnd->SetWindowText(sz);
}
return;
}
void CChartDirControl::ClearChartData()
{
m_timeStamps.clear();
m_dataSeriesA.clear();
m_dataSeriesB.clear();
m_dataSeriesC.clear();
m_eSeries1 = MERTRIC_SERIES_NONE;
m_eSeries2 = MERTRIC_SERIES_NONE;
return;
}
|