?? multicolorplotbtn.cpp
字號:
//////////////////////////////////// MulticolorPlotBtn.cpp ////////////////////////////////////
#include "StdAfx.h"
#include ".\multicolorplotbtn.h"
#include "MemDC.h"
#define GRID_TIMER 1
//網(wǎng)格刷新速率
#define GRID_UPDATE_SPEED 50
typedef struct
{
float fx ;
float fy ;
} DATA_POINT ;
DATA_POINT * g_DataPoint ;
CMulticolorPlotBtn::CMulticolorPlotBtn()
: nPlotType(BAR)
, bfInit(false)
, nGridResolutionX(10)
, nGridResolutionY(10)
, nGridScrollSpeedX(-1)
, nGridScrollSpeedY(0)
, nPlotGranulatrity(2)
, nGridLineWidth(1)
, m_clrDarkBack(RGB(0,0,75))
, 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)
{
// 關(guān)鍵代碼
// 初始化關(guān)鍵代碼的 C_S 結(jié)構(gòu)
InitializeCriticalSection ( & g_cs ) ;
// 初始化標(biāo)題
_stprintf ( szTitls , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
// 初始化單位
_stprintf ( szUints , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
}
CMulticolorPlotBtn::~CMulticolorPlotBtn(void)
{
if ( pfData )
{
delete [] pfData ;
}
// 釋放關(guān)鍵代碼
DeleteCriticalSection ( & g_cs ) ;
}
BEGIN_MESSAGE_MAP(CMulticolorPlotBtn, CButton)
ON_WM_TIMER()
END_MESSAGE_MAP()
void CMulticolorPlotBtn::PreSubclassWindow()
{
// TODO: 在此添加專用代碼和/或調(diào)用基類
// 避免把該按鈕當(dāng)成下壓式按鈕
ModifyStyle( 0 , BS_OWNERDRAW ) ;
GetWindowRect ( & m_rect ) ;
ScreenToClient ( & m_rect ) ;
// 得到該控件的寬和高
m_Size.cx = m_rect.right - m_rect.left ;
m_Size.cy = m_rect.bottom - m_rect.top ;
// 計算控件可容納可見的數(shù)據(jù)點數(shù)
nPlotData = m_Size.cx / nPlotGranulatrity ;
// 設(shè)置控件上顯示的文字的字體和大小
m_SmallFont.CreateFont( -11 , 0 , 0 , 0 , FW_THIN , false , false , false , DEFAULT_CHARSET ,
OUT_DEFAULT_divCIS , CLIP_DEFAULT_divCIS , DEFAULT_QUALITY , VARIABLE_PITCH , _TEXT( "Times New Roman" ) ) ;
// 給實際數(shù)據(jù)分配內(nèi)存
pfData = new float [ nPlotData ] ;
if ( pfData )
{
// 初始化數(shù)據(jù)為 0
ZeroMemory ( pfData , sizeof ( pfData ) * nPlotData ) ;
m_GridPen.CreatePen ( PS_SOLID , nGridLineWidth , m_clrDarkLine ) ;
GetWindowRect ( & m_rect ) ;
ScreenToClient ( & m_rect ) ;
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 ) ;
}
CButton::PreSubclassWindow();
}
void CMulticolorPlotBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: 添加您的代碼以繪制指定項
ASSERT( lpDrawItemStruct != NULL ) ;
CDC * pDC = CDC::FromHandle( lpDrawItemStruct -> hDC ) ;
// 創(chuàng)建內(nèi)存 DC
CMemDC * pMemDC = new CMemDC ( pDC ) ;
// 得到控件大小
RECT clipRect ;
pMemDC->GetClipBox ( & clipRect ) ;
if ( bfInit == false )
{
// 如果沒有初始化,則初始化畫刷
CBitmap m_Bmp ;
// 如果控件大小有效
if ( clipRect.right - clipRect.left > 1 )
{
// 根據(jù)數(shù)據(jù)點分辨率創(chuàng)建內(nèi)存位圖
m_Bmp.CreateCompatibleBitmap( pMemDC ,nPlotGranulatrity , m_Size.cy ) ;
CBitmap * pOldBmp = pMemDC->SelectObject( & m_Bmp ) ;
CSize m_BmpSize = m_Bmp.GetBitmapDimension () ;
// 根據(jù)不同的曲線分別繪制
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 ;
pMemDC->SetPixelV ( 0 , x , RGB ( r , g , b ) ) ;
pMemDC->SetPixelV ( 1 , x , RGB ( r , g , b ) ) ;
}
}
else if ( nPlotType == LINE )
{
}
else
{
}
pMemDC->SelectObject ( pOldBmp ) ;
// 生成位圖畫刷
m_clrBrush.CreatePatternBrush ( & m_Bmp ) ;
bfInit = true ;
}
}
if ( bfInit )
{
// 填充背景色
pMemDC->FillSolidRect ( & clipRect , m_clrDarkBack ) ;
CFont * pOldFont ;
//
CPoint orgBrushOrigin = pMemDC->GetBrushOrg () ;
// 畫網(wǎng)格
int nGridLinesX = m_Size.cx / nGridResolutionX ;
int nGridLinesY = m_Size.cy / nGridResolutionY ;
// 選擇畫筆
CPen * pOldPen = pMemDC->SelectObject ( & m_GridPen ) ;
// 創(chuàng)建垂直線
for ( int x = 0 ; x <= nGridLinesX ; x ++ )
{
pMemDC->MoveTo ( x * nGridResolutionX + nGridStarPosX , 0 );
pMemDC->LineTo ( x * nGridResolutionX + nGridStarPosX , m_Size.cy );
}
// 添加水平線
for ( int y = 0 ; y <= nGridLinesY ; y ++ )
{
pMemDC->MoveTo ( 0 , nGridStarPosY + m_Size.cy - y * nGridResolutionY - 2 ) ;
pMemDC->LineTo ( m_Size.cx , nGridStarPosY + m_Size.cy - y * nGridResolutionY - 2 ) ;
}
// 控制網(wǎng)格正確移動
nGridStarPosX += nGridScrollSpeedX ;
nGridStarPosY += nGridScrollSpeedY ;
if ( nGridStarPosX < 0 ) nGridStarPosX = nGridResolutionX ;
if ( nGridStarPosX > nGridResolutionX ) nGridStarPosX = 0 ;
if ( nGridStarPosY < 0 ) nGridStarPosY = nGridResolutionY ;
if ( nGridStarPosY > nGridResolutionY ) nGridStarPosY = 0 ;
// 還原網(wǎng)格畫筆
pMemDC->SelectObject ( pOldPen ) ;
// 用關(guān)鍵代碼同步和SetData
EnterCriticalSection ( & g_cs ) ;
// 畫數(shù)據(jù)
float fx , fy ;
if ( nPlotType == BAR )
{
RECT rFill ;
for ( int nData = 0 ; nData < nPlotData ; nData ++ )
{
fx = ( float ) ( m_rect.left + nData * nPlotGranulatrity ) ;
fy = fabs ( ( float ) ( m_rect.bottom - ( ( ( ( pfData[nData] - fLow ) / ( fHigh - fLow ) ) * m_Size.cy ) ) ) ) ;
rFill.bottom = ( LONG ) m_rect.bottom ;
rFill.top = ( LONG ) fy ;
rFill.left = ( LONG ) fx ;
rFill.right = ( LONG ) ( fx + nPlotGranulatrity ) ;
pMemDC->SetBrushOrg ( ( int ) fx , m_rect.bottom ) ;
// 用初始化畫刷時生成的漸變位圖畫刷填充矩形
pMemDC->FillRect ( & rFill , & m_clrBrush ) ;
// 畫數(shù)據(jù)點處的顏色
pMemDC->SetPixelV ( ( int ) fx , ( int ) fy , m_clrCyanData ) ;
}
}
else if ( nPlotType == LINE )
{
CPoint * g_DataPoint = new CPoint [nPlotData] ;
// 創(chuàng)建曲線畫筆
CPen m_Pen ;
m_Pen.CreatePen ( PS_SOLID , nLineWidth , m_clrLinePen ) ;
CPen * m_pOldPen = pMemDC->SelectObject ( & m_Pen ) ;
for ( int nData = 0 ; nData < nPlotData ; nData ++ )
{
g_DataPoint[nData].x = ( LONG ) ( m_rect.left + nData * nPlotGranulatrity ) ;
g_DataPoint[nData].y = ( LONG ) fabs ( ( float ) ( m_rect.bottom - ( ( ( ( pfData[nData] - fLow ) / ( fHigh - fLow ) ) * m_Size.cy ) ) ) ) ;
}
pMemDC->Polyline ( g_DataPoint , nPlotData ) ;
pMemDC->SelectObject ( m_pOldPen ) ;
delete [] g_DataPoint ;
}
else
{
}
// 繪制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 = pMemDC->GetTextColor () ;
int nBkMode = pMemDC->GetBkMode () ;
pMemDC->SetTextColor ( m_clrAxisScaleY ) ;
pMemDC->SetBkMode ( TRANSPARENT ) ;
pOldFont = pMemDC->SelectObject ( & m_SmallFont ) ;
// 如果要求現(xiàn)實Y軸刻度數(shù)字
switch ( nShowFormatDataText )
{
case 0 : // 不顯示
{
} break ;
case 1 : // 僅顯示標(biāo)題
{
_stprintf ( szAxisScaleYMax , _TEXT ( "%s" ) , szTitls ) ;
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
} break ;
case 2 : // 顯示標(biāo)題和流量比例
{
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
} break ;
case 3 : // 顯示最大最小值
{
// 格式化最大值和標(biāo)題及單位
_stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;
// 格式化最小值
_stprintf ( szAxisScaleYMin , _TEXT ( "%8.1f" ) , fLow ) ;
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
pMemDC->TextOut ( 0 , m_Size.cy - 10 , szAxisScaleYMin ) ;
} break ;
case 4 : // 顯示全部
{
// 格式化最大值和標(biāo)題及單位
_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軸刻度
pMemDC->TextOut ( 0 , 0 , szAxisScaleYMax ) ;
pMemDC->TextOut ( 0 , m_Size.cy - 10 , szAxisScaleYMin ) ;
pMemDC->TextOut ( 0 , m_Size.cy / 2 , szAxisScaleY ) ;
} break ;
}
pMemDC->SetTextColor ( clrText ) ;
pMemDC->SetBkMode ( nBkMode ) ;
pMemDC->SelectObject ( pOldFont ) ;
// 離開關(guān)鍵代碼
LeaveCriticalSection ( & g_cs ) ;
pMemDC->SetBrushOrg ( orgBrushOrigin.x , orgBrushOrigin.y ) ;
}
delete pMemDC ;
ReleaseDC ( pDC ) ;
}
void CMulticolorPlotBtn::OnTimer(UINT nIDEvent)
{
// TODO: 在此添加消息處理程序代碼和/或調(diào)用默認值
switch ( nIDEvent )
{
case GRID_TIMER :
{
} break ;
}
Invalidate ( false ) ;
CButton::OnTimer(nIDEvent);
}
// BAR 顏色
void CMulticolorPlotBtn::SetBarColor ( COLORREF clrUp , COLORREF clrDown , bool bfRfastness ,
bool bfGfastness , bool bfBfastness )
{
}
// 設(shè)置數(shù)據(jù)
void CMulticolorPlotBtn::SetData ( float fData )
{
// 用關(guān)鍵代碼同步
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 ;
}
}
// 離開關(guān)鍵代碼
LeaveCriticalSection ( & g_cs ) ;
}
// 鎖定數(shù)據(jù)顯示范圍
void CMulticolorPlotBtn::LockRang ( bool bfLock )
{
bLock = bfLock ;
}
void CMulticolorPlotBtn::LockRang ( float fMin , float fMax )
{
fLow = fMin ;
fHigh = fMax ;
LockRang ( true ) ;
}
//////////////////////////////////// end ////////////////////////////////////
///////////////////////////// MemDC.h ///////////////////////////////////////////////////
#if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
//////////////////////////////////////////////////
// CMemDC 實現(xiàn)一個內(nèi)存DC
class CMemDC : public CDC
{
private:
CBitmap m_bitmap; // 實際的bitmap
CBitmap* m_pOldBitmap; // 原先在CMemDC中的位圖
CDC* m_pDC; // 保存從構(gòu)造函數(shù)中傳來的CDC
CRect m_rect; // 畫的矩形區(qū)域
BOOL m_bMemDC; // 如果CDC是一個內(nèi)存DC,則為TRUE
public:
CMemDC(CDC* pDC) : CDC()
{
ASSERT(pDC != NULL);
m_pDC = pDC;
m_pOldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();//判斷是否是一個內(nèi)存DC
if (m_bMemDC) // 創(chuàng)建一個內(nèi)存DC
{
pDC->GetClipBox(&m_rect);
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_pOldBitmap = SelectObject(&m_bitmap);
SetWindowOrg(m_rect.left, m_rect.top);
}
else // 這不是一個內(nèi)存DC,我們只拷貝相關(guān)的DC部分以備打印
{
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
~CMemDC()
{
if (m_bMemDC)
{
// 拷貝實際的位圖到屏幕上
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
this, m_rect.left, m_rect.top, SRCCOPY);
//裝入原始的位圖
SelectObject(m_pOldBitmap);
}
else
{
m_hDC = m_hAttribDC = NULL;
}
}
// 允許作為指針
CMemDC* operator->() {return this;}
operator CMemDC*() {return this;}
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the divvious line.
#endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
//////////////////////////////////// end ////////////////////////////////////
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -