📄 multicolorplotctrl.cpp
字号:
////////////////////////////////////////////////////////////////////////
//文件名 :MULTICOLORPLOT.CPP
//控件说明:实时曲线显示功能控件,提供LINE和BAR两种曲线显示功能
///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MultiColorPlotCtrl.h"
#include ".\multicolorplotctrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMultiColorPlotCtrl
CMultiColorPlotCtrl::CMultiColorPlotCtrl()
: nPlotType(BAR)
, nGridResolutionX(10)
, nGridResolutionY(10)
, nGridScrollSpeedX(-2)
, nGridScrollSpeedY(0)
, nPlotGranulatrity(2)
, nGridLineWidth(1)
, m_clrDarkBack(RGB(0,128,0))
, m_clrDarkLine(RGB(32,64,32))
, nPlotData(0)
, pfData(NULL)
, fLow(0.0)
, fHigh(100.0)
, fScaleY(1.0)
, m_clrCyanData(RGB(0,255,255))
, nGridStarPosX(0)
, nGridStarPosY(0)
, bLock(true)
, m_clrAxisScaleY(RGB(0,255,255))
, nShowFormatDataText(0)
, m_clrLinePen(RGB(0,255,0))
, nLineWidth(1)
{
// 关键代码
// 初始化关键代码的 C_S 结构
InitializeCriticalSection ( & g_cs ) ;
// 初始化标题
_stprintf ( szTitls , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
// 初始化单位
_stprintf ( szUints , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
}
CMultiColorPlotCtrl::~CMultiColorPlotCtrl()
{
if ( pfData )
{
delete [] pfData ;
}
// 释放关键代码
DeleteCriticalSection ( & g_cs ) ;
}
BEGIN_MESSAGE_MAP(CMultiColorPlotCtrl, CStatic)
//{{AFX_MSG_MAP(CMultiColorPlotCtrl)
ON_WM_PAINT()
//}}AFX_MSG_MAP
ON_WM_ERASEBKGND()
ON_WM_TIMER()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMultiColorPlotCtrl message handlers
void CMultiColorPlotCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
// 获得控件区域
GetClientRect (&m_rectCtrl);
// 创建内存 DC
CMemDC *pMemDC = new CMemDC(&dc, &m_rectCtrl);
CPoint orgBrushOrigin = pMemDC->GetBrushOrg () ;
if(m_dcBackground.GetSafeHdc() == NULL || m_pBitmapBackground.m_hObject == NULL)
{
m_dcBackground.CreateCompatibleDC(&dc);
m_pBitmapBackground.CreateCompatibleBitmap(&dc, m_rectCtrl.Width(),m_rectCtrl.Height()) ;
m_pBitmapOldBackground = m_dcBackground.SelectObject(&m_pBitmapBackground) ;
InitColorPlot(&m_dcBackground);
}
pMemDC->BitBlt(0, 0, m_rectCtrl.Width(), m_rectCtrl.Height(),
&m_dcBackground, 0, 0, SRCCOPY) ;
//画曲线背景和网格
DrawBackGroundGrid(pMemDC);
//画曲线数据
DrawValue(pMemDC);
//画曲线Y刻度
DrawAxisScaleYValue(pMemDC);
pMemDC->SetBrushOrg ( orgBrushOrigin.x , orgBrushOrigin.y ) ;
delete pMemDC ;
}
// 设置画线的类型
void CMultiColorPlotCtrl::SetPlotType(int nType)
{
nPlotType = nType ;
}
// 数据点面积大小(即:一个数据点占据的像素数)
BOOL CMultiColorPlotCtrl::SetPlotGranulatrity(int nPlotGrltiy)
{
nPlotGranulatrity = nPlotGrltiy ;
nPlotData = m_Size.cx / nPlotGranulatrity ;
pfData = new float [nPlotData] ;
if ( pfData )
{
// 初始化数据为 0
ZeroMemory ( pfData , sizeof ( pfData ) * nPlotData ) ;
return TRUE ;
}
return FALSE ;
}
// 前景色
void CMultiColorPlotCtrl::SetGridLineClr(COLORREF clr)
{
m_clrDarkLine = clr ;
m_GridPen.CreatePen ( PS_SOLID , nGridLineWidth , m_clrDarkLine ) ;
m_clrDarkLine = clr ;
}
// 数据范围
void CMultiColorPlotCtrl::SetRang(float fL, float fH)
{
fLow = fL ;
fHigh = fH ;
}
// 创建画笔
void CMultiColorPlotCtrl::SetLinePen(int nWidth, COLORREF clr)
{
nGridLineWidth = nWidth ;
m_clrDarkLine = clr ;
m_GridPen.CreatePen ( PS_SOLID , nGridLineWidth , m_clrDarkLine ) ;
}
// Y轴刻度颜色
void CMultiColorPlotCtrl::SetAxisScaleClrY(COLORREF clr)
{
m_clrAxisScaleY = clr ;
}
// 标题
void CMultiColorPlotCtrl::SetTitle(LPCTSTR pctTitle)
{
_stprintf ( szTitls , _TEXT ( "%s" ) , pctTitle ) ;
}
// 数据单位例:SetUnit( _TEXT ( "(k/sec)" ) ) ;
void CMultiColorPlotCtrl::SetUnit(LPCTSTR pctUint)
{
_stprintf ( szUints , _TEXT ( "%s" ) , pctUint ) ;
}
// 是否显示数据标题、颜色、单位
/*
nShow = 0 ; 不显示任何文本
nShow = 1 ; 仅仅显示标题
nShow = 2 ; 仅仅显示标题和流量总计
nShow = 3 ; 显示标题和最小值
nShow = 4 ; 显示标题、最小值和中值
*/
void CMultiColorPlotCtrl::ShowTitle(int nShow)
{
nShowFormatDataText = nShow ;
}
// BAR 颜色
// clrUp -------- 顶部颜色
// clrDown -------- 底部颜色
// bfRfastness -------- 红色分量是否固定不变 false ---- 渐变
// bfGfastness -------- 红色分量是否固定不变 false ---- 渐变
// bfBfastness -------- 红色分量是否固定不变 false ---- 渐变
void CMultiColorPlotCtrl::SetBarColor(COLORREF clrUp, COLORREF clrDown, bool bfRfastness, bool bfGfastness, bool bfBfastness)
{
}
// 曲线颜色
void CMultiColorPlotCtrl::SetLineColorWidth(COLORREF clrLine, int nWidth)
{
nLineWidth = nWidth ;
m_clrLinePen = clrLine ;
}
void CMultiColorPlotCtrl::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
// 相应通告消息
ModifyStyle( 0 , SS_NOTIFY ) ;
GetClientRect ( & m_rectCtrl ) ;
// 得到该控件的宽和高
m_Size.cx = m_rectCtrl.right - m_rectCtrl.left ;
m_Size.cy = m_rectCtrl.bottom - m_rectCtrl.top ;
// 计算控件可容纳可见的数据点数
nPlotData = m_Size.cx / nPlotGranulatrity ;
// 设置控件上显示的文字的字体和大小
m_SmallFont.CreateFont( -11 , 0 , 0 , 0 , FW_THIN , false , false , false , DEFAULT_CHARSET ,
OUT_DEFAULT_PRECIS , CLIP_DEFAULT_PRECIS , DEFAULT_QUALITY , VARIABLE_PITCH , _TEXT( "Times New Roman" ) ) ;
// 给实际数据分配内存
pfData = new float [ nPlotData ] ;
if ( pfData )
{
// 初始化数据为 0
ZeroMemory ( pfData , sizeof ( pfData ) * nPlotData ) ;
m_GridPen.CreatePen ( PS_SOLID , nGridLineWidth , m_clrDarkLine ) ;
CRgn m_Rgn ;
m_Rgn.CreateRoundRectRgn ( 0 , 0 , m_Size.cx , m_Size.cy , 10 , 10 ) ;
SetWindowRgn ( ( HRGN ) m_Rgn , true ) ;
SetTimer ( GRID_TIMER , GRID_UPDATE_SPEED , NULL ) ;
}
CStatic::PreSubclassWindow();
}
BOOL CMultiColorPlotCtrl::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
return TRUE;
}
void CMultiColorPlotCtrl::ReconstructControl(void)
{
}
void CMultiColorPlotCtrl::InitColorPlot(CDC *pDC)
{
// 根据不同的曲线分别绘制
if ( nPlotType == BAR )
{
double factor = 255.0 / ( float ) m_Size.cy ;
BYTE r , g , b ;
for ( int x = 0 ; x < m_Size.cy ; x ++ )
{
g = ( BYTE ) ( 255 - factor * x ) ;
r = ( BYTE ) ( factor * x ) ;
b = ( BYTE ) 64 ;
pDC->SetPixelV ( 0 , x , RGB ( r , g , b ) ) ;
pDC->SetPixelV ( 1 , x , RGB ( r , g , b ) ) ;
}
}
else if ( nPlotType == LINE )
{
}
else
{
}
pDC->SelectObject ( m_pBitmapOldBackground ) ;
// 生成位图画刷
m_clrBrush.CreatePatternBrush ( & m_pBitmapBackground ) ;
}
//绘制网格和背景
void CMultiColorPlotCtrl::DrawBackGroundGrid(CDC * pDC)
{
// 填充背景色
pDC->FillSolidRect ( & m_rectCtrl , m_clrDarkBack ) ;
// 画网格
int nGridLinesX = m_Size.cx / nGridResolutionX ;
int nGridLinesY = m_Size.cy / nGridResolutionY ;
// 选择画笔
CPen * pOldPen = pDC->SelectObject ( & m_GridPen ) ;
// 创建垂直线
for ( int x = 0 ; x <= nGridLinesX ; x ++ )
{
pDC->MoveTo ( x * nGridResolutionX + nGridStarPosX , 0 );
pDC->LineTo ( x * nGridResolutionX + nGridStarPosX , m_Size.cy );
}
// 添加水平线
for ( int y = 0 ; y <= nGridLinesY ; y ++ )
{
pDC->MoveTo ( 0 , nGridStarPosY + m_Size.cy - y * nGridResolutionY - 2 ) ;
pDC->LineTo ( m_Size.cx , nGridStarPosY + m_Size.cy - y * nGridResolutionY - 2 ) ;
}
// 控制网格正确移动
nGridStarPosX += nGridScrollSpeedX ;
nGridStarPosY += nGridScrollSpeedY ;
if ( nGridStarPosX < 0 ) nGridStarPosX = nGridResolutionX ;
if ( nGridStarPosX > nGridResolutionX ) nGridStarPosX = 0 ;
if ( nGridStarPosY < 0 ) nGridStarPosY = nGridResolutionY ;
if ( nGridStarPosY > nGridResolutionY ) nGridStarPosY = 0 ;
// 还原网格画笔
pDC->SelectObject ( pOldPen ) ;
}
void CMultiColorPlotCtrl::DrawValue(CDC * pDC)
{
float fx , fy ;
// 用关键代码同步和SetData
EnterCriticalSection ( & g_cs ) ;
if ( nPlotType == BAR )
{
RECT rFill ;
for ( int nData = 0 ; nData < nPlotData ; nData ++ )
{
fx = ( float ) ( m_rectCtrl.left + nData * nPlotGranulatrity ) ;
fy = ( float ) fabs ( ( float ) ( m_rectCtrl.bottom - ( ( ( ( pfData[nData] - fLow ) / ( fHigh - fLow ) ) * m_Size.cy ) ) ) ) ;
rFill.bottom = ( LONG ) m_rectCtrl.bottom ;
rFill.top = ( LONG ) fy ;
rFill.left = ( LONG ) fx ;
rFill.right = ( LONG ) ( fx + nPlotGranulatrity ) ;
pDC->SetBrushOrg ( ( int ) fx , m_rectCtrl.bottom ) ;
// 用初始化画刷时生成的渐变位图画刷填充矩形
pDC->FillRect ( & rFill , & m_clrBrush ) ;
// 画数据点处的颜色
pDC->SetPixelV ( ( int ) fx , ( int ) fy , m_clrCyanData ) ;
}
}
else if ( nPlotType == LINE )
{
CPoint * g_DataPoint = new CPoint [nPlotData] ;
// 创建曲线画笔
CPen m_Pen ;
m_Pen.CreatePen ( PS_SOLID , nLineWidth , m_clrLinePen ) ;
CPen * m_pOldPen = pDC->SelectObject ( & m_Pen ) ;
for ( int nData = 0 ; nData < nPlotData ; nData ++ )
{
g_DataPoint[nData].x = ( LONG ) ( m_rectCtrl.left + nData * nPlotGranulatrity ) ;
g_DataPoint[nData].y = ( LONG ) fabs ( ( float ) ( m_rectCtrl.bottom - ( ( ( ( pfData[nData] - fLow ) / ( fHigh - fLow ) ) * m_Size.cy ) ) ) ) ;
}
pDC->Polyline ( g_DataPoint , nPlotData ) ;
pDC->SelectObject ( m_pOldPen ) ;
delete [] g_DataPoint ;
}
else
{
}
}
void CMultiColorPlotCtrl::DrawAxisScaleYValue(CDC * pDC)
{
CFont * pOldFont ;
// 绘制Y轴刻度
TCHAR szAxisScaleYMax [MAX_PATH * sizeof ( TCHAR ) + 1] ;
TCHAR szAxisScaleYMin [MAX_PATH * sizeof ( TCHAR ) + 1] ;
TCHAR szAxisScaleY [MAX_PATH * sizeof ( TCHAR ) + 1] ;
ZeroMemory ( & szAxisScaleYMax , sizeof ( szAxisScaleYMax ) ) ;
ZeroMemory ( & szAxisScaleYMin , sizeof ( szAxisScaleYMin ) ) ;
ZeroMemory ( & szAxisScaleY , sizeof ( szAxisScaleY ) ) ;
COLORREF clrText = pDC->GetTextColor () ;
int nBkMode = pDC->GetBkMode () ;
pDC->SetTextColor ( m_clrAxisScaleY ) ;
pDC->SetBkMode ( TRANSPARENT ) ;
pOldFont = pDC->SelectObject ( & m_SmallFont ) ;
// 如果要求现实Y轴刻度数字
switch ( nShowFormatDataText )
{
case 0 : // 不显示
{
}
break ;
case 1 : // 仅显示标题
{
_stprintf ( szAxisScaleYMax , _TEXT ( "%s" ) , szTitls ) ;
pDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
}
break ;
case 2 : // 显示标题和流量比例
{
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
pDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
}
break ;
case 3 : // 显示最大最小值
{
// 格式化最大值和标题及单位
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
// 格式化最小值
_stprintf ( szAxisScaleYMin , _TEXT ( "%8.1f" ) , fLow ) ;
pDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
pDC->TextOut ( 0 , m_Size.cy - 10 , szAxisScaleYMin ) ;
}
break ;
case 4 : // 显示全部
{
// 格式化最大值和标题及单位
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
// 格式化最小值
_stprintf ( szAxisScaleYMin , _TEXT ( "%8.1f" ) , fLow ) ;
// 格式化中值
_stprintf ( szAxisScaleY , _TEXT ( "%8.1f" ) , ( ( fHigh - fLow ) / 2.0 + fLow ) ) ;
// 绘制Y轴刻度
pDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
pDC->TextOut ( 0 , m_Size.cy - 10 , szAxisScaleYMin ) ;
pDC->TextOut ( 0 , m_Size.cy / 2 , szAxisScaleY ) ;
} break ;
}
pDC->SetTextColor ( clrText ) ;
pDC->SetBkMode ( nBkMode ) ;
pDC->SelectObject ( pOldFont ) ;
// 离开关键代码
LeaveCriticalSection ( & g_cs ) ;
}
void CMultiColorPlotCtrl::OnTimer(UINT nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
switch ( nIDEvent )
{
case GRID_TIMER :
{
}
break ;
}
Invalidate ( false ) ;
CStatic::OnTimer(nIDEvent);
}
// 设置网格间距
void CMultiColorPlotCtrl::SetGridResolutionX(int nGridReluX)
{
nGridResolutionX = nGridReluX ;
}
// 设置网格间距
void CMultiColorPlotCtrl::SetGridResolutionY(int nGridReluY)
{
nGridResolutionY = nGridReluY ;
}
// 设置网格滚动速度,正值为从左向右滚动,0不动
void CMultiColorPlotCtrl::SetGridScrollSpeedX(int nSpeedX)
{
nGridScrollSpeedX = nSpeedX ;
}
// 正值为从上到下滚动,0不动
void CMultiColorPlotCtrl::SetGridScrollSpeedY(int nSpeedY)
{
nGridScrollSpeedY = nSpeedY ;
}
// 网格线宽度
void CMultiColorPlotCtrl::SetGridLineWidth(int nWidth)
{
nGridLineWidth = nWidth ;
}
// 背景色
void CMultiColorPlotCtrl::SetGridBackClr(COLORREF clr)
{
m_clrDarkBack = clr ;
}
// // 锁定数据显示范围
void CMultiColorPlotCtrl::LockRang(bool bfLock)
{
bLock = bfLock ;
}
// 锁定数据显示范围
void CMultiColorPlotCtrl::LockRang(float fMin, float fMax)
{
fLow = fMin ;
fHigh = fMax ;
LockRang ( true ) ;
}
// 设置数据
void CMultiColorPlotCtrl::SetData(float fData)
{
// 用关键代码同步
EnterCriticalSection ( & g_cs ) ;
for ( int n = 0 ; n < nPlotData - 1 ; n ++ )
{
pfData [ n ] = pfData [ n + 1 ] ;
}
pfData [ nPlotData - 1 ] = fData ;
if ( bLock ) // 锁定比例范围
{
}
else
{
// 保存最小值
if ( fLow > fData )
{
fLow = fData ;
}
// 保存最大值
if ( fHigh < fData )
{
fHigh = fData ;
}
}
// 离开关键代码
LeaveCriticalSection ( & g_cs ) ;
}
// 曲线颜色
void CMultiColorPlotCtrl::SetLineColor(COLORREF clrLine)
{
m_clrLinePen = clrLine ;
}
void CMultiColorPlotCtrl::SetLineWidth(int nWidth)
{
nLineWidth = nWidth ;
}
const COLORREF CMultiColorPlotCtrl::GetLineColor(void)
{
return m_clrLinePen ;
}
const int CMultiColorPlotCtrl::GetLineWidth(void)
{
return nLineWidth ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -