www.gusucode.com > VC++曲线绘制源码——人体生命曲线-源码程序 > VC++曲线绘制源码——人体生命曲线-源码程序/code/BioGraphCtrl.cpp

    #include "stdafx.h"
#include "math.h"
#include "BioGraphCtrl.h"
// Download by http://www.NewXing.com
BioGraphCtrl::BioGraphCtrl()
{
	m_bornDate = CTime(1980, 1, 1, 0, 0, 0 );
	m_curDate = CTime::GetCurrentTime ();

	m_startDate = CTime (m_curDate.GetYear(), m_curDate.GetMonth(), 1, 0, 0, 0);
	m_endDate = CTime (m_curDate.GetYear(), m_curDate.GetMonth()+1, 1, 0, 0, 0);

	m_topColor = RGB (255, 255, 255);
	m_bottomColor = RGB (255, 255, 0);

	m_focusColor = RGB(255,0,0);
	m_focusDate = CTime (m_curDate.GetYear(), m_curDate.GetMonth(), 5, 0, 0, 0);
}

BioGraphCtrl::~BioGraphCtrl()
{
}

void BioGraphCtrl::SetBornDate (CTime bornDate)
{
	m_bornDate = bornDate;
	Invalidate ();
}

CTime BioGraphCtrl::GetBornDate ()
{
	return m_bornDate;
    }

void BioGraphCtrl::SetCurDate (CTime curDate)
{
	m_curDate = curDate;
}

CTime BioGraphCtrl::GetCurDate ()
{
	return m_curDate;
}

void BioGraphCtrl::SetStartDate (CTime startDate)
{
	m_startDate = startDate;
	Invalidate ();
}

CTime BioGraphCtrl::GetStartDate ()
{
	return m_startDate;
}

void BioGraphCtrl::SetEndDate (CTime endDate)
{
	if (endDate == NULL)
	{
		int month = m_startDate.GetMonth();
		int year = m_startDate.GetYear();

		if (month == 12)
		{
			month = 1;
			year ++;
		}
		else 
			month++;

		m_endDate = CTime(year, month, m_startDate.GetDay(), 0, 0, 0);
	}
	else
		m_endDate = endDate;
}

CTime BioGraphCtrl::GetEndDate ()
{
	return m_endDate;
}

void BioGraphCtrl::SetFocusDate (CTime focusDate)
{
	m_focusDate = focusDate;
}

CTime BioGraphCtrl::GetFocusDate ()
{
	return m_focusDate;
}

void BioGraphCtrl::SetTopColor(COLORREF topColor)
{
	m_topColor = topColor;
}

COLORREF BioGraphCtrl::GetTopColor()
{
	return m_topColor;
}

void BioGraphCtrl::SetBottomColor(COLORREF bottomColor)
{
	m_bottomColor = bottomColor;
}

COLORREF BioGraphCtrl::GetBottomColor()
{
	return m_bottomColor;
}

void BioGraphCtrl::SetFocusColor(COLORREF focusColor)
{
	m_focusColor = focusColor;
}

COLORREF BioGraphCtrl::GetFocusColor()
{
	return m_focusColor;
}

void BioGraphCtrl::GotoNextMonth()
{
	int month = m_endDate.GetMonth();
	int year = m_endDate.GetYear();

	if (month == 12)
	{
		month = 1;
		year ++;
	}
	else 
		month++;

	m_startDate = m_endDate;
	m_endDate = CTime(year, month, 1, 0, 0, 0);
	m_focusDate = CTime(m_startDate.GetYear(), m_startDate.GetMonth(), m_focusDate.GetDay(), 0, 0, 0); 

	Invalidate ();
	GetParent ()->SendMessage (WM_BIO_SELECTCHANGING, GetDlgCtrlID (), NULL );
}

void BioGraphCtrl::GotoPrevMonth()
{
	int month = m_startDate.GetMonth();
	int year = m_startDate.GetYear();

	if (month == 1)
	{
		month = 12;
		year --;
	}
	else 
		month--;

	m_endDate = m_startDate;
	m_startDate = CTime(year, month, 1, 0, 0, 0);
	m_focusDate = CTime(m_startDate.GetYear(), m_startDate.GetMonth(), m_focusDate.GetDay(), 0, 0, 0); 

	Invalidate ();
	GetParent ()->SendMessage (WM_BIO_SELECTCHANGING, GetDlgCtrlID (), NULL );
}

