之前因为实验室做的一个项目中需要进行实时动态的曲线显示,在mfc上本来就没有多少可用的高级控件。负责这部分的学长用了mschart来做实时的曲线显示,但是效果基本还可以,但是因为重绘导致的闪烁还是很让客户觉得不是很好。所以后来我接手这部分后,就决定开始重新写一个曲线控件。从实现的效果来看,基本还是满足要求的。
主要的思想就是重绘,所有的东西都是画出来的。windows的所有控件都是画出来的,譬如按钮,简单来说就是一个方块。只是检测鼠标位置以及鼠标事件,当鼠标点击以及鼠标位置在方块位置上时,就表示这个按钮被点击了。所以自己模拟就可以了。这个也是现在windows下主流的一种客户端程序编程方法directUI。例如QQ的客户端、360的客户端等等都是利用这种方法完成的。不说这些,直接给出代码吧。
先给效果图吧!
#pragma once
#include <math.h>
#include <vector>
using namespace std;
struct LinePoint //ÕÛÏßµãÊýŸÝ
{
float x;
float y;
LinePoint(float a, float b)
{
x = a;
y = b;
}
};
struct LineChartData
{
vector<LinePoint> vecPoint; //µãÊýŸÝ
CString strLegend; //ÕÛÏß±êÇ©£¬Íš¹ýžÃ±êǩΚһȷ¶šÒ»ÌõÕÛÏß
bool bIsShow; //ÊÇ·ñÏÔÊŸ
//ÓÃÓÚ¹¹œšÕÛÏß»±Ê
int nLineStyle; //ÕÛÏß·çžñ
int nLineWidth; //ÕÛÏß¿í¶È
COLORREF cfLineColor; //ÕÛÏßÑÕÉ«
};
// CLineChart
class CLineChart : public CWnd
{
DECLARE_DYNAMIC(CLineChart)
private:
COLORREF m_cfBkColor; //ÕÛÏßÍŒ±³Ÿ°ÑÕÉ«
CRect m_rectLine; //ÕÛÏßÇøÓòλÖ㬻æÖÆÕÛÏßÇøÓò
CRect m_rectClient; //¿Í»§ÇøÇøÓòλÖÃ
int m_nTitleHeight; //±êÌâžß¶È
CString m_strTitle; //±êÌâÎÄ×Ö
CFont* m_pTitleFont; //±êÌâÎÄ×Ö×ÖÌå
int m_nLegendWidth; //ÕÛÏß±êÇ©ÎıŸ¿í¶È
CFont* m_pLegendFont; //±êÇ©ÎıŸ×ÖÌå
bool m_bIsXShowGrid; //XÖáÏÔÊŸÍøžñ±êÖŸ
float m_fXAxisStart; //XÖῪʌµã
float m_fXAxisStop; //XÖáœáÊøµã
float m_fXAxisStep; //XÖᲜ³€
CFont* m_pXAxisPointFont; //XÖá×ø±êµã×ÖÌå
CString m_strXAxisLegend; //XÖá±êÇ©ÎıŸ
CFont* m_pXAxisLegendFont; //XÖá±êÇ©ÎıŸ×ÖÌå
int m_nXAxisHeight; //XÖá±êÇ©Óë×ø±êµãžß¶È
bool m_bIsYShowGrid; //YÖáÏÔÊŸÍøžñ±êÖŸ
float m_fYAxisStart; //YÖῪʌµã
float m_fYAxisStop; //YÖáœáÊøµã
float m_fYAxisStep; //YÖᲜ³€
CString m_strYAxisLegend; //YÖá±êÇ©ÎıŸ
CFont* m_pYAxisPointFont; //YÖá×ø±êµã×ÖÌå
CFont* m_pYAxisLegendFont; //YÖá±êÇ©ÎıŸ×ÖÌå
int m_nYAxisWidth; //YÖá±êÇ©Óë×ø±êµãžß¶È
CPen* m_pPenGrid;//Íøžñ»±Ê
CPen* m_pPenAxis;//×ø±êÖá»±Ê
vector<LineChartData> m_vecChartData;
public:
CLineChart();
virtual ~CLineChart();
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
bool AddLine(CString strLegend, COLORREF cfColor, bool bIsShow = true);//ÌíŒÓÖ±Ïß
bool AddLine(CString strLegend, COLORREF cfColor, int nLineStyle, int nLineWidth, bool bIsShow = true);//ÌíŒÓÖ±Ïß
bool AddLineData(CString strLegend, LinePoint point);//ΪֱÏßÌíŒÓÒ»žöÊýŸÝµã
bool AddLineData(CString strLegend, vector<LinePoint> vecPoint);//ΪֱÏßÌíŒÓһϵÁÐÊýŸÝµã
void SetBkColor(COLORREF cfColor);//ÉèÖñ³Ÿ°ÑÕÉ«
void SetTitleText(CString strTitle);//ÉèÖñêÌâÀžÎıŸ
void SetXAxisText(CString strText);//ÉèÖÃXÖá±êÇ©
void SetYAxisText(CString strText);//ÉèÖÃYÖá±êÇ©
void SetXAxisData(float fStart, float fStop, float fStep);//ÉèÖÃXÖáµÄÊýŸÝÊôÐÔ£¬°üÀš¿ªÊŒ×ø±ê£¬œáÊø×ø±êÓ벜³€
void SetYAxisData(float fStart, float fStop, float fStep);//ÉèÖÃYÖáµÄÊýŸÝÊôÐÔ£¬°üÀš¿ªÊŒ×ø±ê£¬œáÊø×ø±êÓ벜³€
void ShowXAxisGrid(bool bIsShow);//ÏÔÊŸXÖáµÄÍøžñ
void ShowYAxisGrid(bool bIsShow);//ÏÔÊŸYÖáµÄÍøžñ
protected:
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnPaint();
void DrawLine(vector<LineChartData>::iterator itor, CDC* pDC);//»æÖÆÕÛÏß
void DrawTitle(CDC* pDC);//»æÖƱêÌâÀž
void DrawLegend(CDC* pDC);//»æÖƱêÇ©ÎıŸ
void DrawXAxis(CDC* pDC);//»æÖÆXÖá±êÇ©ÎıŸÍøžñ
void DrawYAxis(CDC* pDC);//»æÖÆXÖá±êÇ©ÎıŸÍøžñ
};
// LineChart.cpp : ʵÏÖÎÄŒþ
//
#include "stdafx.h"
#include "ChartTest.h"
#include "LineChart.h"
// CLineChart
IMPLEMENT_DYNAMIC(CLineChart, CWnd)
CLineChart::CLineChart()
{
m_cfBkColor = RGB(236, 233, 216);
m_nTitleHeight = 20;
m_strTitle = _T("ÎÒÊÇÒ»žö±êÌâÀž");
m_pTitleFont = new CFont();
m_pTitleFont->CreatePointFont(120, _T("ËÎÌå"));
m_nLegendWidth = 30;
m_pLegendFont = new CFont();
m_pLegendFont->CreatePointFont(100, _T("ËÎÌå"));
m_bIsXShowGrid = true;
m_fXAxisStart = 0;
m_fXAxisStop = 10;
m_fXAxisStep = 1;
m_pXAxisPointFont = new CFont();
m_pXAxisPointFont->CreatePointFont(90, _T("ËÎÌå"));
m_strXAxisLegend = _T("XÖá±êÇ©±êÇ©");
m_pXAxisLegendFont = new CFont();
m_pXAxisLegendFont->CreatePointFont(120, _T("ËÎÌå"));
m_nXAxisHeight = 20;
m_bIsYShowGrid = true;
m_fYAxisStart = 0;
m_fYAxisStop = 10;
m_fYAxisStep = 1;
m_pYAxisPointFont = new CFont();
m_pYAxisPointFont->CreatePointFont(90, _T("ËÎÌå"));
m_strYAxisLegend = _T("YÖá");
m_pYAxisLegendFont = new CFont();
m_pYAxisLegendFont->CreateFontW(18, 0, 900, 900, FW_NORMAL,
0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH, _T("Arial"));
// m_pYAxisLegendFont->CreatePointFont(120, _T("ËÎÌå"));
m_pPenGrid = new CPen();
m_pPenGrid->CreatePen(PS_DOT, 1, RGB(0, 0, 0));
m_pPenAxis = new CPen();
m_pPenAxis->CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
m_nYAxisWidth = 20;
}
CLineChart::~CLineChart()
{
if (NULL != m_pPenAxis)
{
m_pPenAxis->DeleteObject();
}
if (NULL != m_pPenGrid)
{
m_pPenGrid->DeleteObject();
}
if (NULL != m_pLegendFont)
{
m_pLegendFont->DeleteObject();
}
if (NULL != m_pTitleFont)
{
m_pTitleFont->DeleteObject();
}
if (NULL != m_pXAxisLegendFont)
{
m_pXAxisLegendFont->DeleteObject();
}
if (NULL != m_pXAxisPointFont)
{
m_pXAxisPointFont->DeleteObject();
}
if (NULL != m_pYAxisLegendFont)
{
m_pYAxisLegendFont->DeleteObject();
}
if (NULL != m_pYAxisPointFont)
{
m_pYAxisPointFont->DeleteObject();
}
}
BEGIN_MESSAGE_MAP(CLineChart, CWnd)
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
END_MESSAGE_MAP()
// CLineChart ÏûÏ¢ŽŠÀí³ÌÐò
BOOL CLineChart::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: ÔÚŽËÌíŒÓךÓÃŽúÂëºÍ/»òµ÷ÓûùÀà
return CWnd::Create(NULL, _T(""), WS_CHILD | WS_VISIBLE, rect, pParentWnd, nID);
}
int CLineChart::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
void CLineChart::SetBkColor(COLORREF cfColor)
{
m_cfBkColor = cfColor;
}
BOOL CLineChart::OnEraseBkgnd(CDC* pDC)
{
// TODO: ÔÚŽËÌíŒÓÏûÏ¢ŽŠÀí³ÌÐòŽúÂëºÍ/»òµ÷ÓÃĬÈÏÖµ
return true;
}
void CLineChart::OnPaint()
{
CPaintDC dc(this);
CDC* pMemDC = new CDC();
CBitmap* pBmp = new CBitmap();
CSize szExent;
//»ñÈ¡¿Í»§ÇøλÖÃ
GetClientRect(m_rectClient);
pMemDC->CreateCompatibleDC(&dc);
pBmp->CreateCompatibleBitmap(&dc, m_rectClient.Width(), m_rectClient.Height());
pMemDC->SelectObject(pBmp);
pMemDC->SetBkMode(TRANSPARENT);
//»æÖƱ³Ÿ°
pMemDC->FillSolidRect(m_rectClient, m_cfBkColor);
DrawTitle(pMemDC);//»æÖƱêÌâÀž
DrawLegend(pMemDC);//»æÖƱêÇ©Àž
//ÐÞžÄXÖá±êÇ©Àžžß¶È
pMemDC->SelectObject(m_pXAxisLegendFont);
szExent = pMemDC->GetTextExtent(m_strXAxisLegend);
m_nXAxisHeight = szExent.cy + 10;
pMemDC->SelectObject(m_pXAxisPointFont);
szExent = pMemDC->GetTextExtent(m_strXAxisLegend);
m_nXAxisHeight += szExent.cy + 5;
//»æÖÆYÖá
DrawYAxis(pMemDC);
//»æÖÆXÖá
DrawXAxis(pMemDC);
//É趚ÕÛÏß»æÖÆÇøÓòŽóС
m_rectLine.top = m_nTitleHeight;
m_rectLine.bottom = m_rectClient.bottom - m_nXAxisHeight;
m_rectLine.left = m_nYAxisWidth;
m_rectLine.right = m_rectClient.right - m_nLegendWidth;
//»æÖÆÕÛÏß
for (vector<LineChartData>::iterator itor = m_vecChartData.begin(); itor != m_vecChartData.end(); itor++)
{
if ((*itor).bIsShow)
{
DrawLine(itor, pMemDC);
}
}
dc.BitBlt(0, 0, m_rectClient.Width(), m_rectClient.Height(), pMemDC, 0, 0, SRCCOPY);
pBmp->DeleteObject();
ReleaseDC(pMemDC);
ReleaseDC(&dc);
}
void CLineChart::DrawTitle(CDC* pDC)
{
//È·¶š±êÌâÀžžß¶È
pDC->SelectObject(m_pTitleFont);
CSize szExent = pDC->GetTextExtent(m_strTitle);
CPoint pt;
m_nTitleHeight = szExent.cy + 20;
//»æÖƱêÌâ
szExent = pDC->GetTextExtent(m_strTitle);
pt.x = (m_rectClient.Width() - szExent.cx) / 2;
pt.y = (m_nTitleHeight - szExent.cy) / 2;
pDC->TextOutW(pt.x, pt.y, m_strTitle);
}
void CLineChart::DrawLegend(CDC* pDC)
{
CSize szExent;
CPoint pt;
pDC->SelectObject(m_pLegendFont);
m_nLegendWidth = -1;
//»ñÈ¡×îŽóµÄ±êÇ©ÎıŸ³€¶ÈÓÃÓÚÈ·¶š±êÇ©ÀžµÄ¿í¶È
for (vector<LineChartData>::iterator itor = m_vecChartData.begin(); itor != m_vecChartData.end(); itor++)
{
if ((*itor).bIsShow)
{
szExent = pDC->GetTextExtent((*itor).strLegend);
if (szExent.cx > m_nLegendWidth)
{
m_nLegendWidth = szExent.cx;
}
}
}
m_nLegendWidth += 40;
//»æÖƱêÇ©ÀžÎıŸÓëÑÕÉ«±êʶÏß
pt.x = m_rectClient.right - m_nLegendWidth + 40;
pt.y = m_rectClient.top + m_nTitleHeight + 10;
for (vector<LineChartData>::iterator itor = m_vecChartData.begin(); itor != m_vecChartData.end(); itor++)
{
if ((*itor).bIsShow)
{
CPen* pPen = new CPen();
pPen->CreatePen(PS_SOLID, 2, (*itor).cfLineColor);
pDC->SelectObject(pPen);
pDC->MoveTo(pt.x - 30, pt.y + szExent.cy / 2);
pDC->LineTo(pt.x - 5, pt.y + szExent.cy / 2);
pDC->TextOutW(pt.x, pt.y, (*itor).strLegend);
pt.y += 10 + szExent.cy;
pPen->DeleteObject();
}
}
}
void CLineChart::DrawYAxis(CDC* pDC)
{
//»æÖÆYÖá±êÇ©
CPoint pt;
int nMaxWidth = 0; //×ø±êÖµµÄ×îŽó¿í¶È
CString str;
int nStep ;//×ø±êÖµÖ®Œä»æÖƵĿí¶ÈÏñËØŒäžô
pDC->SelectObject(m_pYAxisLegendFont);
CSize szExent = pDC->GetTextExtent(m_strYAxisLegend);
pt.x = 5;
pt.y = (m_rectClient.Height() - m_nTitleHeight - szExent.cy) / 2;
pDC->TextOutW(pt.x, pt.y, m_strYAxisLegend);
//»æÖÆYÖá×ø±ê
pDC->SelectObject(m_pYAxisPointFont);
m_nYAxisWidth = pt.x + szExent.cy + 10;
//»ñÈ¡×îŽóµÄYÖá×ø±êÖµ¿í¶È
for (float i = m_fYAxisStart; i <= m_fYAxisStop; i += m_fYAxisStep) //»ñÈ¡YÖá×ø±ê×îŽó¿í¶È
{
str.Format(_T("%.2f"), i);
szExent = pDC->GetTextExtent(str);
if (nMaxWidth < szExent.cx)
{
nMaxWidth = szExent.cx;
}
}
m_nYAxisWidth += nMaxWidth;
//»æÖÆYÖá×ø±êÖá,°üÀšŒýÍ·ÓëÖ±ÏßÖá
pDC->SelectObject(m_pPenAxis);
pDC->MoveTo(m_nYAxisWidth - 3, m_rectClient.top + m_nTitleHeight - 7);
pDC->LineTo(m_nYAxisWidth, m_rectClient.top + m_nTitleHeight - 15);
pDC->LineTo(m_nYAxisWidth + 3, m_rectClient.top + m_nTitleHeight - 7);
pDC->MoveTo(m_nYAxisWidth, m_rectClient.top + m_nTitleHeight - 15);
pDC->LineTo(m_nYAxisWidth, m_rectClient.bottom - m_nXAxisHeight);
nStep = (m_rectClient.Height() - m_nTitleHeight - m_nXAxisHeight) / ((m_fYAxisStop - m_fYAxisStart) / m_fYAxisStep);
if (nStep < 40) //µ÷ÕûYÖᲜ³€
{
m_fYAxisStep *= 2;
m_fYAxisStop = ceil((m_fYAxisStop - m_fYAxisStart) / m_fYAxisStep) * m_fYAxisStep + m_fYAxisStart;
Invalidate();
return;
}
//»æÖÆYÖá×ø±êµã£¬×ø±êλÖÃÓëÍøžñ
for (float i = m_fYAxisStart; i <= m_fYAxisStop; i += m_fYAxisStep)
{
//»æÖÆYÖá×ø±êµã
str.Format(_T("%.2f"), i);
szExent = pDC->GetTextExtent(str);
pt.x = m_nYAxisWidth - szExent.cx - 5;
pt.y = m_rectClient.bottom - m_nXAxisHeight - (i - m_fYAxisStart) / m_fYAxisStep * nStep - szExent.cy / 2;
pDC->TextOutW(pt.x, pt.y, str);
//»æÖÆYÖá×ø±êµãλÖÃ
pDC->SelectObject(m_pPenAxis);
pDC->MoveTo(m_nYAxisWidth, pt.y + szExent.cy / 2);
pDC->LineTo(m_nYAxisWidth + 5, pt.y + szExent.cy / 2);
//»æÖÆYÖáÍøžñ
if (m_bIsYShowGrid)
{
pDC->SelectObject(m_pPenGrid);
pDC->LineTo(m_rectClient.right - m_nLegendWidth, pt.y + szExent.cy / 2);
}
}
//ŒÆËã×îÓÒ±ßXÖáÍøžñÏßλÖÃ
pDC->SelectObject(m_pXAxisPointFont);
str.Format(_T("%.0f"), m_fXAxisStop);
szExent = pDC->GetTextExtent(str);
//XÖá×ø±êµãλÖòœ³€
nStep = (m_rectClient.Width() - m_nYAxisWidth - m_nLegendWidth) / ((m_fXAxisStop - m_fXAxisStart) / m_fXAxisStep);
if (nStep < 40) //µ÷ÕûXÖᲜ³€
{
m_fXAxisStep *= 2;
m_fXAxisStop = ceil((m_fXAxisStop - m_fXAxisStart) / m_fXAxisStep) * m_fXAxisStep + m_fXAxisStart;
Invalidate();
return;
}
pt.x = m_rectClient.left + m_nYAxisWidth + (m_fXAxisStop - m_fXAxisStart) / m_fXAxisStep * nStep - szExent.cx / 2;
pt.y = m_rectClient.bottom - m_nXAxisHeight + 5;
//Èô»æÖÆYÖáÍøžñ,µ«²»»æÖÆXÖáÍøžñÏߣ¬Ôò»æÖÆ×îÓÒ±ßXÖáÍøžñÏß
if (m_bIsYShowGrid && !m_bIsXShowGrid)
{
pDC->MoveTo(pt.x + szExent.cx / 2, m_rectClient.bottom - m_nXAxisHeight - 5);
pDC->LineTo(pt.x + szExent.cx / 2, m_rectClient.top + m_nTitleHeight);
}
if (m_bIsYShowGrid)
{
//È¥³ý×îÓÒ±ßXÖáÍøžñÏßÓұߵĶàÓàÍøžñÏß
CRect rectClear;
rectClear.left = pt.x + szExent.cx / 2 + 1;
rectClear.right = m_rectClient.right - m_nLegendWidth;
rectClear.bottom = m_rectClient.bottom - m_nXAxisHeight - 1;
rectClear.top = m_rectClient.top + m_nTitleHeight + 1;
pDC->FillSolidRect(rectClear, m_cfBkColor);
}
}
void CLineChart::DrawXAxis(CDC* pDC)
{
//»æÖÆXÖá±êÇ©
CPoint pt;
int nStep; //XÖá×ø±êŒäµÄÏñËØŒäžô
CString str;
pDC->SelectObject(m_pXAxisLegendFont);
CSize szExent = pDC->GetTextExtent(m_strXAxisLegend);
pt.x = (m_rectClient.Width() - m_nYAxisWidth - m_nLegendWidth - szExent.cx) / 2 + m_nYAxisWidth;
pt.y = m_rectClient.bottom - szExent.cy - 5;
pDC->TextOutW(pt.x, pt.y, m_strXAxisLegend);
//»æÖÆXÖá×ø±êÖᣬ°üÀšŒýÍ·ÓëÖ±ÏßÖá
pDC->SelectObject(m_pPenAxis);
pDC->MoveTo(m_rectClient.right - m_nLegendWidth + 7, m_rectClient.bottom - m_nXAxisHeight - 3);
pDC->LineTo(m_rectClient.right - m_nLegendWidth + 15, m_rectClient.bottom - m_nXAxisHeight);
pDC->LineTo(m_rectClient.right - m_nLegendWidth + 7, m_rectClient.bottom - m_nXAxisHeight + 3);
pDC->MoveTo(m_nYAxisWidth, m_rectClient.bottom - m_nXAxisHeight);
pDC->LineTo(m_rectClient.right - m_nLegendWidth + 15, m_rectClient.bottom - m_nXAxisHeight);
pDC->SelectObject(m_pXAxisPointFont);
nStep = (m_rectClient.Width() - m_nYAxisWidth - m_nLegendWidth) / ((m_fXAxisStop - m_fXAxisStart) / m_fXAxisStep);
if (nStep < 40) //µ÷ÕûXÖᲜ³€
{
m_fXAxisStep *= 2;
m_fXAxisStop = ceil((m_fXAxisStop - m_fXAxisStart) / m_fXAxisStep) * m_fXAxisStep + m_fXAxisStart;
Invalidate();
return;
}
for (float i = m_fXAxisStart; i <= m_fXAxisStop; i += m_fXAxisStep)
{
//»æÖÆXÖá×ø±êµã
str.Format(_T("%.0f"), i);
szExent = pDC->GetTextExtent(str);
pt.x = m_rectClient.left + m_nYAxisWidth + (i - m_fXAxisStart) / m_fXAxisStep * nStep - szExent.cx / 2;
pt.y = m_rectClient.bottom - m_nXAxisHeight + 5;
pDC->TextOutW(pt.x, pt.y, str);
//»æÖÆXÖá×ø±êµãλÖÃ
pDC->SelectObject(m_pPenAxis);
pDC->MoveTo(pt.x + szExent.cx / 2, m_rectClient.bottom - m_nXAxisHeight);
pDC->LineTo(pt.x + szExent.cx / 2, m_rectClient.bottom - m_nXAxisHeight - 5);
//»æÖÆXÖá±ížñ
if (m_bIsXShowGrid)
{
pDC->SelectObject(m_pPenGrid);
pDC->LineTo(pt.x + szExent.cx / 2, m_rectClient.top + m_nTitleHeight);
}
}
//ŒÆËãYÖá×îÉÏÃæÍøžñÏßλÖÃ
pDC->SelectObject(m_pYAxisPointFont);
str.Format(_T("%.2f"), m_fYAxisStop);
szExent = pDC->GetTextExtent(str);
//YÖá×ø±êµãÏñËØλÖòœ³€
nStep = (m_rectClient.Height() - m_nTitleHeight - m_nXAxisHeight) / ((m_fYAxisStop - m_fYAxisStart) / m_fYAxisStep);
if (nStep < 40) //µ÷ÕûYÖᲜ³€
{
m_fYAxisStep *= 2;
m_fYAxisStop = ceil((m_fYAxisStop - m_fYAxisStart) / m_fYAxisStep) * m_fYAxisStep + m_fYAxisStart;
Invalidate();
return;
}
pt.x = m_nYAxisWidth - szExent.cx - 5;
pt.y = m_rectClient.bottom - m_nXAxisHeight - (m_fYAxisStop - m_fYAxisStart) / m_fYAxisStep * nStep - szExent.cy / 2;
//Èô»æÖÆXÖáÍøžñ,µ«²»»æÖÆYÖáÍøžñÏߣ¬Ôò»æÖÆ×îÉÏÃæYÖáÍøžñÏß
if (!m_bIsYShowGrid && m_bIsXShowGrid)
{
pDC->MoveTo(m_nYAxisWidth + 5, pt.y + szExent.cy / 2);
pDC->LineTo(m_rectClient.right - m_nLegendWidth, pt.y + szExent.cy / 2);
}
if (m_bIsXShowGrid)
{
//È¥³ý×îÉÏÃæYÖáÍøžñÏßÉϱߵĶàÓàÍøžñÏß
CRect rectClear;
rectClear.left = m_rectClient.left + m_nYAxisWidth + 1;
rectClear.right = m_rectClient.right - m_nLegendWidth;
rectClear.bottom = pt.y + szExent.cy / 2;
rectClear.top = m_rectClient.top + m_nTitleHeight + 1;
pDC->FillSolidRect(rectClear, m_cfBkColor);
}
}
void CLineChart::DrawLine(vector<LineChartData>::iterator itor, CDC* pDC)
{
//ŽŽœšÕÛÏß»±Ê
CPen* pPen = new CPen();
CPoint pt;
int nXStep = m_rectLine.Width() / ((m_fXAxisStop - m_fXAxisStart) / m_fXAxisStep);
int nYStep = m_rectLine.Height() / ((m_fYAxisStop - m_fYAxisStart) / m_fYAxisStep);
pPen->CreatePen((*itor).nLineStyle, (*itor).nLineWidth, (*itor).cfLineColor);
pDC->SelectObject(pPen);
vector<LinePoint>::iterator ptItor = (*itor).vecPoint.begin();
while (ptItor != (*itor).vecPoint.end())
{
if ((*ptItor).x < m_fXAxisStart && (*ptItor).x > m_fXAxisStop)
{
continue;
}
if ((*ptItor).y < m_fYAxisStart)
{
m_fYAxisStart -= (int)((m_fYAxisStart - (*ptItor).y) / m_fYAxisStep + 1) * m_fYAxisStep;
Invalidate();
return;
}
else if ((*ptItor).y > m_fYAxisStop)
{
m_fYAxisStop += (int)(((*ptItor).y - m_fYAxisStop) / m_fYAxisStep + 1) * m_fYAxisStep;
Invalidate();
return;
}
else
{
//È·¶šÕÛÏßµãλÖÃ
pt.x = m_rectLine.left + ((*ptItor).x - m_fXAxisStart) / m_fXAxisStep * nXStep;
pt.y = m_rectLine.bottom - ((*ptItor).y - m_fYAxisStart) / m_fYAxisStep * nYStep;
//»æÖÆÕÛÏß
if (ptItor == (*itor).vecPoint.begin())
{
pDC->MoveTo(pt.x, pt.y);
}
else
{
pDC->LineTo(pt.x, pt.y);
}
}
ptItor++;
}
pPen->DeleteObject();
}
bool CLineChart::AddLine(CString strLegend, COLORREF cfColor, bool bIsShow)
{
vector<LineChartData>::iterator itor = m_vecChartData.begin();
bool bIsExist = false; //ÅжÏÕÛÏßÊÇ·ñÒÑŸŽæÔÚ
while (itor != m_vecChartData.end())
{
if ((*itor).strLegend == strLegend)
{
bIsExist = true;
break;
}
itor++;
}
if (bIsExist) //žÃÕÛÏßÒÑŸŽæÔÚ£¬žü»»±êÇ©ÎıŸºóÖØÐÂÌíŒÓ
{
return false;
}
else
{
//ÌíŒÓžÃÕÛÏß
LineChartData line;
line.strLegend = strLegend;
line.cfLineColor = cfColor;
line.nLineStyle = PS_SOLID;
line.nLineWidth = 1;
line.bIsShow = bIsShow;
m_vecChartData.push_back(line);
return true;
}
}
bool CLineChart::AddLine(CString strLegend, COLORREF cfColor, int nLineStyle, int nLineWidth, bool bIsShow)
{
vector<LineChartData>::iterator itor = m_vecChartData.begin();
bool bIsExist = false; //ÅжÏÕÛÏßÊÇ·ñÒÑŸŽæÔÚ
while (itor != m_vecChartData.end())
{
if ((*itor).strLegend == strLegend)
{
bIsExist = true;
break;
}
itor++;
}
if (bIsExist) //žÃÕÛÏßÒÑŸŽæÔÚ£¬žü»»±êÇ©ÎıŸºóÖØÐÂÌíŒÓ
{
return false;
}
else
{
//ÌíŒÓžÃÕÛÏß
LineChartData line;
line.strLegend = strLegend;
line.cfLineColor = cfColor;
line.nLineStyle = nLineStyle;
line.nLineWidth = nLineWidth;
line.bIsShow = bIsShow;
m_vecChartData.push_back(line);
return true;
}
}
bool CLineChart::AddLineData(CString strLegend, LinePoint point)
{
vector<LineChartData>::iterator itor = m_vecChartData.begin();
for (;itor != m_vecChartData.end(); itor++)
{
if ((*itor).strLegend == strLegend)
{
(*itor).vecPoint.push_back(point);
if (point.x > m_fXAxisStop)
{
m_fXAxisStop += ceil((point.x - m_fXAxisStop) / m_fXAxisStep) * m_fXAxisStep;
}
else if (point.x < m_fXAxisStart)
{
m_fXAxisStart -= ceil((m_fXAxisStart - point.x) / m_fXAxisStep) * m_fXAxisStep;
}
return true;
}
}
return false;
}
bool CLineChart::AddLineData(CString strLegend, vector<LinePoint> vecPoint)
{
vector<LineChartData>::iterator itor = m_vecChartData.begin();
vector<LinePoint>::iterator ptItor = vecPoint.begin();
for (;itor != m_vecChartData.end(); itor++)
{
if ((*itor).strLegend == strLegend)
{
for (; ptItor != vecPoint.end(); ptItor++)
{
(*itor).vecPoint.push_back((*ptItor));
if ((*ptItor).x > m_fXAxisStop)
{
m_fXAxisStop += ceil(((*ptItor).x - m_fXAxisStop) / m_fXAxisStep) * m_fXAxisStep;
}
else if ((*ptItor).x < m_fXAxisStart)
{
m_fXAxisStart -= ceil((m_fXAxisStart - (*ptItor).x) / m_fXAxisStep) * m_fXAxisStep;
}
}
return true;
}
}
return false;
}
void CLineChart::SetTitleText(CString strTitle)
{
m_strTitle = strTitle;
}
void CLineChart::SetXAxisText(CString strText)
{
m_strXAxisLegend = strText;
}
void CLineChart::SetYAxisText(CString strText)
{
m_strYAxisLegend = strText;
}
void CLineChart::SetXAxisData(float fStart, float fStop, float fStep)
{
m_fXAxisStart = fStart;
m_fXAxisStop = fStop;
m_fXAxisStep = fStep;
}
void CLineChart::SetYAxisData(float fStart, float fStop, float fStep)
{
m_fYAxisStart = fStart;
m_fYAxisStop = fStop;
m_fYAxisStep = fStep;
}
void CLineChart::ShowXAxisGrid(bool bIsShow)
{
m_bIsXShowGrid = bIsShow;
}
void CLineChart::ShowYAxisGrid(bool bIsShow)
{
m_bIsYShowGrid = bIsShow;
}