📄 chart.cpp
字号:
#include "stdafx.h"
#include "Chart.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CChart
CChart::CChart()
{
SetRange(-10,10,-10,10);
strChartTitle = "Untitled Chart" ;
strLabelX = "x" ;
strLabelY = "y" ;
iChartType = 2 ;
nGridX = 10 ;
nGridY = 10 ;
bIsSerieAllocated = FALSE ;
bLogScale = FALSE ;
bFontIsCreate = FALSE ;
bBkNeedToUpdate = TRUE ;
nPlotIndex = 0 ;
nPointCount = 0 ;
nSerieCount = 1 ;
m_BGColor = RGB(0,255,255);
m_AxisColor = RGB(0,0,0);
m_GridColor = RGB(120,120,120);
}
CChart::~CChart()
{
for( int i = 0 ; i < nSerieCount ; i++){
mpSerie[i].FreeSerie() ;
}
if(memBkDC.GetSafeHdc() != NULL)
memBkDC.SelectObject(m_pOldBkBitmap);
if( bFontIsCreate ) {
delete pLegendFontY ;
delete pLegendFontX ;
delete pTitleFont ;
}
}
BEGIN_MESSAGE_MAP(CChart, CWnd)
//{{AFX_MSG_MAP(CChart)
ON_WM_PAINT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CChart message handlers
BOOL CChart::Create(DWORD dwStyle, CRect &rect, CWnd *pParent, UINT id)
{
//DWORD style = dwStyle & ( ~WS_BORDER ) ;
//static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
BOOL result ;
result = CWnd::CreateEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE,
NULL, NULL, dwStyle,
rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
pParent->GetSafeHwnd(), (HMENU)id) ;
if( !result )
AfxMessageBox("Error creating window");
m_ctlRect = rect ;
pParent->ClientToScreen(m_ctlRect) ;
ScreenToClient(m_ctlRect) ;
CreateFont(); // Get system font for label draw
bFontIsCreate = TRUE ;
CalcRect() ; // Compute rectangle
ResCalc(); // Compute resolution per dot .
return result ;
}
void CChart::CalcRect()
{
int offsetX , offsetY ;
if(m_ctlRect)
{
m_clientRect.left = m_ctlRect.left+2 ;
m_clientRect.right = m_ctlRect.right-2 ;
m_clientRect.top = m_ctlRect.top+2 ;
m_clientRect.bottom = m_ctlRect.bottom-2;
} else {
m_clientRect = m_ctlRect ;
}
//Calculate offset of window to be 4/5 of its window .
offsetY = m_clientRect.Height()/5 ;
offsetX = m_clientRect.Width()/5 ;
m_axisRect.left = m_clientRect.left + (offsetX) ;
m_axisRect.right = m_clientRect.right - (offsetX/2) ;
m_axisRect.top = m_clientRect.top + (offsetY) ;
m_axisRect.bottom = m_clientRect.bottom - (offsetY) ;
}
//////////////////////////////////////////////////////////
// Draw box and fill color inside it .
void CChart::DrawBorder(CDC *pDC)
{
CBrush brushCtl;//(m_BGColor);
brushCtl.CreateSolidBrush(m_BGColor);
pDC->Rectangle(m_clientRect);
pDC->FillRect(m_clientRect,&brushCtl) ;
}
void CChart::DrawAxis(CDC *pDC)
{
CPen *old , pen(PS_SOLID, 2, m_AxisColor) ;
old = pDC->SelectObject(&pen) ;
double dcenter ;
switch( iChartType ) {
case 0:
pDC->MoveTo(Corrdinate(dRangeX[MIN],dRangeY[MIN]));
pDC->LineTo(Corrdinate(dRangeX[MAX],dRangeY[MIN]));
pDC->MoveTo(Corrdinate(dRangeX[MIN],dRangeY[MIN]));
pDC->LineTo(Corrdinate(dRangeX[MIN],dRangeY[MAX]));
break;
case 1:
dcenter = (dRangeY[MAX] + dRangeY[MIN]) / 2 ;
pDC->MoveTo(Corrdinate(dRangeX[MIN],dcenter));
pDC->LineTo(Corrdinate(dRangeX[MAX],dcenter));
pDC->MoveTo(Corrdinate(dRangeX[MIN],dRangeY[MIN]));
pDC->LineTo(Corrdinate(dRangeX[MIN],dRangeY[MAX]));
break;
case 2:
//draw vertical axis
dcenter = (dRangeX[MAX] + dRangeX[MIN]) /2 ;
pDC->MoveTo(Corrdinate(dcenter,dRangeY[MIN]));
pDC->LineTo(Corrdinate(dcenter,dRangeY[MAX]));
//draw horizontal axis
dcenter = (dRangeY[MAX] + dRangeY[MIN]) /2 ;
pDC->MoveTo(Corrdinate(dRangeX[MIN],dcenter));
pDC->LineTo(Corrdinate(dRangeX[MAX],dcenter));
break;
}
pDC->SelectObject(old) ;
}
CPoint CChart::Corrdinate(double x, double y)
{
double rx , ry ;
int xPixel , yPixel ;
CPoint retPt ;
rx = x - dRangeX[MIN] ; // Calculate horizontal offset from origin
ry = y - dRangeY[MIN] ; // Calculate vertical offset from origin .
// Convert offset to be number of pixel on screen .
xPixel = (int)(rx / dResX) ;
yPixel = (int)(ry / dResY) ;
//Calulate point to be drawn .
retPt.x= xPixel + m_axisRect.left ;
retPt.y= m_axisRect.bottom - yPixel;
return retPt ;
}
void CChart::Plot(CDC *pDC)
{
// If there is no data available for plot then return .
if ( !nPlotIndex ) return ;
CPen *old , *pen ;
CPoint pt ;
int i;
for( i = 0 ; i < nSerieCount ; i++) {
// Create the new pen as the color of serie
pen = new CPen(PS_SOLID,0,mpSerie[i].m_plotColor);
old = pDC->SelectObject(pen);
// calculate the corrdinate of ploting point.
pt = Corrdinate(mpSerie[i].dValueX[0],mpSerie[i].dValueY[0]) ;
pDC->MoveTo(pt);
//Start plot all available data .
for(int index = 1 ; index <= nPlotIndex ; index++){
pt = Corrdinate(mpSerie[i].dValueX[index],
mpSerie[i].dValueY[index]) ;
pDC->LineTo(pt) ;
}
pDC->SelectObject(old);
delete pen ;
}
}
void CChart::DrawChartTitle(CDC *pDC)
{
int x , y ;
int oldbkmode ;
CFont *old ;
old = pDC->SelectObject(pTitleFont);
oldbkmode = pDC->SetBkMode(TRANSPARENT) ;
CSize textSize = pDC->GetTextExtent(strChartTitle,
strChartTitle.GetLength()) ;
//Calculate centre window corrdinate of text ;
pDC->SetTextAlign(TA_LEFT);
y = m_ctlRect.top + (textSize.cy/2) ;
x = m_clientRect.left +
(m_clientRect.Width()/2) - (textSize.cx/2) ;
pDC->TextOut(x,y,strChartTitle) ;
pDC->SetBkMode(oldbkmode);
pDC->SelectObject(old);
}
void CChart::DrawGrid(CDC *pDC)
{
CPen *old , pen(PS_SOLID, 0, m_GridColor);
CPoint m_start, m_stop ;
int i ;
double x ,y ;
double step ;
old = pDC->SelectObject(&pen);
// Draw vertical grid
step = (dRangeX[MAX] - dRangeX[MIN]) / (double)nGridX ;
for( i = 0 ; i <= nGridX ; i++ )
{
x = dRangeX[MIN] + (step * (double)i) ;
m_start = Corrdinate(x,dRangeY[MIN]);
m_stop = Corrdinate(x,dRangeY[MAX]);
pDC->MoveTo(m_start);
pDC->LineTo(m_stop);
}
// Draw horizontal grid.
step = (dRangeY[MAX] - dRangeY[MIN]) / (double)nGridY ;
for( i = 0 ; i <= nGridY ; i++ )
{
y = dRangeY[MIN] + (step * (double)i) ;
m_start = Corrdinate(dRangeX[MIN],y) ;
m_stop = Corrdinate(dRangeX[MAX],y) ;
pDC->MoveTo(m_start);
pDC->LineTo(m_stop);
}
pDC->SelectObject(old);
}
BOOL CChart::SetRange(double dMinX, double dMaxX,
double dMinY,double dMaxY)
{
bBkNeedToUpdate = TRUE ; // Background need to be re-draw
dRangeY[MIN] = dMinY ;
dRangeY[MAX] = dMaxY ;
dRangeX[MAX] = dMaxX ;
dRangeX[MIN] = dMinX ;
ResCalc();
return TRUE ;
}
////////////////////////////////////////////////////////
//Calculate resolution per dot
void CChart::ResCalc()
{
double dpixelx, dpixely ;
dpixelx = (double)m_axisRect.Width() ;
dpixely = (double)m_axisRect.Height() ;
dResY = (dRangeY[MAX] - dRangeY[MIN]) / dpixely ;
dResX = (dRangeX[MAX] - dRangeX[MIN]) / dpixelx ;
}
///////////////////////////////////////////////////////
// Set Axis style
//
void CChart::SetAxisStyle(int iStyle)
{
if( (iStyle > 2) || (iStyle < 0) ) return ;
iChartType = iStyle ;
}
////////////////////////////////////////////////////////
// Draw 1/5 fine scale in log mode
// in order to implement log grid set bLogScale = TRUE
void CChart::DrawLogGrid(CDC *pDC)
{
// Change this number for changing number of fine scales.
const int FINE_SCALE = 5 ;
CPen *old , pen(PS_SOLID, 0, RGB(192,192,192)) ;
CPoint m_start, m_stop ;
int i ;
int j ;
double y ;
double step ;
double Ymax , Ymin ;
Ymax = dRangeY[MAX] ;
Ymin = dRangeY[MIN] ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -