以曲线或柱状图实时显示数据的控件

来源:互联网 发布:明星为什么戴口罩 知乎 编辑:程序博客网 时间:2024/05/22 13:07

本代码已经更新,请到 http://hi.baidu.com/wlzqi 中去查看。

该控件从按钮类派生而来,使用非常方便。
    使用时只需加入 MulticolorPlotBtn.cppMulticolorPlotBtn.h并替换你的按钮类即可。
    功能:1.曲线实时显示数据,并可随时改变曲线颜色。
          2.用渐变色的柱状图实时显示数据。
          3.完全自定义背景色、背景网格色,粗细以及网格滚动方向。(上下左右)
          4.自定义曲线(柱状图)的滚动方向。
          5.数据显示范围:可自定义、自动寻找最合适的范围、随时锁定(不锁定)数据显示范围。
          6.支持浮点数、负数。


需要的朋友请点击这里下载源代码以及实例工程 (能看见左侧图标表示链接有效)

或点击这里下载
/////////////// MulticolorPlotBtn.h ////////////////////////
/*
模块名称:MulticolorPlotBtn.h
版    本:0.1 Alpha
版    权:Copyright (C) 2005 wlzqin
模块功能:动态图表显示数据
作    者:wlzqi
作者邮箱:
建立时间:22005年6月14日  乙酉 鸡年五月初八
最后修改:by wlzqi
修改历程:
注意事项:
备  注:支持 UNICODE 和 ANSI 编码
           :测试平台 Windows 2000、IE6、Direcx9、 AMD Xp 2000 + CPU
           :不兼容 Windows 98
功能简介:动态实时显示数据,显示方式有BAR和LINE(其它方式以后添加)
             ,可动态实时改变曲线属性。支持任意范围数据,可设定范围,
             也可不设定显示范围(自动寻找最符合的范围),还可任意锁定
             (自由)范围。支持浮点数。
*/

#pragma once
#include "afxwin.h"
#include <math.h>

#define BAR                        0
#define      LINE                  1

class CMulticolorPlotBtn :
     public CButton
{
public:
     CMulticolorPlotBtn(void) ;
     virtual ~CMulticolorPlotBtn(void);

private:                        // 公共属性
     int nPlotType ;            // 曲线类型  BAR 或 LINE                        // BAR
     bool bfInit ;            // 是否初始化                                          // false
     // 网格X方向上的间距
     int nGridResolutionX ;                                                            // 10
     // 网格Y方向上的间距
     int nGridResolutionY ;                                                            // 10
     // 网格滚动的速度和方向(正值为从左向右滚动和从上到下,否则反之。0不动)
     int nGridScrollSpeedX ;                                                            // -1
     int nGridScrollSpeedY ;                                                            // 0
     // 数据点分辨率大小(即:一个数据点占据的像素数)
     int nPlotGranulatrity ;                                                            // 2
     // 网格线宽度
     int nGridLineWidth ;                                                            // 1
     // 背景色
     COLORREF m_clrDarkBack ;                                                      // RGB(0,0,75)
     // 前景色
     COLORREF m_clrDarkLine ;                                                      // RGB(32,64,32)
     // 控件矩形
     RECT m_rect ;
     // 控件的尺寸
     CSize m_Size ;
     // 控件可容纳可见的数据点数
     int nPlotData ;                                                                        // 0
     // 实际数据
     float * pfData ;                                                                  // 0
     // 数据范围
     float fLow , fHigh ;                                                            // 0,0
     // 数据比例
     float fScaleY ;                                                                        // 1.0
     // 数据点处的颜色
     COLORREF m_clrCyanData ;                                                      // RGB ( 0,255,255 )
     // 画笔
     CPen m_GridPen ;
     // 数据点位图画刷
     CBrush m_clrBrush ;
     // 网格开始位置
     int nGridStarPosX , nGridStarPosY ;                                          // 0,0
     // 锁定显示范围
     bool bLock ;                                                                        // true---锁定
     // 控件上显示的字体
     CFont m_SmallFont ;
     // Y轴刻度的颜色
     COLORREF m_clrAxisScaleY ;                                                      // RGB ( 0,255,255 )
     // 是否显示Y轴刻度数字
     int nShowFormatDataText ;                                                      // 0---不显示
     // 控件标题
     TCHAR szTitls [MAX_PATH * sizeof ( TCHAR ) + 1] ;                  // NULL
     // 曲线单位
     TCHAR szUints [32 * sizeof ( TCHAR ) + 1] ;                              // NULL
private:
     // 关键代码
     CRITICAL_SECTION            g_cs ;
public:                        // 公共方法
     // 设置画线的类型
     void SetPlotType ( int nType )
     {
           nPlotType = nType ;

           bfInit = false ;
     }
     // 设置网格间距
     void SetGridResolutionX ( int nGridReluX ) { nGridResolutionX = nGridReluX ; }
     void SetGridResolutionY ( int nGridReluY ) { nGridResolutionY = nGridReluY ; }
     // 设置网格滚动速度
     // 正值为从左向右滚动,0不动
     void SetGridScrollSpeedX ( int nSpeedX ) { nGridScrollSpeedX = nSpeedX ; }
     // 正值为从上到下滚动,0不动
     void SetGridScrollSpeedY ( int nSpeedY ) { nGridScrollSpeedY = nSpeedY ; }
     // 数据点面积大小(即:一个数据点占据的像素数)
     bool 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 true ;
     }
     // 网格线宽度
     void SetGridLineWidth ( int nWidth ) { nGridLineWidth = nWidth ; }
     // 背景色
     void SetGridBackClr ( COLORREF clr ) { m_clrDarkBack = clr ; }
     // 前景色
     void SetGridLineClr ( COLORREF clr )
     {
           m_clrDarkLine      = clr            ;
           m_GridPen.CreatePen      ( PS_SOLID , nGridLineWidth , m_clrDarkLine      ) ;

           m_clrDarkLine = clr ;
     }
     // 数据范围
     void SetRang ( float fL , float fH )
     {
           fLow      = fL ;
           fHigh      = fH ;
     }
     // 创建画笔
     void SetLinePen ( int nWidth , COLORREF clr )
     {
           nGridLineWidth      = nWidth      ;
           m_clrDarkLine      = clr            ;
           m_GridPen.CreatePen      ( PS_SOLID , nGridLineWidth , m_clrDarkLine      ) ;
     }
     // 锁定数据显示范围
     void LockRang ( bool bfLock = true ) ;
     void LockRang ( float fMin = 0.0 , float fMax = 100.0 ) ;
     // Y轴刻度颜色,bfShow==0显示刻度数字,1仅在左上角显示1000(k/sec)/2000样子的数字,2显示最大最小,3显示全部
     void SetAxisScaleClrY ( COLORREF clr = RGB ( 0 , 255 , 255 ) )
     {

           m_clrAxisScaleY = clr ;
     }
     // 标题
     void SetTitle ( PCTSTR pctTitle = NULL )
     {
           _stprintf ( szTitls , _TEXT ( "%s" ) , pctTitle ) ;
     }
     // 数据单位例:SetUnit( _TEXT ( "(k/sec)" ) ) ;
     void SetUnit ( PCTSTR pctUint = NULL )
     {
           _stprintf ( szUints , _TEXT ( "%s" ) , pctUint ) ;
     }
     // 是否显示数据标题、颜色、单位
     /*
     nShow = 0 ; 不显示任何文本
     nShow = 1 ; 仅仅显示标题
     nShow = 2 ; 仅仅显示标题和流量总计
     nShow = 3 ; 显示标题和最小值
     nShow = 4 ; 显示标题、最小值和中值
     */
     void ShowTitle ( int nShow = 1 )
     {
           nShowFormatDataText = nShow ;
     }