void BioGraphCtrl::GotoCurrentMonth()
{
	CTime currentTime = CTime::GetCurrentTime();
	m_startDate = CTime(currentTime.GetYear(), currentTime.GetMonth(), 1, 0, 0, 0);

	int month = m_startDate.GetMonth();
	int year = m_startDate.GetYear();

	if (month == 12)
	{
		month = 1;
		year ++;
	}
	else 
		month++;

	m_endDate = CTime(year, month, 1, 0, 0, 0);
	m_focusDate = CTime(m_startDate.GetYear(), m_startDate.GetMonth(), m_focusDate.GetDay(), 0, 0, 0); 

	Invalidate ();
	GetParent ()->SendMessage (WM_BIO_SELECTCHANGING, GetDlgCtrlID (), NULL );
}

//渐变颜色背景
void BioGraphCtrl::DrawBackground (CDC* pDC)
{
	byte r1 = GetRValue (m_topColor);
	byte g1 = GetGValue (m_topColor);
	byte b1 = GetBValue (m_topColor);

	byte r2 = GetRValue (m_bottomColor);
	byte g2 = GetGValue (m_bottomColor);
	byte b2 = GetBValue (m_bottomColor);

	CRect rect;
	GetClientRect(rect);

	float rStep = float (r2-r1) / rect.Height ();
	float gStep = float (g2-g1) / rect.Height ();
	float bStep = float (b2-b1) / rect.Height ();

	float r = r1;
	float g = g1;
	float b = b1;
	
	for (float y = 0; y < rect.Height(); y ++)
	{
		CPen pen (PS_SOLID, 1, RGB (r, g, b));
		CPen* oldPen = pDC->SelectObject (&pen);

		pDC->MoveTo (0, int(y));
		pDC->LineTo (rect.right, int(y));

		pDC->SelectObject (oldPen);

		r += rStep;
		g += gStep;
		b += bStep;
	}
}

//画网格
void BioGraphCtrl::DrawGrid (CDC* pDC)
{
	CFont font;
	font.CreateFont (14, 4, 0, 0, FW_EXTRALIGHT, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS,_T("Arial"));
	
	CFont* oldFont = pDC->SelectObject(&font);

	CRect rect;
	GetClientRect(rect);
	rect.bottom -= 20;

	//画横线
	CPen pen1 (PS_SOLID, 1, RGB (0, 0, 180));
	CPen* oldPen = pDC->SelectObject(&pen1); 

	float yStep = float (rect.Height()-1) / 10;
	for (float y = 0 ; y < rect.Height(); y += yStep)
	{
		pDC->MoveTo (rect.left, int(y));
		pDC->LineTo (rect.right, int(y));
	}

	//画竖线
	CPen pen2 (PS_SOLID, 1, RGB(150, 150, 0));
	pDC->SelectObject(&pen2); 

	int days = min (max ( int((m_endDate-m_startDate).GetDays ()), 7), 100);

	float xStep = float (rect.Width()-1) / days;
	for (float x = 0; x < rect.Width(); x += xStep)
	{
		pDC->MoveTo (int(x), rect.top);
		pDC->LineTo (int(x), rect.bottom);
	}

	//加粗中线
	CPen pen3 (PS_SOLID, 2, RGB(50, 0, 250));
	pDC->SelectObject(&pen3); 

	pDC->MoveTo (rect.left, rect.Height() / 2);
	pDC->LineTo (rect.right, rect.Height() / 2);

	DrawGuage(pDC);

	pDC->SelectObject (oldPen);
	pDC->SelectObject (oldFont);
}

//画生命曲线
void BioGraphCtrl::DrawLifeCurve (CDC* pDC)
{
	//体力曲线
	DrawLifeCurve(pDC, 23, 1, 1, RGB(0,255,0));

	//情绪曲线
	DrawLifeCurve(pDC, 28, 1, 1, RGB(0,0,255));

	//智力曲线
	DrawLifeCurve(pDC, 33, 1, 1, RGB(255,0,0));
}

//画曲线
void BioGraphCtrl::DrawLifeCurve (CDC* pDC, int cycle, float range, int width, COLORREF color)
{
	const float Pi  = 3.1415926353f;

	CPen pen (PS_SOLID, width, color);
	CPen* oldPen = pDC->SelectObject(&pen); 

	CRect rect;
	GetClientRect(rect);
	rect.bottom -= 20;

	int offsDay = CalcDays() % cycle;

	int days = min (max ( int((m_endDate-m_startDate).GetDays ()), 7), 100);
	float xStep = float (rect.Width()-1) / days;

	for (float x = 0; x <= rect.right; x ++)
	{
		float y = rect.Height() / 2  - rect.Height() / 2 * range * float (sin((x + offsDay*xStep) * 2 * Pi / (cycle*xStep)));

		if (x == 0)
			pDC->MoveTo (int (x), int (y));
		else
			pDC->LineTo (int (x), int (y));
	}

	pDC->SelectObject (oldPen);
}

void BioGraphCtrl::DrawLabel (CDC* pDC)
{
}

//画焦点
void BioGraphCtrl::	DrawFocus (CDC* pDC)
{
	CRect rect;
	GetClientRect(rect);

	int days = min (max ( int((m_endDate-m_startDate).GetDays ()), 7), 100);
	float xStep = float (rect.Width()-1) / days;
	int offsDays = int ((m_focusDate - m_startDate).GetDays ());

	int x = int(xStep * offsDays);

	CPen pen (PS_SOLID, 3, m_focusColor);
	CPen* oldPen = pDC->SelectObject(&pen);

	pDC->MoveTo (x, rect.top);
	pDC->LineTo (x, rect.bottom - 20);
	pDC->LineTo (int(x + xStep), rect.bottom - 20);
	pDC->LineTo (int(x + xStep), rect.top);
	pDC->LineTo (x, rect.top);

	pDC->SelectObject (oldPen);

}

void BioGraphCtrl::DrawGuage (CDC* pDC)
{
	CRect rect;
	GetClientRect(rect);

	int days = min (max ( int((m_endDate-m_startDate).GetDays ()), 7), 100);
	float xStep = float (rect.Width()-1) / days;

	int fontHeight = max (6, min (int(xStep), 32));

	CFont font;
	font.CreateFont (fontHeight, 0, 0, 0, FW_EXTRALIGHT, 0, 0, 0,
		ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS,
		DRAFT_QUALITY, VARIABLE_PITCH | FF_SWISS,_T("Arial"));

	pDC->SelectObject(&font);
	pDC->SetBkMode(TRANSPARENT);
	pDC->SetTextColor(RGB(20,20,0));

	CTime curDate = m_startDate.GetTime();
	CTimeSpan day( 1, 0, 0, 0);
	for (float x = 0; x < rect.Width(); x += xStep)
	{
		CString str = curDate.Format("%d");
		pDC->TextOut(int(x + xStep / 5), rect.bottom - 20, str);
		curDate = curDate + day;
	}
}

int  BioGraphCtrl::CalcDays ()
{
	return int ((m_startDate - m_bornDate).GetDays ());
}

float BioGraphCtrl::Eval (CTime testDate, int cycle)
{
	const float Pi  = 3.1415926353f;

	int offsDay = (int ((testDate - m_bornDate).GetDays ())) % cycle;

	return float ((sin(float(offsDay) * 2 * Pi / cycle)) + 1) * 50;
}

CString BioGraphCtrl::EvalString(CTime testDate)
{
	CString str ="";

	str.Format("%s\r\n体力 %.f\r\n情绪 %.f\r\n智力 %.f\r\n", testDate.Format("%Y - %m - %d"), Eval(testDate, 23), Eval(testDate, 28), Eval(testDate, 33));
    return str;
}


BEGIN_MESSAGE_MAP(BioGraphCtrl, CWnd)
	ON_WM_LBUTTONDOWN()
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

void BioGraphCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
	GetParent ()->SendMessage (WM_BIO_SELECTCHANGED, GetDlgCtrlID (), NULL );

	CWnd::OnLButtonDown(nFlags, point);
}

void BioGraphCtrl::OnPaint()
{
	CPaintDC dc(this);
	CDC* pDC = &dc;

	DrawBackground (pDC);
	DrawGrid (pDC);
	DrawLifeCurve (pDC);
	DrawFocus (pDC);

	DrawLabel (pDC);
}

void BioGraphCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
	static CTime oldFocusDate = m_focusDate;

	CRect rect;
	GetClientRect(rect);

	int days = min (max ( int((m_endDate-m_startDate).GetDays ()), 7), 100);
	float xStep = float (rect.Width()-1) / days;

	CTimeSpan day( int (point.x / xStep), 0, 0, 0);
	m_focusDate = m_startDate.GetTime();
	m_focusDate += day;
	
	if (m_focusDate != oldFocusDate )
	{
		GetParent ()->SendMessage (WM_BIO_SELECTCHANGING, GetDlgCtrlID (), NULL );
		Invalidate ();
	}

	oldFocusDate = m_focusDate;

	CWnd::OnMouseMove(nFlags, point);
}