www.gusucode.com > VC++自定义图表控件及使用例子源码程序 > VC++自定义图表控件及使用例子源码程序\code\ChartCtrl_demo\ChartDemo\ChartCtrl\ChartCandlestickSerie.cpp

    //Download by http://www.NewXing.com
/*
 *
 *	ChartCandlestickSerie.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 "ChartCandlestickSerie.h"
#include "ChartCtrl.h"

CChartCandlestickSerie::CChartCandlestickSerie(CChartCtrl* pParent) 
  : CChartSerieBase<SChartCandlestickPoint>(pParent), m_iCandlestickWidth(7)
{
	m_bShadow = true;
}

CChartCandlestickSerie::~CChartCandlestickSerie()
{
}

void CChartCandlestickSerie::AddPoint(double XVal, 
									  double Low, 
									  double High, 
									  double Open, 
									  double Close)
{
	SChartCandlestickPoint NewPoint(XVal, Low, High, Open, Close);
	CChartSerieBase<SChartCandlestickPoint>::AddPoint(NewPoint);
}

void CChartCandlestickSerie::SetWidth(int Width)
{
	m_iCandlestickWidth = Width; 
	m_pParentCtrl->RefreshCtrl();
}

bool CChartCandlestickSerie::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 i=uFirst ; i < uLast ; i++)
	{
		SChartCandlestickPoint Point = GetPoint(i);
		int ScreenXVal = m_pHorizontalAxis->ValueToScreen(Point.XVal);
		int ScreenLow = m_pVerticalAxis->ValueToScreen(Point.Low);
		int ScreenHigh = m_pVerticalAxis->ValueToScreen(Point.High);

		int halfWidth = m_iCandlestickWidth/2;
		CRect Rectangle;
		if (ScreenLow > ScreenHigh) 
			Rectangle.SetRect(ScreenXVal-halfWidth, ScreenHigh,
			ScreenXVal+halfWidth+1, ScreenLow+1);
		else 
			Rectangle.SetRect(ScreenXVal-halfWidth, ScreenLow,
			ScreenXVal+halfWidth+1, ScreenHigh+1);
		if (Rectangle.PtInRect(screenPoint))
		{
			bResult = true;
			uIndex = i;
			break;
		}
	}
	return bResult; 
}

void CChartCandlestickSerie::DrawLegend(CDC* pDC, const CRect& rectBitmap) const
{
	if (m_strSerieName == _T(""))
		return;
	if (!pDC->GetSafeHdc())
		return;

	NewPen.CreatePen(PS_SOLID,1,m_SerieColor);
	BrushFill.CreateSolidBrush(m_SerieColor);
	CBrush* pOldBrush = pDC->SelectObject(&BrushFill);
	CPen* pOldPen = pDC->SelectObject(&NewPen);
	int OldBkMode = pDC->SetBkMode(TRANSPARENT);

	int margin = (rectBitmap.Width() - m_iCandlestickWidth)/2;
	CRect CandleRect(rectBitmap.left+margin, rectBitmap.top+4,
					 rectBitmap.right-margin+1, rectBitmap.bottom-3);
	pDC->Rectangle(CandleRect);
	int MiddleX = rectBitmap.left + rectBitmap.Width()/2;
	pDC->MoveTo(MiddleX, CandleRect.top);
	pDC->LineTo(MiddleX, rectBitmap.top);
	pDC->MoveTo(MiddleX, CandleRect.bottom);
	pDC->LineTo(MiddleX, rectBitmap.bottom);

	pDC->SetBkMode(OldBkMode);
	pDC->SelectClipRgn(NULL);
	pDC->SelectObject(pOldPen);
	pDC->SelectObject(pOldBrush);
	BrushFill.DeleteObject();
	NewPen.DeleteObject();
}

void CChartCandlestickSerie::Draw(CDC* pDC)
{
	if (!m_bIsVisible)
		return;

	unsigned uFirst=0, uLast=0;
	if (!GetVisiblePoints(uFirst,uLast))
		return;

	if (pDC->GetSafeHdc())
	{
		ShadowBrush.CreateSolidBrush(m_ShadowColor);
		NewPen.CreatePen(PS_SOLID,1,m_SerieColor);
		ShadowPen.CreatePen(PS_SOLID,1,m_ShadowColor);
		BrushFill.CreateSolidBrush(m_SerieColor);
		BrushEmpty.CreateSolidBrush(RGB(255,255,255));

		int OldBkMode = pDC->SetBkMode(TRANSPARENT);
		//To have lines limited in the drawing rectangle :
		pDC->IntersectClipRect(m_PlottingRect);

		for (m_uLastDrawnPoint;m_uLastDrawnPoint<GetPointsCount();m_uLastDrawnPoint++)
		{
			SChartCandlestickPoint Point = GetPoint(m_uLastDrawnPoint);
			DrawCandleStick(pDC, Point);
		}

		pDC->SetBkMode(OldBkMode);
		pDC->SelectClipRgn(NULL);
		BrushFill.DeleteObject();
		BrushEmpty.DeleteObject();
		NewPen.DeleteObject();
		ShadowBrush.DeleteObject();
		ShadowPen.DeleteObject();
	}
}

void CChartCandlestickSerie::DrawAll(CDC *pDC)
{
	if (!m_bIsVisible)
		return;

	unsigned uFirst=0, uLast=0;
	if (!GetVisiblePoints(uFirst,uLast))
		return;

	if (pDC->GetSafeHdc())
	{
		ShadowBrush.CreateSolidBrush(m_ShadowColor);
		NewPen.CreatePen(PS_SOLID,1,m_SerieColor);
		ShadowPen.CreatePen(PS_SOLID,1,m_ShadowColor);
		BrushFill.CreateSolidBrush(m_SerieColor);
		BrushEmpty.CreateSolidBrush(RGB(255,255,255));

		pDC->SetBkMode(TRANSPARENT);
		//To have lines limited in the drawing rectangle :
		pDC->IntersectClipRect(m_PlottingRect);

		for (m_uLastDrawnPoint=uFirst;m_uLastDrawnPoint<=uLast;m_uLastDrawnPoint++)
		{
			SChartCandlestickPoint Point = GetPoint(m_uLastDrawnPoint);
			DrawCandleStick(pDC, Point);
		}

		pDC->SelectClipRgn(NULL);
		BrushFill.DeleteObject();
		BrushEmpty.DeleteObject();
		NewPen.DeleteObject();
		ShadowBrush.DeleteObject();
		ShadowPen.DeleteObject();
	}
}

void CChartCandlestickSerie::DrawCandleStick(CDC* pDC, SChartCandlestickPoint Point)
{
	int ScreenXVal = m_pHorizontalAxis->ValueToScreen(Point.XVal);
	int ScreenOpen = m_pVerticalAxis->ValueToScreen(Point.Open);
	int ScreenClose = m_pVerticalAxis->ValueToScreen(Point.Close);
	int ScreenLow = m_pVerticalAxis->ValueToScreen(Point.Low);
	int ScreenHigh = m_pVerticalAxis->ValueToScreen(Point.High);

	int halfWidth = m_iCandlestickWidth/2;
	CPoint TopLeft, BottomRight;
	CRect Body;
	CRect ShadowBody;
	if (ScreenOpen > ScreenClose) 
		Body.SetRect(ScreenXVal-halfWidth, ScreenClose,
					 ScreenXVal+halfWidth+1, ScreenOpen+1);
	else 
		Body.SetRect(ScreenXVal-halfWidth, ScreenOpen,
					 ScreenXVal+halfWidth+1, ScreenClose+1);

	ShadowBody = Body;
	ShadowBody.OffsetRect(m_iShadowDepth, m_iShadowDepth);

	CBrush* pOldBrush = pDC->SelectObject(&ShadowBrush);
	CPen* pOldPen = pDC->SelectObject(&ShadowPen);

	if (m_bShadow) 
		pDC->Rectangle(ShadowBody);
	if (Point.Open > Point.Close)
		pDC->SelectObject(&BrushFill);
	else
		pDC->SelectObject(&BrushEmpty);

	if (m_bShadow) 
	{
		pDC->MoveTo(ScreenXVal+m_iShadowDepth, ScreenOpen+m_iShadowDepth);
		pDC->LineTo(ScreenXVal+m_iShadowDepth, ScreenHigh+m_iShadowDepth);		
		pDC->MoveTo(ScreenXVal+m_iShadowDepth, ScreenClose+m_iShadowDepth);
		pDC->LineTo(ScreenXVal+m_iShadowDepth, ScreenLow+m_iShadowDepth);	
	}
	pDC->SelectObject(&NewPen);
	pDC->MoveTo(ScreenXVal, ScreenOpen);	pDC->LineTo(ScreenXVal, ScreenHigh);
	pDC->MoveTo(ScreenXVal, ScreenClose);	pDC->LineTo(ScreenXVal, ScreenLow);

	pDC->Rectangle(Body);
	pDC->SelectObject(pOldBrush);
	pDC->SelectObject(pOldPen);
}