private:                        // BAR属性
     // BAR颜色
     COLORREF m_clrUp ;
     COLORREF m_clrDown ;
public:                              // BAR方法
     // BAR 颜色
     // clrUp            -------- 顶部颜色
     // clrDown            -------- 底部颜色
     // bfRfastness  -------- 红色分量是否固定不变  false ---- 渐变
     // bfGfastness  -------- 红色分量是否固定不变  false ---- 渐变
     // bfBfastness  -------- 红色分量是否固定不变  false ---- 渐变
     void SetBarColor ( COLORREF clrUp , COLORREF clrDown , bool bfRfastness = false , bool bfGfastness = false , bool bfBfastness = false ) ;
     // 设置数据
     void SetData ( float fData ) ;
private:                        // LINE属性
     // 曲线颜色
     COLORREF m_clrLinePen ;                              // RGB(0,255,0)
     // 曲线宽度
     int nLineWidth ;
public:                              // LINE方法
     // 曲线颜色
     void SetLineColorWidth ( COLORREF clrLine = RGB ( 0 , 255 , 0 ) , int nWidth = 1 )
     {
           nLineWidth            = nWidth ;
           m_clrLinePen      = clrLine ;
     }
     void SetLineColor ( COLORREF clrLine = RGB ( 0 , 255 , 0 ) ) { m_clrLinePen      = clrLine ; }
     void SetLineWidth ( int nWidth = 1 ) { nLineWidth = nWidth ; }
     const COLORREF GetLineColor () { return m_clrLinePen ; }
     const int GetLineWidth () { return nLineWidth ; }
public:
     DECLARE_MESSAGE_MAP()
     afx_msg void OnTimer(UINT nIDEvent);
protected:
     virtual void PreSubclassWindow();
public:
     virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
};

/////////////// MulticolorPlotBtn.h end ////////////////////////

/////////////// MulticolorPlotBtn.cpp //////////////////////////
#include "StdAfx.h"
#include "./multicolorplotbtn.h"

#include "MemDC.h"


#define GRID_TIMER                              1
//网格刷新速率
#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)
{
     // 关键代码
     // 初始化关键代码的 C_S 结构
     InitializeCriticalSection ( & g_cs ) ;

     // 初始化标题
     _stprintf ( szTitls , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
     // 初始化单位
     _stprintf ( szUints , _TEXT ( "%s" ) , _TEXT ( "" ) ) ;
}

CMulticolorPlotBtn::~CMulticolorPlotBtn(void)
{
     if ( pfData )
     {
           delete [] pfData ;
     }

     // 释放关键代码
     DeleteCriticalSection ( & g_cs ) ;
}

BEGIN_MESSAGE_MAP(CMulticolorPlotBtn, CButton)
     ON_WM_TIMER()
END_MESSAGE_MAP()

void CMulticolorPlotBtn::PreSubclassWindow()
{
     // TODO: 在此添加专用代码和/或调用基类

     // 避免把该按钮当成下压式按钮
     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      ;

     // 计算控件可容纳可见的数据点数
     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      ) ;

           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 ) ;

     // 创建内存 DC
     CMemDC * pMemDC = new CMemDC ( pDC ) ;

     // 得到控件大小
     RECT clipRect ;
     pMemDC->GetClipBox ( & clipRect ) ;

     if ( bfInit == false )
     {
           // 如果没有初始化,则初始化画刷
           CBitmap m_Bmp ;

           // 如果控件大小有效
           if ( clipRect.right - clipRect.left > 1 )
           {
                 // 根据数据点分辨率创建内存位图
                 m_Bmp.CreateCompatibleBitmap( pMemDC ,nPlotGranulatrity , m_Size.cy ) ;

                 CBitmap * pOldBmp = pMemDC->SelectObject( & m_Bmp ) ;

                 CSize m_BmpSize = m_Bmp.GetBitmapDimension () ;            

                 // 根据不同的曲线分别绘制
                 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 () ;

           // 画网格
           int nGridLinesX = m_Size.cx / nGridResolutionX ;
           int nGridLinesY = m_Size.cy / nGridResolutionY ;

           // 选择画笔
           CPen * pOldPen = pMemDC->SelectObject ( & m_GridPen ) ;

           // 创建垂直线
           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 ) ;
           }
           // 控制网格正确移动
           nGridStarPosX += nGridScrollSpeedX ;
           nGridStarPosY += nGridScrollSpeedY ;

           if ( nGridStarPosX < 0                              ) nGridStarPosX = nGridResolutionX ;
           if ( nGridStarPosX > nGridResolutionX      ) nGridStarPosX = 0 ;
           if ( nGridStarPosY < 0                              ) nGridStarPosY = nGridResolutionY ;
           if ( nGridStarPosY > nGridResolutionY      ) nGridStarPosY = 0 ;

           // 还原网格画笔
           pMemDC->SelectObject ( pOldPen ) ;

           // 用关键代码同步和SetData
           EnterCriticalSection ( & g_cs ) ;

           // 画数据
           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      ) ;
                       // 画数据点处的颜色
                       pMemDC->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 = 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 ) ;

           // 如果要求现实Y轴刻度数字
           switch ( nShowFormatDataText )
           {
           case 0 :                        // 不显示
                 {
                 } break ;
           case 1 :                        // 仅显示标题
                 {
                       _stprintf ( szAxisScaleYMax , _TEXT ( "%s" ) , szTitls ) ;

                       pMemDC->TextOut ( 0 ,                         0      , szAxisScaleYMax      ) ;
                 } break ;
           case 2 :                        // 显示标题和流量比例
                 {
                       _stprintf ( szAxisScaleYMax , _TEXT ( "%s %8.1f %s / %8.1f" ) , szTitls , pfData [ nPlotData - 1 ] , szUints , fHigh ) ;

                       pMemDC->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 ) ;

                       pMemDC->TextOut ( 0 ,                         0      , szAxisScaleYMax      ) ;
                       pMemDC->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轴刻度
                       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      ) ;

           // 离开关键代码
           LeaveCriticalSection ( & g_cs ) ;

           pMemDC->SetBrushOrg ( orgBrushOrigin.x , orgBrushOrigin.y ) ;
     }

     delete pMemDC ;

     ReleaseDC ( pDC ) ;
}


void CMulticolorPlotBtn::OnTimer(UINT nIDEvent)
{
     // TODO: 在此添加消息处理程序代码和/或调用默认值
     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 )
{
}

// 设置数据
void CMulticolorPlotBtn::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 CMulticolorPlotBtn::LockRang ( bool bfLock )
{
     bLock = bfLock ;
}

void CMulticolorPlotBtn::LockRang ( float fMin , float fMax )
{
     fLow      = fMin ;
     fHigh      = fMax ;

     LockRang ( true ) ;
}
/////////////// MulticolorPlotBtn.cpp end //////////////////////////

原创粉丝点击