// 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>
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_BAR;
m_szTitleY = "Byte In & Out";
m_szTitleY2 = "Total Byte";
}
//
// 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);
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));
}
}
// *** 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("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);
m_timeStamps.push_back(atof(szDateTime));
}
}
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
viewer->setFullRange("x", 0, m_timeStamps/*m_sztimeArray*/.size() - 1);
// Initialize the view port to show the latest 20% of the time range
viewer->setViewPortWidth(0.1);
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 = DoubleArray(&m_timeStamps[0]/*m_sztimeArray*/ + startIndex, noOfPoints);
DoubleArray viewPortDataSeriesA = DoubleArray(&m_dataSeriesA[0] + startIndex, noOfPoints);
DoubleArray viewPortDataSeriesB = DoubleArray(&m_dataSeriesB[0] + startIndex, noOfPoints);
DoubleArray viewPortDataSeriesC = DoubleArray(&m_dataSeriesC[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.
///////////////////////////////////////////////////////////////////////////////////////
CRect rcClient;
m_ChartViewer.GetClientRect(&rcClient);
// Create an XYChart object of size 650 x 350 pixels, with a white (ffffff) background and grey
// (aaaaaa) border
//XYChart *c = new XYChart(650 + 20, 350 + 100, 0xffffff, 0xaaaaaa);
// 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() - 50, 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);
// 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);
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;
// Add a line layer for the lines, using a line width of 2 pixels
if(m_eChartType == CHART_LINE)
{
LineLayer *layer = c->addLineLayer();
pBaseLayer = layer;
LineLayer *layer2 = c->addLineLayer();
pBaseLayer2 = layer2;
layer->setLineWidth(1);
layer2->setLineWidth(1);
layer->setFastLineMode();
layer2->setFastLineMode();
}
else if(m_eChartType == CHART_BAR)
{
BarLayer *layer = c->addBarLayer();
pBaseLayer = layer;
BarLayer *layer2 = c->addBarLayer();
pBaseLayer2 = layer2;
layer->setLineWidth(1);
layer2->setLineWidth(1);
layer->setBarShape(Chart::CircleShape);
layer2->setBarShape(Chart::CircleShape);
}
else if(m_eChartType == CHART_SPINE)
{
SplineLayer *layer = c->addSplineLayer();
pBaseLayer = layer;
SplineLayer *layer2 = c->addSplineLayer();
pBaseLayer2 = layer2;
layer->setLineWidth(1);
layer2->setLineWidth(1);
layer->setFastLineMode();
layer2->setFastLineMode();
}
//LineLayer *layer2 = c->addLineLayer();
BarLayer *layer2 = c->addBarLayer();
layer2->setBarShape(Chart::CircleShape);
layer2->setLineWidth(1);
//layer2->setBarWidth(4);
// 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)
pBaseLayer->addDataSet(viewPortDataSeriesA, 0xff3333);
pBaseLayer->addDataSet(viewPortDataSeriesB, 0x008800);
pBaseLayer2->addDataSet(viewPortDataSeriesC, 0x3333CC);
pBaseLayer2->setUseYAxis2();
///////////////////////////////////////////////////////////////////////////////////////
// Configure axis scale and labelling
///////////////////////////////////////////////////////////////////////////////////////
// Set the x-axis as a date/time axis with the scale according to the view port x range.
//c->xAxis()->setLabels(viewPortTimeStamps);
int nStep = c->getWidth() / 50;
//c->xAxis()->setLabelStep(viewPortTimeStamps.len / nStep/*20*/ + 1);
//<<
pBaseLayer->setXData(viewPortTimeStamps);
pBaseLayer2->setXData(viewPortTimeStamps);
c->xAxis()->setDateScale(viewPortTimeStamps[0], viewPortTimeStamps[noOfPoints-1]);
//if ( (viewPortTimeStamps[0] - viewPortTimeStamps[noOfPoints-1]) * viewPortTimeStamps.len / 1000 <= 20 * 60)
// c->xAxis()->setLabelFormat("{value|hh:nn}");
//else
// c->xAxis()->setLabelFormat("{value|nn:ss}");
c->xAxis()->setFormatCondition(">", 20*60);
c->xAxis()->setLabelFormat("{value|hh:nn}");
c->yAxis()->setFormatCondition("else");
c->yAxis()->setLabelFormat("{value|nn:ss}");
//<<
//c->xAxis()->setLabelStyle("arial.ttf", 8, Chart::TextColor, 90);
CString szZoom;
szZoom.Format(" %f \\n",m_ChartViewer.getZoomInHeightLimit());
OutputDebugString(szZoom);
c->yAxis()->setFormatCondition(">", 1000*1000);
c->yAxis()->setLabelFormat("{={value}/1000000}M");
c->yAxis()->setFormatCondition(">", 1000);
c->yAxis()->setLabelFormat("{={value}/1000}K");
c->yAxis()->setFormatCondition("else");
c->yAxis()->setLabelFormat("{={value}}");
c->yAxis()->setWidth(2);
c->yAxis2()->setWidth(2);
c->yAxis()->setColors(RGB(0,0,0));
c->yAxis2()->setColors(RGB(255,0,0));
c->yAxis2()->setColors(0xbb0000);
c->yAxis2()->setFormatCondition(">", 1000*1000);
c->yAxis2()->setLabelFormat("{={value}/1000000}M");
c->yAxis2()->setFormatCondition(">", 1000);
c->yAxis2()->setLabelFormat("{={value}/1000}K");
c->yAxis2()->setFormatCondition("else");
c->yAxis2()->setLabelFormat("{={value}}");
if(m_dYScale)
c->yAxis()->setLinearScale(0,m_dYScale);
if(m_dYScale2)
c->yAxis2()->setLinearScale(0,m_dYScale2);
///////////////////////////////////////////////////////////////////////////////////////
// Output the chart
///////////////////////////////////////////////////////////////////////////////////////
// Include tool tip for the chart
m_ChartViewer.setImageMap(
c->getHTMLImageMap("", "", "title='{xLabel}: US${value}K'"));
delete viewer->getChart();
viewer->setChart(c);
}
//
// 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, yyyy") << "]<*/*>";
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() - 3, 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_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() + 50;
//***
pWnd = GetDlgItem(IDC_MFCLINK_LINE2);
pWnd->GetWindowRect(&rcWndRect);
nX = rcParent.right - nSpace - 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(25,10+rcWndRect.Height()*2,25,25);
pWnd = GetDlgItem(IDC_ChartViewer);
pWnd->MoveWindow(rcParent);
CRect rcChartView;
m_ChartViewer.GetClientRect(&rcChartView);
m_ChartViewer.MoveWindow(rcParent);
pWnd = GetDlgItem(IDC_SPIN_SCALEY1);
pWnd->GetClientRect(&rcWndRect);
pWnd->MoveWindow(rcParent.left - rcWndRect.Width() - nSpace,rcParent.top,rcWndRect.Width(),rcWndRect.Height());
pWnd = GetDlgItem(IDC_SPIN_SCALEY2);
pWnd->GetClientRect(&rcWndRect);
pWnd->MoveWindow(rcParent.right + nSpace,rcParent.top,rcWndRect.Width(),rcWndRect.Height());
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;
}
|