www.gusucode.com > VC++自定义图表控件及使用例子源码程序 > VC++自定义图表控件及使用例子源码程序\code\ChartCtrl_source\ChartSurfaceSerie.cpp
//Download by http://www.NewXing.com /* * * ChartSurfaceSerie.cpp * * Written by C閐ric Moonen (cedric_moonen@hotmail.com) * * * * This code may be used for any non-commercial and commercial purposes in a compiled form. * The code may be redistributed as long as it remains unmodified and providing that the * author name and this disclaimer remain intact. The sources can be modified WITH the author * consent only. * * This code is provided without any garanties. I cannot be held responsible for the damage or * the loss of time it causes. Use it at your own risks * * An e-mail to notify me that you are using this code is appreciated also. * * */ #include "stdafx.h" #include "ChartSurfaceSerie.h" #include "ChartCtrl.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CChartSurfaceSerie::CChartSurfaceSerie(CChartCtrl* pParent) : CChartXYSerie(pParent), m_FillStyle(fsHatchDownDiag), m_bHorizontal(true) { } CChartSurfaceSerie::~CChartSurfaceSerie() { } void CChartSurfaceSerie::Draw(CDC* pDC) { DrawAll(pDC); } void CChartSurfaceSerie::DrawAll(CDC* pDC) { unsigned uFirst=0, uLast=0; if (!GetVisiblePoints(uFirst,uLast)) return; if (uFirst>0) uFirst--; if (uLast<GetPointsCount()-1) uLast++; unsigned uCount = uLast - uFirst + 1; CPoint* pPoints = new CPoint[uCount+2]; CBrush NewBrush; if (m_FillStyle == fsSolid) NewBrush.CreateSolidBrush(m_SerieColor); else { int nIndex = 0; switch (m_FillStyle) { case fsHatchDownDiag: nIndex = HS_FDIAGONAL; break; case fsHatchUpDiag: nIndex = HS_BDIAGONAL; break; case fsHatchCross: nIndex = HS_CROSS; break; case fsHatchDiagCross: nIndex = HS_DIAGCROSS; break; case fsHatchHorizontal: nIndex = HS_HORIZONTAL; break; case fsHatchVertical: nIndex = HS_VERTICAL; break; } NewBrush.CreateHatchBrush(nIndex,m_SerieColor); } CBrush* pOldBrush = pDC->SelectObject(&NewBrush); for (unsigned index=uFirst; index<=uLast; index++) { SChartXYPoint Point = GetPoint(index); ValueToScreen(Point.X, Point.Y, pPoints[index-uFirst+1]); } if (m_bHorizontal) { pPoints[0].x = pPoints[1].x; pPoints[uCount+1].x = pPoints[uCount].x; double Position = m_pHorizontalAxis->GetPosition()/100.00; int AxisPos = m_PlottingRect.top + (int)(Position * (m_PlottingRect.bottom-m_PlottingRect.top)); pPoints[0].y = AxisPos; pPoints[uCount+1].y = AxisPos; } else { pPoints[0].y = pPoints[1].y; pPoints[uCount+1].y = pPoints[uCount].y; double Position = m_pVerticalAxis->GetPosition()/100.00; int AxisPos = m_PlottingRect.left + (int)(Position * (m_PlottingRect.right-m_PlottingRect.left)); pPoints[0].x = AxisPos; pPoints[uCount+1].x = AxisPos; } pDC->SetBkMode(TRANSPARENT); //To have lines limited in the drawing rectangle : CRect TempClipRect(m_PlottingRect); TempClipRect.DeflateRect(1,1); pDC->SetBkMode(TRANSPARENT); pDC->IntersectClipRect(TempClipRect); pDC->Polygon(pPoints,uCount+2); pDC->SelectClipRgn(NULL); pDC->SelectObject(pOldBrush); DeleteObject(NewBrush); delete[] pPoints; } void CChartSurfaceSerie::DrawLegend(CDC* pDC, const CRect& rectBitmap) const { if (m_strSerieName== _T("")) return; // Draw the bitmap CBrush NewBrush; if (m_FillStyle == fsSolid) NewBrush.CreateSolidBrush(m_SerieColor); else { int nIndex = 0; switch (m_FillStyle) { case fsHatchDownDiag: nIndex = HS_FDIAGONAL; break; case fsHatchUpDiag: nIndex = HS_BDIAGONAL; break; case fsHatchCross: nIndex = HS_CROSS; break; case fsHatchDiagCross: nIndex = HS_DIAGCROSS; break; case fsHatchHorizontal: nIndex = HS_HORIZONTAL; break; case fsHatchVertical: nIndex = HS_VERTICAL; break; } NewBrush.CreateHatchBrush(nIndex,m_SerieColor); } CBrush* pOldBrush = pDC->SelectObject(&NewBrush); pDC->Rectangle(rectBitmap); pDC->SelectObject(pOldBrush); DeleteObject(NewBrush); } void CChartSurfaceSerie::SetFillStyle(FillStyle NewStyle) { m_FillStyle = NewStyle; m_pParentCtrl->RefreshCtrl(); } void CChartSurfaceSerie::SetHorizontal(bool bHoriz) { m_bHorizontal = bHoriz; if (m_bHorizontal) m_vPoints.SetOrdering(poXOrdering); else m_vPoints.SetOrdering(poYOrdering); m_pParentCtrl->RefreshCtrl(); } void CChartSurfaceSerie::SetSeriesOrdering(PointsOrdering ) { TRACE("Can't change the series ordering of a surface series."); } bool CChartSurfaceSerie::IsPointOnSerie(const CPoint& screenPoint, unsigned& uIndex) const { uIndex = INVALID_POINT; if (!m_bIsVisible) return false; unsigned uFirst=0, uLast=0; if (!GetVisiblePoints(uFirst,uLast)) return false; if (uFirst>0) uFirst--; if (uLast<GetPointsCount()) uLast++; bool bResult = false; for (unsigned ptIndex=uFirst; ptIndex<uLast-1; ptIndex++) { SChartXYPoint SeriePoint1 = GetPoint(ptIndex); SChartXYPoint SeriePoint2 = GetPoint(ptIndex+1); CPoint point1; CPoint point2; ValueToScreen(SeriePoint1.X, SeriePoint1.Y, point1); ValueToScreen(SeriePoint2.X, SeriePoint2.Y, point2); double lineSlope = (1.0*(point2.y-point1.y))/(point2.x-point1.x); double lineOffset = (1.0*(point2.x*point1.y-point1.x*point2.y))/(point2.x-point1.x); if (m_bHorizontal) { if ( (screenPoint.x < point1.x) || (screenPoint.x > point2.x)) continue; int Position = m_pHorizontalAxis->GetPosition(); if ( (Position==100) && (screenPoint.y > (screenPoint.x *lineSlope + lineOffset)) ) bResult = true; if ( (Position==0) && (screenPoint.y < (screenPoint.x *lineSlope + lineOffset)) ) bResult = true; if (bResult) { // Check if the click is close to one of the two points. int xDist = abs(screenPoint.x - point1.x); int yDist = abs(screenPoint.y - point1.y); if (xDist<=5 && yDist<=5) uIndex = ptIndex; xDist = abs(screenPoint.x - point2.x); yDist = abs(screenPoint.y - point2.y); if (xDist<=5 && yDist<=5) uIndex = ptIndex+1; break; } } else { if ( (screenPoint.y > point1.y) || (screenPoint.y < point2.y)) continue; int Position = m_pVerticalAxis->GetPosition(); if ( (Position==0) && (screenPoint.x < (screenPoint.y-lineOffset)/lineSlope) ) bResult = true; if ( (Position==100) && (screenPoint.x > (screenPoint.y-lineOffset)/lineSlope) ) bResult = true; if (bResult) { // Check if the click is close to one of the two points. int xDist = abs(screenPoint.x - point1.x); int yDist = abs(screenPoint.y - point1.y); if (xDist<=5 && yDist<=5) uIndex = ptIndex; xDist = abs(screenPoint.x - point2.x); yDist = abs(screenPoint.y - point2.y); if (xDist<=5 && yDist<=5) uIndex = ptIndex+1; break; } } } return bResult; }