chartwnd.cpp
来自「The application wizard has created this 」· C++ 代码 · 共 552 行 · 第 1/2 页
CPP
552 行
/************************************************************************************************
// $Header: /home/cvsroot/SoccerDoctor/Chart/ChartWnd.cpp,v 1.5 2002/09/10 06:44:35 peter Exp $
//***********************************************************************************************
/************************************************************************************************/
/* */
/* File : ChartWnd.cpp */
/* */
/* Purpose : interface for the plot area of the CChartCtrl */
/* */
/* Author : Scott Pelger Date Created: 10JUN02 */
/* */
/* Revisions */
/* */
/* Engineer Date Description */
/* */
/* Scott Pelger 10JUN02 initial version */
/* */
/************************************************************************************************/
#include "stdafx.h"
#include "ChartWnd.h"
#include <time.h>
#include "MemDC.h"
CChartWnd::CChartWnd() :
m_Axis(),
m_pYAxisFont(NULL),
m_bRotate(FALSE),
m_eStyle(SHOW_POPUP_WINDOWS_BR),
m_pCurrentDataPoint(NULL),
m_bScrolling(FALSE),
m_bRefreshDisplayCompletely(FALSE) {}
CChartWnd::~CChartWnd() {
if (m_pYAxisFont){
m_pYAxisFont->DeleteObject();
delete m_pYAxisFont;
}
m_GraphBitmap.DeleteObject();
m_WholeBitmap.DeleteObject();
}
BEGIN_MESSAGE_MAP(CChartWnd, CChartWndBase)
//{{AFX_MSG_MAP(CChartWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/************************************************************************************************/
/* */
/* Function: CChartWnd::DrawChart() */
/* */
/* Purpose : carries out the grunt work of drawing the chart using a mem dc to prevent the */
/* control from flickering. after the control is completely drawn a copy is made to */
/* be used in OnPaint for fast updates. */
/* */
/* Inputs : NONE */
/* */
/* Outputs : NONE */
/* */
/* Author : Scott Pelger Date Created: 15MAY02 */
/* */
/* Revisions */
/* */
/* Engineer Date Description */
/* */
/* Scott Pelger 15MAY02 initial version */
/* */
/************************************************************************************************/
void CChartWnd::DrawChart() {
CClientDC dc(this);
/****set up the memory DC****/
CMemDC memDC(&dc);
CBitmap memBitmap;
CRect rcClient;
GetClientRect(&rcClient);
int nRectWidth(rcClient.Width());
int nRectHeight(rcClient.Height());
m_rcClientRect = rcClient;
memBitmap.CreateCompatibleBitmap(&dc, nRectWidth, nRectHeight);
CBitmap* pOldBitmap = memDC.SelectObject(&memBitmap);
/****set up the memory DC****/
memDC.FillSolidRect(&m_rcClientRect, m_crWindowColor);
memDC.SelectObject(m_pFont);
memDC.SetTextColor(m_crTextColor);
m_rcClientRect.DeflateRect(5, 5);
if (TYPE_BAR==m_DataSeriesArray.GetChartType()) {
m_Axis.SetAxisScale(X_AXIS, 0, m_DataSeriesArray.GetMaxInAllSeries()+1);
m_Axis.SetScaleStep(X_AXIS, 1, 1);
}
m_Axis.DrawAxis(&memDC, &m_rcClientRect);
//if the vertical scaling has changed we need to force
//a complete redraw of the chart, if we are not scrolling
//then we always do a full redraw
if (m_Axis.HasVerticalScalingChanged()){
m_bRefreshDisplayCompletely = !(m_bScrolling = FALSE);
}
m_DataSeriesArray.DrawData(&memDC, &m_Axis);
m_DataSeriesArray.DrawIcons(&memDC, &m_Axis);
dc.BitBlt(rcClient.left, rcClient.top, nRectWidth, nRectHeight, &memDC, 0, 0, SRCCOPY);
if (m_DataSeriesArray.DataRemoved()&&TYPE_STRIP_CHART_FILLED==m_eChartType){
m_bScrolling = TRUE;
}
// memDC 和 memDC2 析构的顺序不同导致GDI资源泄漏,maybe
CMemDC memDC2(&memDC);
m_PlotRect = m_Axis.GetRect();
m_GraphBitmap.DeleteObject();
m_GraphBitmap.CreateCompatibleBitmap(&dc, m_PlotRect.Width(), m_PlotRect.Height());
memDC2.SelectObject(&m_GraphBitmap);
memDC2.BitBlt(0, 0, m_PlotRect.Width(), m_PlotRect.Height(), &memDC, m_PlotRect.left, m_PlotRect.top, SRCCOPY);
//next, let's make a copy of the entire chart window for fast OnPaint() updates
GetClientRect(&rcClient);
m_WholeBitmap.DeleteObject();
m_WholeBitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
memDC2.SelectObject(&m_WholeBitmap);
memDC2.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);
// 防止资源泄漏
memDC.SelectObject(pOldBitmap);
memBitmap.DeleteObject();
}
void CChartWnd::OnPaint() {
CRect rcClient;
GetClientRect(&rcClient);
CPaintDC dc(this);
CMemDC memDC(&dc);
memDC.SelectObject(&m_WholeBitmap);
dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);
}
/************************************************************************************************/
/* */
/* Function: CChartWnd::SetFont() */
/* */
/* Purpose : carries out the grunt work of drawing the chart using a mem dc to prevent the */
/* control from flickering. after the control is completely drawn a copy is made to */
/* be used in OnPaint for fast updates. */
/* */
/* Inputs : BYTE byPointSize -> desired point size of font */
/* char* psFontName -> desired font name to use */
/* BYTE byStyle -> desired styles of font such as BOLD, ITALIC, and UNDERLINE */
/* */
/* Outputs : BOOL <- TRUE if an error occured, FALSE otherwise */
/* */
/* Author : Scott Pelger Date Created: 15MAY02 */
/* */
/* Revisions */
/* */
/* Engineer Date Description */
/* */
/* Scott Pelger 15MAY02 initial version */
/* */
/************************************************************************************************/
BOOL CChartWnd::SetFont(BYTE byPointSize, char* psFontName, BYTE byStyle/*=0*/) {
CChartWndBase::SetFont(byPointSize, psFontName, byStyle);
if (m_pYAxisFont)
m_pYAxisFont->DeleteObject();
if (!m_pYAxisFont) {
m_pYAxisFont = new CFont;
if (!m_pYAxisFont)
return TRUE;
}
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
strcpy(lf.lfFaceName, psFontName);
lf.lfHeight = byPointSize*10;
lf.lfWeight = byStyle&BOLD?FW_BOLD:FW_NORMAL;
lf.lfItalic = byStyle&ITALIC;
lf.lfUnderline = byStyle&UNDERLINE;
lf.lfOrientation = 900;
lf.lfEscapement = 900;
CClientDC dc(this);
m_pYAxisFont->CreatePointFontIndirect(&lf, &dc);
m_Axis.m_pYAxisFont = m_pYAxisFont;
m_Axis.m_pFont = m_pFont;
return FALSE;
}
/************************************************************************************************/
/* */
/* Function: CChartWnd::_DataPointHitTest() */
/* */
/* Purpose : cycles through all data points and determines if this point lies within it's */
/* detect region */
/* */
/* Inputs : CPoint& Point -> the point to test */
/* */
/* Outputs : CDataPoint* <- pointer to the data point if found */
/* */
/* Author : Scott Pelger Date Created: 12JUN02 */
/* */
/* Revisions */
/* */
/* Engineer Date Description */
/* */
/* Scott Pelger 12JUN02 initial version */
/* Scott Pelger 27JUN02 return NULL if chart is any strip chart */
/* Scott Pelger 28JUN02 force nNumberOfSeries to 1 if chart is any pie chart, */
/* skip data series' that contain no data points */
/* */
/************************************************************************************************/
CDataPoint* CChartWnd::_DataPointHitTest(CPoint& Point) {
if (TYPE_STRIP_CHART ==m_DataSeriesArray.GetChartType()||
TYPE_STRIP_CHART_FILLED ==m_DataSeriesArray.GetChartType())
return NULL;
int nNumberOfSeries(m_DataSeriesArray.GetCount());
int nNumberInSeries(m_DataSeriesArray.GetMaxInAllSeries());
CDataSeries* pDataSeries = NULL;
CDataPoint* pDataPoint = NULL;
if (TYPE_PIE ==m_DataSeriesArray.GetChartType()||
TYPE_ROTATED_PIE==m_DataSeriesArray.GetChartType())
nNumberOfSeries = 1;
for (int i(nNumberOfSeries-1);i>-1;i--) {
if (!(pDataSeries = (CDataSeries*)m_DataSeriesArray.GetDataSeries(i)))
continue;
for (int j(nNumberInSeries-1);j>-1;j--) {
//if no data points in this series skip on to the next
if (!(pDataSeries->GetCount()))
break;
if (!(pDataPoint = pDataSeries->GetAt(j)))
continue;
if (TYPE_AREA==m_eChartType) {
//for area chart we only have one data point to test for
if (!(pDataPoint = pDataSeries->GetAt(0)))
continue;
}
if (pDataPoint->m_DetectRegion.PtInRegion(Point))
return pDataPoint;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?