zoukankan      html  css  js  c++  java
  • C++制作电压表电流表仪表盘(vs2008)

    Meter类

    Meter.h

      1 #if !defined(AFX_METER_H__D5802279_6502_4453_BE21_58604877AD39__INCLUDED_)
      2 #define AFX_METER_H__D5802279_6502_4453_BE21_58604877AD39__INCLUDED_
      3 
      4 #if _MSC_VER > 1000
      5 #pragma once
      6 #endif // _MSC_VER > 1000
      7 // Meter.h : header file
      8 //
      9 
     10 #ifndef ROUND
     11 #define ROUND(x) (int)((x) + 0.5 - (double)((x) < 0))
     12 #endif
     13 
     14 #define BOUNDARY_POINTS 200
     15 #define TABNUM 6
     16 /////////////////////////////////////////////////////////////////////////////
     17 // CMeter window
     18 
     19 class CMeter : public CStatic
     20 {
     21 // Construction
     22 public:
     23     CMeter();
     24 
     25 // Attributes
     26 public:
     27 
     28 // Operations
     29 public:
     30 
     31 // Overrides
     32     // ClassWizard generated virtual function overrides
     33     //{{AFX_VIRTUAL(CMeter)
     34     protected:
     35     //}}AFX_VIRTUAL
     36 
     37 // Implementation
     38 public:
     39     void SetAngleRange(int nStartAngleDeg, int nEndAngleDeg);
     40     int m_nTabNum;
     41     void SetSubTicks(int nSubTicks);
     42     void SetTicks(int nTicks);
     43     void DrawValue(CDC *pDC);
     44     void SetColorTick(BOOL bColorTick = FALSE);
     45     BOOL m_bColorTick;
     46     void DrawNode(CDC *pDC);
     47     COLORREF m_colorTable[6];
     48     void SetValueDecimals(int nDecimals);
     49     void SetUnits(CString &strUnits);
     50     CString m_strUnits;
     51     int m_nValueDecimals;
     52     void SetScaleDecimals(int nDecimals);
     53     void SetRange(double dMin, double dMax);
     54     void SetNeedleColor (COLORREF colorNeedle);
     55     void UpdateNeedle(double dValue);
     56     COLORREF m_colorNeedle;
     57     int m_nScaleDecimals;
     58     
     59     double m_dCurrentValue;
     60     double m_dMaxValue;
     61     double m_dMinValue;
     62 
     63     void DrawNeedle(CDC *pDC);
     64     void ReconstructControl();
     65     void DrawMeterBackground(CDC *pDC, CRect &rect);
     66     int m_nStartAngleDeg;    // 仪表盘圆弧起始角度
     67     int m_nEndAngleDeg;        // 仪表盘圆弧终止角度
     68     int m_nTicks;            // 刻度数
     69     int m_nSubTicks;        // 分刻度数
     70     virtual ~CMeter();
     71 
     72     // Generated message map functions
     73 protected:
     74     double m_dLeftAngleRad;
     75     double m_dRightAngleRad;
     76     int m_nCenterRadius;
     77     
     78     CRect m_rectCtrl;            // 控件区域
     79     CRect m_rectValue;            // 显示数值区域
     80     CRgn m_rgnBoundary;
     81 
     82     CBitmap *m_pBitmapOldBackground ;
     83     CBitmap m_bitmapBackground ;
     84     CDC m_dcBackground;
     85 
     86     CPoint m_ptMeterCenter;        // 仪表中心
     87     CPoint m_pointBoundary[BOUNDARY_POINTS]; // 边界点,用于绘制刻度
     88 
     89     CFont m_font;            // 显示文字字体
     90 
     91     COLORREF m_colorWindow;        // 背景色
     92     COLORREF m_colorHighlight;    
     93     COLORREF m_colorShadow;
     94     COLORREF m_colorButton;
     95     COLORREF m_colorText;        // 显示文本颜色
     96 
     97     int m_nRadiusFrame;            // 仪表盘边框半径
     98     //{{AFX_MSG(CMeter)
     99     afx_msg void OnPaint();
    100     afx_msg void OnSize(UINT nType, int cx, int cy);
    101     //}}AFX_MSG
    102 
    103     DECLARE_MESSAGE_MAP()
    104 };
    105 
    106 /////////////////////////////////////////////////////////////////////////////
    107 
    108 //{{AFX_INSERT_LOCATION}}
    109 // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    110 
    111 #endif // !defined(AFX_METER_H__D5802279_6502_4453_BE21_58604877AD39__INCLUDED_)

    Meter.cpp

      1 // Meter.cpp : implementation file
      2 //
      3 
      4 #include "stdafx.h" 
      5 #include "Meter.h"
      6 #include "math.h"
      7 #include "MemDCEx.h"
      8 
      9 
     10 #ifdef _DEBUG
     11 #define new DEBUG_NEW
     12 #undef THIS_FILE
     13 static char THIS_FILE[] = __FILE__;
     14 #endif
     15 
     16 #define PT_NUM 50
     17 /////////////////////////////////////////////////////////////////////////////
     18 // CMeter
     19 
     20 CMeter::CMeter()
     21 {
     22     m_nStartAngleDeg = 225;
     23     m_nEndAngleDeg = 315;
     24     m_nTicks = 10;
     25     m_nSubTicks = 5;
     26     m_dMaxValue = 100.0;
     27     m_dMinValue = 0.0;
     28     m_dCurrentValue = 00.0;
     29     m_nScaleDecimals = 0;
     30     m_nValueDecimals = 1;
     31     m_colorNeedle = RGB(255, 0, 0);
     32     m_strUnits = _T("(KV)");
     33     m_bColorTick = FALSE;
     34     
     35     // 颜色表格
     36     m_colorTable[0] = RGB(177,255,99);
     37     m_colorTable[1] = RGB(0, 255,0);
     38     m_colorTable[2] = RGB(0,123,0);
     39     m_colorTable[3] = RGB(230,248, 38);
     40     m_colorTable[4] = RGB(253, 138, 29);
     41     m_colorTable[5] = RGB(255, 0, 0);
     42 }
     43 
     44 CMeter::~CMeter()
     45 {
     46 }
     47 
     48 
     49 BEGIN_MESSAGE_MAP(CMeter, CStatic)
     50     //{{AFX_MSG_MAP(CMeter)
     51     ON_WM_PAINT()
     52     ON_WM_SIZE()
     53     //}}AFX_MSG_MAP
     54 END_MESSAGE_MAP()
     55 
     56 /////////////////////////////////////////////////////////////////////////////
     57 // CMeter message handlers
     58 
     59 void CMeter::OnPaint() 
     60 {
     61     CPaintDC dc(this); // device context for painting
     62 
     63     // 获得控件区域
     64     GetClientRect (&m_rectCtrl);
     65 
     66     CMemDCEx memDC(&dc, &m_rectCtrl);
     67 
     68     // 选取圆盘边框半径
     69     m_nRadiusFrame = max(m_rectCtrl.Height(), m_rectCtrl.Width())*9/21;
     70 
     71     // 获得仪表盘中心点
     72     m_ptMeterCenter = m_rectCtrl.CenterPoint();
     73     m_ptMeterCenter.y += m_nRadiusFrame/10;
     74     
     75     //绘制仪表盘
     76     if(m_dcBackground.GetSafeHdc()== NULL|| (m_bitmapBackground.m_hObject == NULL))
     77     {
     78         m_dcBackground.CreateCompatibleDC(&dc);
     79         m_bitmapBackground.CreateCompatibleBitmap(&dc, m_rectCtrl.Width(),                                                                                     m_rectCtrl.Height()) ;
     80         m_pBitmapOldBackground = m_dcBackground.SelectObject(&m_bitmapBackground) ;
     81         DrawMeterBackground(&m_dcBackground, m_rectCtrl);
     82 
     83     }
     84     memDC.BitBlt(0, 0, m_rectCtrl.Width(), m_rectCtrl.Height(), 
     85                        &m_dcBackground, 0, 0, SRCCOPY) ;
     86 
     87     // 绘制指针
     88     DrawNeedle(&memDC);
     89 
     90     DrawNode(&memDC);
     91 
     92     DrawValue(&memDC);
     93     // Do not call CStatic::OnPaint() for painting messages
     94 }
     95 
     96 void CMeter::DrawMeterBackground(CDC *pDC, CRect &rect)
     97 {
     98     int nInnerRadius = m_nRadiusFrame*8/10;    // 内圆弧半径
     99 
    100     m_nCenterRadius = m_nRadiusFrame/20;    // 中心园半径大小
    101 
    102     int nFrame = m_nRadiusFrame/18;            // 边框厚度
    103 
    104     double dstepTickDeg = (360.0+m_nStartAngleDeg-m_nEndAngleDeg)/(m_nTicks*m_nSubTicks);    // 刻度步进角度
    105 
    106     int nSubTickR = nInnerRadius+(m_nRadiusFrame-2*nFrame-nInnerRadius)/2;
    107 
    108     double dDeg = (m_nStartAngleDeg+360.0-m_nEndAngleDeg)/(TABNUM*PT_NUM);
    109      
    110 
    111     CRect rectPanel,rectInnerPanel;
    112     CPen penDraw, *pPenOld;
    113     CFont *pFontOld;
    114     CBrush brushFill, *pBrushOld;
    115     POINT ptStart, ptEnd, ptInnerStart, ptInnerEnd;    
    116     CPoint pointInner[BOUNDARY_POINTS], ptGroup1[PT_NUM*TABNUM+1], ptGroup2[PT_NUM*TABNUM+1];
    117     CPoint ptRgn[PT_NUM*2+2];
    118     CPoint pttemp;
    119     CString strtemp;
    120     double dRadPerDeg;
    121     double dTickAngleRad;
    122     double dTemp;
    123     int nRef = 0;
    124     int nTickAngle;    
    125     int nHeight;    // 字体大小
    126     double dtempangle;
    127     
    128     // 计算起始角终止角弧度
    129     dRadPerDeg = 4.0*atan(1.0)/180.0;
    130     m_dLeftAngleRad = (m_nStartAngleDeg-180.0)*dRadPerDeg;
    131     m_dRightAngleRad = (m_nEndAngleDeg-360.0)*dRadPerDeg;
    132     
    133     // 计算圆弧起始终止点及区域
    134     ptStart.x = m_ptMeterCenter.x-(int)(m_nRadiusFrame*cos(m_dLeftAngleRad));
    135     ptStart.y = m_ptMeterCenter.y+(int)(m_nRadiusFrame*sin(m_dLeftAngleRad));
    136     ptEnd.x = m_ptMeterCenter.x+(int)(m_nRadiusFrame*cos(-m_dRightAngleRad));
    137     ptEnd.y = m_ptMeterCenter.y+(int)(m_nRadiusFrame*sin(-m_dRightAngleRad));
    138     
    139     rectPanel.SetRect(m_ptMeterCenter.x-m_nRadiusFrame, m_ptMeterCenter.y-m_nRadiusFrame,
    140                         m_ptMeterCenter.x+m_nRadiusFrame, m_ptMeterCenter.y+m_nRadiusFrame);
    141     // 获取点的位置
    142     for(int i=0; i<=PT_NUM*TABNUM; i++)
    143     {
    144         ptGroup1[i].x = m_ptMeterCenter.x + (int)((m_nRadiusFrame-nFrame)*cos((m_nStartAngleDeg-i*dDeg)*dRadPerDeg));
    145         ptGroup1[i].y = m_ptMeterCenter.y - (int)((m_nRadiusFrame-nFrame)*sin((m_nStartAngleDeg-i*dDeg)*dRadPerDeg));
    146         ptGroup2[i].x = m_ptMeterCenter.x + (int)(m_nRadiusFrame*8*cos((m_nStartAngleDeg-i*dDeg)*dRadPerDeg)/10);
    147         ptGroup2[i].y = m_ptMeterCenter.y - (int)(m_nRadiusFrame*8*sin((m_nStartAngleDeg-i*dDeg)*dRadPerDeg)/10);
    148     }
    149 
    150     // 获取系统颜色;
    151     m_colorWindow    = GetSysColor(COLOR_WINDOW);
    152     m_colorButton    = GetSysColor(COLOR_BTNFACE);
    153     m_colorShadow    = GetSysColor(COLOR_BTNSHADOW);
    154     m_colorHighlight = GetSysColor(COLOR_BTNHIGHLIGHT);
    155     m_colorText        = GetSysColor(COLOR_BTNTEXT);
    156     // 临时使用的颜色
    157     COLORREF colorCaption, cEdge, cMiddle;
    158     cMiddle = RGB(255, 255, 255);
    159     cEdge = RGB(96, 96, 255);
    160 
    161     // 用按钮色绘制背景
    162     brushFill.DeleteObject();
    163     brushFill.CreateSolidBrush(m_colorButton);
    164     pBrushOld = pDC->SelectObject(&brushFill);
    165     pDC->Rectangle(rect);
    166     pDC->SelectObject(pBrushOld);
    167 
    168     // 绘制圆盘边框
    169 
    170     for(int iOnBand=nFrame; iOnBand>0; iOnBand--)
    171     {
    172         penDraw.DeleteObject();
    173         colorCaption = RGB((GetRValue(cEdge)-GetRValue(cMiddle))*((float)iOnBand)/nFrame+GetRValue(cMiddle),
    174             (GetGValue(cEdge)-GetGValue(cMiddle))*((float)iOnBand)/nFrame+GetGValue(cMiddle),
    175             (GetBValue(cEdge)-GetBValue(cMiddle))*((float)iOnBand)/nFrame+GetBValue(cMiddle));
    176         penDraw.CreatePen(PS_SOLID, iOnBand*2, colorCaption);
    177         pPenOld = pDC->SelectObject(&penDraw);
    178         pDC->Arc(&rectPanel, ptEnd, ptStart);
    179         pDC->SelectObject(pPenOld);    
    180     }
    181     // 绘制内圈
    182     ptInnerStart.x = m_ptMeterCenter.x-(int)(nInnerRadius*cos(m_dLeftAngleRad));
    183     ptInnerStart.y = m_ptMeterCenter.y+(int)(nInnerRadius*sin(m_dLeftAngleRad));
    184     ptInnerEnd.x = m_ptMeterCenter.x+(int)(nInnerRadius*cos(-m_dRightAngleRad));
    185     ptInnerEnd.y = m_ptMeterCenter.y+(int)(nInnerRadius*sin(-m_dRightAngleRad));
    186     
    187     rectInnerPanel.SetRect(m_ptMeterCenter.x-nInnerRadius, m_ptMeterCenter.y-nInnerRadius,
    188                         m_ptMeterCenter.x+nInnerRadius ,m_ptMeterCenter.y+nInnerRadius);
    189 
    190     penDraw.DeleteObject();
    191     penDraw.CreatePen(PS_SOLID, 1, RGB(255,255,0));
    192     pPenOld = pDC->SelectObject(&penDraw);
    193     pDC->Arc(&rectInnerPanel, ptInnerEnd, ptInnerStart);
    194     pDC->SelectObject(pPenOld);    
    195     
    196     if(m_bColorTick)
    197     {
    198         
    199         // 绘制色彩刻度
    200         for(int i=0; i<TABNUM; i++)
    201         {
    202             //确定区域
    203             for(int j=0; j<=PT_NUM; j++)
    204             {
    205                 ptRgn[j] = ptGroup1[i*PT_NUM+j];
    206                 ptRgn[2*PT_NUM+1-j] = ptGroup2[i*PT_NUM+j];
    207             }
    208             brushFill.DeleteObject();
    209             brushFill.CreateSolidBrush(m_colorTable[i]);
    210             pBrushOld = pDC->SelectObject(&brushFill);
    211             penDraw.DeleteObject();
    212             penDraw.CreatePen(PS_SOLID, 1, m_colorTable[i]);
    213             pPenOld = pDC->SelectObject(&penDraw);
    214             pDC->Polygon(ptRgn, 2*PT_NUM+2);
    215             pDC->SelectObject(pBrushOld);
    216             pDC->SelectObject(pPenOld);
    217         }
    218         
    219     }
    220 
    221     // 计算刻度点,避免不能整除引起较大误差*100
    222     for(nTickAngle=m_nStartAngleDeg*100; nTickAngle>=(m_nEndAngleDeg-360)*100; nTickAngle-=(int)(dstepTickDeg*100))
    223     {
    224         // 转换成弧度
    225         dTickAngleRad = (double)nTickAngle/100*dRadPerDeg;    
    226         // 确定外圈坐标
    227         // 确定x坐标
    228         dTemp = m_ptMeterCenter.x + (m_nRadiusFrame-2*nFrame)*cos(dTickAngleRad);
    229         m_pointBoundary[nRef].x = ROUND(dTemp);
    230         // 确定y坐标
    231         dTemp = m_ptMeterCenter.y - (m_nRadiusFrame-2*nFrame)*sin(dTickAngleRad);
    232         m_pointBoundary[nRef].y = ROUND(dTemp);
    233         
    234         // 确定刻度点(主刻度和子刻度)
    235         //主刻度及文本标注点
    236         if(nRef%m_nSubTicks == 0)
    237         {
    238             dTemp = m_ptMeterCenter.x + nInnerRadius*cos(dTickAngleRad);
    239             pointInner[nRef].x = ROUND(dTemp);
    240             dTemp = m_ptMeterCenter.y - nInnerRadius*sin(dTickAngleRad);
    241             pointInner[nRef].y = ROUND(dTemp);
    242         }
    243         // 子刻度
    244         else
    245         {
    246             dTemp = m_ptMeterCenter.x + nSubTickR*cos(dTickAngleRad);
    247             pointInner[nRef].x = ROUND(dTemp);
    248             dTemp = m_ptMeterCenter.y - nSubTickR*sin(dTickAngleRad);
    249             pointInner[nRef].y = ROUND(dTemp);
    250         }
    251         nRef++ ;
    252     }
    253     // 多边形区域
    254     m_rgnBoundary.DeleteObject() ;
    255     m_rgnBoundary.CreatePolygonRgn(m_pointBoundary, nRef, ALTERNATE);
    256     
    257     m_rectValue.top = m_ptMeterCenter.y + m_nRadiusFrame/5;
    258     m_rectValue.bottom = m_ptMeterCenter.y + m_nRadiusFrame/2;
    259     m_rectValue.left = m_ptMeterCenter.x - m_nRadiusFrame/2;
    260     m_rectValue.right = m_ptMeterCenter.x + m_nRadiusFrame/2;
    261 
    262     // 绘制刻度
    263     penDraw.DeleteObject();
    264     penDraw.CreatePen(PS_SOLID, 1, RGB(0,0,0));
    265     pPenOld = pDC->SelectObject(&penDraw);
    266     for(int i=0; i<nRef; i++)
    267     {
    268         pDC->MoveTo(m_pointBoundary[i]);
    269         pDC->LineTo(pointInner[i]);
    270     }
    271     pDC->SelectObject(pPenOld);    
    272 
    273     // 刻度标号
    274 
    275     nHeight = m_nRadiusFrame/8;  //字体大小
    276     m_font.CreateFont(nHeight, 0, 0, 0, 550, 
    277                             FALSE, FALSE, 0, ANSI_CHARSET,
    278                             OUT_DEFAULT_PRECIS, 
    279                             CLIP_DEFAULT_PRECIS,
    280                             DEFAULT_QUALITY, 
    281                             DEFAULT_PITCH|FF_SWISS, "Arial");
    282 
    283     pFontOld = pDC->SelectObject(&m_font);
    284     pDC->SetBkMode(TRANSPARENT);
    285     for(int i=0; i<=m_nTicks; i++)
    286     {    
    287         dtempangle = m_nStartAngleDeg-i*m_nSubTicks*dstepTickDeg;
    288         strtemp.Format("%.*lf", m_nScaleDecimals, (m_dMinValue+(m_dMaxValue-m_dMinValue)*i/m_nTicks));
    289 
    290         if(dtempangle>190)
    291         {
    292             pDC->SetTextAlign(TA_BOTTOM|TA_LEFT);
    293             pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/2, strtemp);
    294         }
    295         
    296         else if(dtempangle>170)
    297         {
    298             pDC->SetTextAlign(TA_BASELINE|TA_LEFT);
    299             pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/3, strtemp);
    300         }
    301         else if(dtempangle>135)
    302         {
    303             pDC->SetTextAlign(TA_BASELINE|TA_LEFT);
    304             pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/2, strtemp);
    305         }
    306         else if(dtempangle>100)
    307         {
    308             pDC->SetTextAlign(TA_TOP|TA_LEFT);
    309             pDC->TextOut(pointInner[m_nSubTicks*i].x-nHeight/4, pointInner[m_nSubTicks*i].y-nHeight/8, strtemp);
    310         }
    311 
    312         else if(dtempangle>80)
    313         {
    314             pDC->SetTextAlign(TA_TOP|TA_CENTER);
    315             pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y, strtemp);
    316         }
    317         else if(dtempangle>45)
    318         {
    319             pDC->SetTextAlign(TA_BOTTOM|TA_RIGHT);
    320             pDC->TextOut(pointInner[m_nSubTicks*i].x+nHeight/3, pointInner[m_nSubTicks*i].y+nHeight, strtemp);
    321         }
    322         else if(dtempangle>10)
    323         {
    324             pDC->SetTextAlign(TA_RIGHT|TA_BASELINE);
    325             pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/2, strtemp);
    326         }
    327         else if(dtempangle>-10)
    328         {
    329             pDC->SetTextAlign(TA_RIGHT|TA_BASELINE);
    330             pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/3, strtemp);
    331         }
    332         else 
    333         {
    334             pDC->SetTextAlign(TA_RIGHT|TA_BOTTOM);
    335             pDC->TextOut(pointInner[m_nSubTicks*i].x, pointInner[m_nSubTicks*i].y+nHeight/2, strtemp);
    336         }
    337     }
    338     pDC->SelectObject(pFontOld);
    339 
    340 }
    341 
    342 void CMeter::ReconstructControl()
    343 {
    344     if ((m_pBitmapOldBackground) && 
    345           (m_bitmapBackground.GetSafeHandle()) && 
    346             (m_dcBackground.GetSafeHdc()))
    347     {
    348             m_dcBackground.SelectObject(m_pBitmapOldBackground);
    349             m_dcBackground.DeleteDC() ;
    350             m_bitmapBackground.DeleteObject();
    351     }
    352 
    353     Invalidate ();
    354 }
    355 
    356 void CMeter::OnSize(UINT nType, int cx, int cy) 
    357 {
    358     CStatic::OnSize(nType, cx, cy);
    359     
    360     // TODO: Add your message handler code here
    361     ReconstructControl() ;
    362 }
    363 
    364 void CMeter::DrawNeedle(CDC *pDC)
    365 {
    366     int nResult;
    367     double dRadPerDeg = 4.0*atan(1.0)/180.0;
    368     double dAngleDeg;
    369     double dAngleRad ;
    370     double dTemp ;
    371     CBrush brushFill, *pBrushOld ;
    372     CPen penDraw, *pPenOld ;
    373     CPoint pointNeedle[4] ;    // 指针由四边形组成
    374 
    375 
    376     // 计算角度并限定指针走的角度
    377     dAngleDeg = m_nStartAngleDeg-(360.0+m_nStartAngleDeg-m_nEndAngleDeg)
    378         *(m_dCurrentValue-m_dMinValue)/(m_dMaxValue-m_dMinValue);
    379     dAngleDeg = min(dAngleDeg, m_nStartAngleDeg);
    380     dAngleDeg = max(dAngleDeg, m_nEndAngleDeg-360.0);
    381     dAngleRad = dAngleDeg*dRadPerDeg;
    382 
    383     // 计算三角形底边两个点
    384     pointNeedle[0].x = m_ptMeterCenter.x - (int)(m_nCenterRadius*10*sin(dAngleRad)/8);
    385     pointNeedle[0].y = m_ptMeterCenter.y - (int)(m_nCenterRadius*10*cos(dAngleRad)/8);
    386     pointNeedle[2].x = m_ptMeterCenter.x + (int)(m_nCenterRadius*10*sin(dAngleRad)/8);
    387     pointNeedle[2].y = m_ptMeterCenter.y + (int)(m_nCenterRadius*10*cos(dAngleRad)/8);
    388     
    389     // 计算指针顶部坐标
    390     dTemp = m_ptMeterCenter.x + m_nRadiusFrame*cos(dAngleRad)*95/100;
    391     pointNeedle[1].x = ROUND(dTemp);
    392     dTemp = m_ptMeterCenter.y - m_nRadiusFrame*sin(dAngleRad)*95/100;
    393     pointNeedle[1].y = ROUND(dTemp);
    394     // 计算指针尾部坐标
    395     dTemp = m_ptMeterCenter.x - m_nRadiusFrame*cos(dAngleRad)/6;
    396     pointNeedle[3].x = ROUND(dTemp);
    397     dTemp = m_ptMeterCenter.y + m_nRadiusFrame*sin(dAngleRad)/6;
    398     pointNeedle[3].y = ROUND(dTemp);
    399 
    400     pDC->SelectClipRgn(&m_rgnBoundary);
    401 
    402     brushFill.CreateSolidBrush(m_colorNeedle);
    403     penDraw.CreatePen(PS_SOLID, 1, m_colorNeedle);
    404 
    405     pPenOld = pDC->SelectObject(&penDraw) ;
    406     pBrushOld = pDC->SelectObject(&brushFill) ;
    407 
    408     // 绘制指针
    409     pDC->Polygon(pointNeedle, 4);
    410 
    411     nResult = pDC->SelectClipRgn(NULL);
    412 
    413     pDC->SelectObject(pPenOld);
    414     pDC->SelectObject(pBrushOld);
    415 
    416     // 立体感处理
    417     if(dAngleDeg>90)
    418     {
    419         penDraw.DeleteObject();
    420         penDraw.CreatePen(PS_SOLID, 2, m_colorShadow);
    421         pPenOld = pDC->SelectObject(&penDraw);
    422         pDC->MoveTo(pointNeedle[1]);
    423         pDC->LineTo(pointNeedle[0]);
    424         pDC->LineTo(pointNeedle[3]);
    425         pDC->SelectObject(pPenOld);
    426         
    427         penDraw.DeleteObject();
    428         penDraw.CreatePen(PS_SOLID, 1, m_colorHighlight);
    429         pPenOld = pDC->SelectObject(&penDraw);
    430         pDC->MoveTo(pointNeedle[1]);
    431         pDC->LineTo(pointNeedle[2]);
    432         pDC->LineTo(pointNeedle[3]);
    433         pDC->SelectObject(pPenOld);
    434     }
    435     else
    436     {
    437         penDraw.DeleteObject();
    438         penDraw.CreatePen(PS_SOLID, 2, m_colorShadow);
    439         pPenOld = pDC->SelectObject(&penDraw);
    440         pDC->MoveTo(pointNeedle[1]);
    441         pDC->LineTo(pointNeedle[2]);
    442         pDC->LineTo(pointNeedle[3]);
    443         pDC->SelectObject(pPenOld);
    444         
    445         penDraw.DeleteObject();
    446         penDraw.CreatePen(PS_SOLID, 1, m_colorHighlight);
    447         pPenOld = pDC->SelectObject(&penDraw);
    448         pDC->MoveTo(pointNeedle[1]);
    449         pDC->LineTo(pointNeedle[0]);
    450         pDC->LineTo(pointNeedle[3]);
    451         pDC->SelectObject(pPenOld);
    452     }
    453 }
    454 
    455 void CMeter::UpdateNeedle(double dValue)
    456 {
    457     m_dCurrentValue = dValue;
    458     Invalidate();
    459 }
    460 
    461 void CMeter::SetNeedleColor(COLORREF colorNeedle)
    462 {
    463     m_colorNeedle = colorNeedle ;
    464     ReconstructControl() ;
    465 }
    466 
    467 
    468 void CMeter::SetRange(double dMin, double dMax)
    469 {
    470     m_dMaxValue = dMax ;
    471     m_dMinValue = dMin ;
    472     ReconstructControl() ;
    473 }
    474 
    475 
    476 void CMeter::SetScaleDecimals(int nDecimals)
    477 {
    478     m_nScaleDecimals = nDecimals ;
    479     ReconstructControl() ;
    480 }
    481 
    482 void CMeter::SetUnits(CString &strUnits)
    483 {
    484     m_strUnits = strUnits ;
    485     ReconstructControl() ;
    486 }
    487 
    488 void CMeter::SetValueDecimals(int nDecimals)
    489 {
    490     m_nValueDecimals = nDecimals ;
    491     ReconstructControl() ;
    492 }
    493 
    494 
    495 
    496 
    497 
    498 void CMeter::DrawNode(CDC *pDC)
    499 {
    500     CPen penDraw, *pPenOld;
    501     COLORREF cEdge, cMiddle, cNode;
    502     cMiddle = RGB(255, 255, 255);
    503     cEdge = RGB(0, 0, 0);
    504     for(int i=m_nCenterRadius*3/4; i>=0; i--)
    505     {
    506         cNode = RGB((GetRValue(cEdge)-GetRValue(cMiddle))*((float)i)*4/(3*m_nCenterRadius)+GetRValue(cMiddle),
    507             (GetGValue(cEdge)-GetGValue(cMiddle))*((float)i)*4/(3*m_nCenterRadius)+GetGValue(cMiddle),
    508             (GetBValue(cEdge)-GetBValue(cMiddle))*((float)i)*4/(3*m_nCenterRadius)+GetBValue(cMiddle));
    509     
    510         penDraw.DeleteObject();
    511         penDraw.CreatePen(PS_SOLID, 1, cNode);
    512         pPenOld = pDC->SelectObject(&penDraw);
    513         pDC->Arc(m_ptMeterCenter.x-i, m_ptMeterCenter.y-i,m_ptMeterCenter.x+i,m_ptMeterCenter.y+i,
    514             m_ptMeterCenter.x-i,m_ptMeterCenter.y,m_ptMeterCenter.x-i,m_ptMeterCenter.y);
    515         pDC->SelectObject(pPenOld);
    516     }
    517 }
    518 
    519 void CMeter::SetColorTick(BOOL bColorTick)
    520 {
    521     m_bColorTick = bColorTick;
    522     ReconstructControl();
    523 }
    524 
    525 void CMeter::DrawValue(CDC *pDC)
    526 {
    527     int nHeight;
    528     CPoint pttemp;
    529     CString strtemp;
    530     CFont *pFontOld;
    531 
    532     //  数值显示
    533     nHeight = m_nRadiusFrame/4;
    534     pttemp = m_rectValue.CenterPoint();
    535     strtemp.Format("%.*lf", m_nValueDecimals, m_dCurrentValue); 
    536     m_font.DeleteObject() ;
    537     m_font.CreateFont (nHeight, 0, 0, 0, 550,
    538                         FALSE, FALSE, 0, ANSI_CHARSET,
    539                         OUT_DEFAULT_PRECIS, 
    540                         CLIP_DEFAULT_PRECIS,
    541                         DEFAULT_QUALITY, 
    542                         DEFAULT_PITCH|FF_SWISS, "Arial") ;
    543     pFontOld = pDC->SelectObject(&m_font);
    544     pDC->SetBkColor(m_colorButton);
    545     pDC->SetTextAlign(TA_TOP|TA_CENTER);
    546     pDC->TextOut(pttemp.x, pttemp.y, m_strUnits);
    547     pDC->TextOut(pttemp.x, pttemp.y+nHeight, strtemp);
    548     // 恢复字体和背景色
    549     pDC->SelectObject(pFontOld);
    550     pDC->SetBkColor(m_colorWindow);
    551 }
    552 
    553 void CMeter::SetTicks(int nTicks)
    554 {
    555     m_nTicks = nTicks;
    556     ReconstructControl();
    557 }
    558 
    559 void CMeter::SetSubTicks(int nSubTicks)
    560 {
    561     m_nSubTicks = nSubTicks;
    562     ReconstructControl();
    563 }
    564 
    565 void CMeter::SetAngleRange(int nStartAngleDeg, int nEndAngleDeg)
    566 {
    567     m_nStartAngleDeg = nStartAngleDeg;
    568     m_nEndAngleDeg = nEndAngleDeg;
    569     ReconstructControl();
    570 }

    MemDCEx.h

      1 #ifndef _MEMDC_H_
      2 #define _MEMDC_H_
      3 
      4 //////////////////////////////////////////////////
      5 // CMemDC - memory DC
      6 //
      7 // Author: Keith Rule
      8 // Email:  keithr@europa.com
      9 // Copyright 1996-1999, Keith Rule
     10 //
     11 // You may freely use or modify this code provided this
     12 // Copyright is included in all derived versions.
     13 //
     14 // History - 10/3/97 Fixed scrolling bug.
     15 //                   Added print support. - KR
     16 //
     17 //           11/3/99 Fixed most common complaint. Added
     18 //                   background color fill. - KR
     19 //
     20 //           11/3/99 Added support for mapping modes other than
     21 //                   MM_TEXT as suggested by Lee Sang Hun. - KR
     22 //
     23 // Modified by Mark Malburg  March 12, 1998
     24 // Email:  mcmalburg@sytech.cummins.com
     25 //  (added new construction and clipboard handling)
     26 //
     27 //    Construction :
     28 //    |
     29 //    |    CMemDC pDC (dc, &drawRect, toMemDC) ;
     30 //    |    
     31 //    |    where:
     32 //    |        "dc"        - pointer to the CDC that is an argument to OnDraw
     33 //    |        "drawRect"    - pointer to the rectangle to draw in
     34 //    |        "boolToMemory"    - TRUE: to the client, FALSE: to clipboard or printer
     35 //    |
     36 //
     37 // This class implements a memory Device Context which allows
     38 // flicker free drawing.
     39 
     40 class CMemDCEx : public CDC 
     41 {
     42 private:    
     43     CBitmap        m_bitmap;        // Offscreen bitmap
     44     CBitmap*    m_oldBitmap;    // bitmap originally found in CMemDC
     45     CDC*        m_pDC;            // Saves CDC passed in constructor
     46     CRect        m_rect;            // Rectangle of drawing area.
     47     BOOL        m_bMemDC;        // TRUE if CDC really is a Memory DC.
     48 public:
     49     
     50     CMemDCEx(CDC* pDC, const CRect* pRect = NULL, bool boolToMemory = TRUE) : CDC()
     51     {
     52         ASSERT(pDC != NULL); 
     53 
     54         // Some initialization
     55         m_pDC = pDC;
     56         m_oldBitmap = NULL;
     57         if (boolToMemory)
     58             m_bMemDC = !pDC->IsPrinting();
     59         else
     60             m_bMemDC = FALSE ;
     61 
     62         // Get the rectangle to draw
     63         if (pRect == NULL) 
     64         {
     65             pDC->GetClipBox(&m_rect);
     66         } 
     67         else 
     68         {
     69             m_rect = *pRect;
     70         }
     71         
     72         if (m_bMemDC) 
     73         {
     74             // Create a Memory DC
     75             CreateCompatibleDC(pDC);
     76             pDC->LPtoDP(&m_rect);
     77 
     78             m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
     79             m_oldBitmap = SelectObject(&m_bitmap);
     80             
     81             SetMapMode(pDC->GetMapMode());
     82             pDC->DPtoLP(&m_rect);
     83             SetWindowOrg(m_rect.left, m_rect.top);
     84         } 
     85         else 
     86         {
     87             // Make a copy of the relevent parts of the current DC for printing
     88             if (pDC->IsPrinting())
     89                 m_bPrinting = pDC->m_bPrinting;
     90             m_hDC       = pDC->m_hDC;
     91             m_hAttribDC = pDC->m_hAttribDC;
     92         }
     93 
     94         // Fill background 
     95         FillSolidRect(m_rect, pDC->GetBkColor());
     96     }
     97 
     98     
     99     ~CMemDCEx()    
    100     {        
    101         if (m_bMemDC) 
    102         {
    103             // Copy the offscreen bitmap onto the screen.
    104             m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
    105                             this, m_rect.left, m_rect.top, SRCCOPY);            
    106             
    107             //Swap back the original bitmap.
    108             SelectObject(m_oldBitmap);
    109         } 
    110         else 
    111         {
    112             // All we need to do is replace the DC with an illegal value,
    113             // this keeps us from accidently deleting the handles associated with
    114             // the CDC that was passed to the constructor.            
    115             m_hDC = m_hAttribDC = NULL;
    116         }    
    117     }
    118     
    119     // Allow usage as a pointer    
    120     CMemDCEx* operator->() 
    121     {
    122         return this;
    123     }    
    124 
    125     // Allow usage as a pointer    
    126     operator CMemDCEx*() 
    127     {
    128         return this;
    129     }
    130 };
    131 
    132 #endif

     完整工程下载:https://download.csdn.net/download/qq_23565865/10715458

  • 相关阅读:
    跨浏览器右键复制实现
    在eclipse里如何快速定位到某一行?
    为数据库中的表添加字段步骤
    一键安装openstack juno 之controller node.
    Linux的/etc/services文件的作用?
    docker and ssh issues
    yum change source repo centos共存安装sun jdk6和jdk7
    random and password 在Linux下生成crypt加密密码的方法,shell 生成指定范围随机数与随机字符串
    OpenStack,ceph
    那些证书相关的玩意儿(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12等)[zz]
  • 原文地址:https://www.cnblogs.com/qiwu1314/p/9776736.html
Copyright © 2011-2022 走看看