OSCOPECTRL.CPP
上传用户:shgx688
上传日期:2009-12-27
资源大小:855k
文件大小:16k
源码类别:

SNMP编程

开发平台:

MultiPlatform

  1. // OScopeCtrl.cpp : implementation file//
  2. #include "stdafx.h"
  3. #include "math.h"
  4. #include "OScopeCtrl.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__ ;
  9. #endif
  10. /////////////////////////////////////////////////////////////////////////////
  11. // COScopeCtrl
  12. COScopeCtrl::COScopeCtrl()
  13. {
  14.   // since plotting is based on a LineTo for each new point
  15.   // we need a starting point (i.e. a "previous" point)
  16.   // use 0.0 as the default first point.
  17.   // these are public member variables, and can be changed outside
  18.   // (after construction).  Therefore m_perviousPosition could be set to
  19.   // a more appropriate value prior to the first call to SetPosition.
  20.   m_dPreviousPosition =   0.0 ;
  21.   // public variable for the number of decimal places on the y axis
  22.   m_nYDecimals = 3 ;
  23.   // set some initial values for the scaling until "SetRange" is called.
  24.   // these are protected varaibles and must be set with SetRange
  25.   // in order to ensure that m_dRange is updated accordingly
  26.   m_dLowerLimit = -10.0 ;
  27.   m_dUpperLimit =  10.0 ;
  28.   m_dRange      =  m_dUpperLimit - m_dLowerLimit ;   // protected member variable
  29.   // m_nShiftPixels determines how much the plot shifts (in terms of pixels) 
  30.   // with the addition of a new data point
  31.   m_nShiftPixels     = 4 ;
  32.   m_nHalfShiftPixels = m_nShiftPixels/2 ;                     // protected
  33.   m_nPlotShiftPixels = m_nShiftPixels + m_nHalfShiftPixels ;  // protected
  34.   // background, grid and data colors
  35.   // these are public variables and can be set directly
  36.   m_crBackColor  = RGB(  0,   0,   0) ;  // see also SetBackgroundColor
  37.   m_crGridColor  = RGB(  0, 255, 255) ;  // see also SetGridColor
  38.   m_crPlotColor  = RGB(255, 255, 255) ;  // see also SetPlotColor
  39.   // protected variables
  40.   m_penPlot.CreatePen(PS_SOLID, 0, m_crPlotColor) ;
  41.   m_brushBack.CreateSolidBrush(m_crBackColor) ;
  42.   // public member variables, can be set directly 
  43.   m_strXUnitsString.Format("Samples") ;  // can also be set with SetXUnits
  44.   m_strYUnitsString.Format("Y units") ;  // can also be set with SetYUnits
  45.   // protected bitmaps to restore the memory DC's
  46.   m_pbitmapOldGrid = NULL ;
  47.   m_pbitmapOldPlot = NULL ;
  48. }  // COScopeCtrl
  49. /////////////////////////////////////////////////////////////////////////////
  50. COScopeCtrl::~COScopeCtrl()
  51. {
  52.   // just to be picky restore the bitmaps for the two memory dc's
  53.   // (these dc's are being destroyed so there shouldn't be any leaks)
  54.   if (m_pbitmapOldGrid != NULL)
  55.     m_dcGrid.SelectObject(m_pbitmapOldGrid) ;  
  56.   if (m_pbitmapOldPlot != NULL)
  57.     m_dcPlot.SelectObject(m_pbitmapOldPlot) ;  
  58. } // ~COScopeCtrl
  59. BEGIN_MESSAGE_MAP(COScopeCtrl, CWnd)
  60.   //{{AFX_MSG_MAP(COScopeCtrl)
  61.   ON_WM_PAINT()
  62.   ON_WM_SIZE()
  63.   //}}AFX_MSG_MAP
  64. END_MESSAGE_MAP()
  65. /////////////////////////////////////////////////////////////////////////////
  66. // COScopeCtrl message handlers
  67. /////////////////////////////////////////////////////////////////////////////
  68. BOOL COScopeCtrl::Create(DWORD dwStyle, const RECT& rect, 
  69.                          CWnd* pParentWnd, UINT nID) 
  70. {
  71.   BOOL result ;
  72.   static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW) ;
  73.   result = CWnd::CreateEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, 
  74.                           className, NULL, dwStyle, 
  75.                           rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
  76.                           pParentWnd->GetSafeHwnd(), (HMENU)nID) ;
  77.   if (result != 0)
  78.     InvalidateCtrl() ;
  79.   return result ;
  80. } // Create
  81. /////////////////////////////////////////////////////////////////////////////
  82. void COScopeCtrl::SetRange(double dLower, double dUpper, int nDecimalPlaces)
  83. {
  84.   ASSERT(dUpper > dLower) ;
  85.   m_dLowerLimit     = dLower ;
  86.   m_dUpperLimit     = dUpper ;
  87.   m_nYDecimals      = nDecimalPlaces ;
  88.   m_dRange          = m_dUpperLimit - m_dLowerLimit ;
  89.   m_dVerticalFactor = (double)m_nPlotHeight / m_dRange ; 
  90.   
  91.   // clear out the existing garbage, re-start with a clean plot
  92.   InvalidateCtrl() ;
  93. }  // SetRange
  94. /////////////////////////////////////////////////////////////////////////////
  95. void COScopeCtrl::SetXUnits(CString string)
  96. {
  97.   m_strXUnitsString = string ;
  98.   // clear out the existing garbage, re-start with a clean plot
  99.   InvalidateCtrl() ;
  100. }  // SetXUnits
  101. /////////////////////////////////////////////////////////////////////////////
  102. void COScopeCtrl::SetYUnits(CString string)
  103. {
  104.   m_strYUnitsString = string ;
  105.   // clear out the existing garbage, re-start with a clean plot
  106.   InvalidateCtrl() ;
  107. }  // SetYUnits
  108. /////////////////////////////////////////////////////////////////////////////
  109. void COScopeCtrl::SetGridColor(COLORREF color)
  110. {
  111.   m_crGridColor = color ;
  112.   // clear out the existing garbage, re-start with a clean plot
  113.   InvalidateCtrl() ;
  114. }  // SetGridColor
  115. /////////////////////////////////////////////////////////////////////////////
  116. void COScopeCtrl::SetPlotColor(COLORREF color)
  117. {
  118.   m_crPlotColor = color ;
  119.   m_penPlot.DeleteObject() ;
  120.   m_penPlot.CreatePen(PS_SOLID, 0, m_crPlotColor) ;
  121.   // clear out the existing garbage, re-start with a clean plot
  122.   InvalidateCtrl() ;
  123. }  // SetPlotColor
  124. /////////////////////////////////////////////////////////////////////////////
  125. void COScopeCtrl::SetBackgroundColor(COLORREF color)
  126. {
  127.   m_crBackColor = color ;
  128.   m_brushBack.DeleteObject() ;
  129.   m_brushBack.CreateSolidBrush(m_crBackColor) ;
  130.   // clear out the existing garbage, re-start with a clean plot
  131.   InvalidateCtrl() ;
  132. }  // SetBackgroundColor
  133. /////////////////////////////////////////////////////////////////////////////
  134. void COScopeCtrl::InvalidateCtrl()
  135. {
  136.   // There is a lot of drawing going on here - particularly in terms of 
  137.   // drawing the grid.  Don't panic, this is all being drawn (only once)
  138.   // to a bitmap.  The result is then BitBlt'd to the control whenever needed.
  139.   int i ;
  140.   int nCharacters ;
  141.   int nTopGridPix, nMidGridPix, nBottomGridPix ;
  142.   CPen *oldPen ;
  143.   CPen solidPen(PS_SOLID, 0, m_crGridColor) ;
  144.   CFont axisFont, yUnitFont, *oldFont ;
  145.   CString strTemp ;
  146.   // in case we haven't established the memory dc's
  147.   CClientDC dc(this) ;  
  148.   // if we don't have one yet, set up a memory dc for the grid
  149.   if (m_dcGrid.GetSafeHdc() == NULL)
  150.   {
  151.     m_dcGrid.CreateCompatibleDC(&dc) ;
  152.     m_bitmapGrid.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight) ;
  153.     m_pbitmapOldGrid = m_dcGrid.SelectObject(&m_bitmapGrid) ;
  154.   }
  155.   
  156.   m_dcGrid.SetBkColor (m_crBackColor) ;
  157.   // fill the grid background
  158.   m_dcGrid.FillRect(m_rectClient, &m_brushBack) ;
  159.   // draw the plot rectangle:
  160.   // determine how wide the y axis scaling values are
  161.   nCharacters = abs((int)log10(fabs(m_dUpperLimit))) ;
  162.   nCharacters = max(nCharacters, abs((int)log10(fabs(m_dLowerLimit)))) ;
  163.   // add the units digit, decimal point and a minus sign, and an extra space
  164.   // as well as the number of decimal places to display
  165.   nCharacters = nCharacters + 4 + m_nYDecimals ;  
  166.   // adjust the plot rectangle dimensions
  167.   // assume 6 pixels per character (this may need to be adjusted)
  168.   m_rectPlot.left = m_rectClient.left + 6*(nCharacters) ;
  169.   m_nPlotWidth    = m_rectPlot.Width() ;
  170.   // draw the plot rectangle
  171.   oldPen = m_dcGrid.SelectObject (&solidPen) ; 
  172.   m_dcGrid.MoveTo (m_rectPlot.left, m_rectPlot.top) ;
  173.   m_dcGrid.LineTo (m_rectPlot.right+1, m_rectPlot.top) ;
  174.   m_dcGrid.LineTo (m_rectPlot.right+1, m_rectPlot.bottom+1) ;
  175.   m_dcGrid.LineTo (m_rectPlot.left, m_rectPlot.bottom+1) ;
  176.   m_dcGrid.LineTo (m_rectPlot.left, m_rectPlot.top) ;
  177.   m_dcGrid.SelectObject (oldPen) ; 
  178.   // draw the dotted lines, 
  179.   // use SetPixel instead of a dotted pen - this allows for a 
  180.   // finer dotted line and a more "technical" look
  181.   nMidGridPix    = (m_rectPlot.top + m_rectPlot.bottom)/2 ;
  182.   nTopGridPix    = nMidGridPix - m_nPlotHeight/4 ;
  183.   nBottomGridPix = nMidGridPix + m_nPlotHeight/4 ;
  184.   for (i=m_rectPlot.left; i<m_rectPlot.right; i+=4)
  185.   {
  186.     m_dcGrid.SetPixel (i, nTopGridPix,    m_crGridColor) ;
  187.     m_dcGrid.SetPixel (i, nMidGridPix,    m_crGridColor) ;
  188.     m_dcGrid.SetPixel (i, nBottomGridPix, m_crGridColor) ;
  189.   }
  190.   // create some fonts (horizontal and vertical)
  191.   // use a height of 14 pixels and 300 weight 
  192.   // (these may need to be adjusted depending on the display)
  193.   axisFont.CreateFont (14, 0, 0, 0, 300,
  194.                        FALSE, FALSE, 0, ANSI_CHARSET,
  195.                        OUT_DEFAULT_PRECIS, 
  196.                        CLIP_DEFAULT_PRECIS,
  197.                        DEFAULT_QUALITY, 
  198.                        DEFAULT_PITCH|FF_SWISS, "Arial") ;
  199.   yUnitFont.CreateFont (14, 0, 900, 0, 300,
  200.                        FALSE, FALSE, 0, ANSI_CHARSET,
  201.                        OUT_DEFAULT_PRECIS, 
  202.                        CLIP_DEFAULT_PRECIS,
  203.                        DEFAULT_QUALITY, 
  204.                        DEFAULT_PITCH|FF_SWISS, "Arial") ;
  205.   
  206.   // grab the horizontal font
  207.   oldFont = m_dcGrid.SelectObject(&axisFont) ;
  208.   
  209.   // y max
  210.   m_dcGrid.SetTextColor (m_crGridColor) ;
  211.   m_dcGrid.SetTextAlign (TA_RIGHT|TA_TOP) ;
  212.   strTemp.Format ("%.*lf", m_nYDecimals, m_dUpperLimit) ;
  213.   m_dcGrid.TextOut (m_rectPlot.left-4, m_rectPlot.top, strTemp) ;
  214.   // y min
  215.   m_dcGrid.SetTextAlign (TA_RIGHT|TA_BASELINE) ;
  216.   strTemp.Format ("%.*lf", m_nYDecimals, m_dLowerLimit) ;
  217.   m_dcGrid.TextOut (m_rectPlot.left-4, m_rectPlot.bottom, strTemp) ;
  218.   // x min
  219.   m_dcGrid.SetTextAlign (TA_LEFT|TA_TOP) ;
  220.   m_dcGrid.TextOut (m_rectPlot.left, m_rectPlot.bottom+4, "0") ;
  221.   // x max
  222.   m_dcGrid.SetTextAlign (TA_RIGHT|TA_TOP) ;
  223.   strTemp.Format ("%d", m_nPlotWidth/m_nShiftPixels) ; 
  224.   m_dcGrid.TextOut (m_rectPlot.right, m_rectPlot.bottom+4, strTemp) ;
  225.   // x units
  226.   m_dcGrid.SetTextAlign (TA_CENTER|TA_TOP) ;
  227.   m_dcGrid.TextOut ((m_rectPlot.left+m_rectPlot.right)/2, 
  228.                     m_rectPlot.bottom+4, m_strXUnitsString) ;
  229.   // restore the font
  230.   m_dcGrid.SelectObject(oldFont) ;
  231.   // y units
  232.   oldFont = m_dcGrid.SelectObject(&yUnitFont) ;
  233.   m_dcGrid.SetTextAlign (TA_CENTER|TA_BASELINE) ;
  234.   m_dcGrid.TextOut ((m_rectClient.left+m_rectPlot.left)/2, 
  235.                     (m_rectPlot.bottom+m_rectPlot.top)/2, m_strYUnitsString) ;
  236.   m_dcGrid.SelectObject(oldFont) ;
  237.   // at this point we are done filling the the grid bitmap, 
  238.   // no more drawing to this bitmap is needed until the setting are changed
  239.   
  240.   // if we don't have one yet, set up a memory dc for the plot
  241.   if (m_dcPlot.GetSafeHdc() == NULL)
  242.   {
  243.     m_dcPlot.CreateCompatibleDC(&dc) ;
  244.     m_bitmapPlot.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight) ;
  245.     m_pbitmapOldPlot = m_dcPlot.SelectObject(&m_bitmapPlot) ;
  246.   }
  247.   // make sure the plot bitmap is cleared
  248.   m_dcPlot.SetBkColor (m_crBackColor) ;
  249.   m_dcPlot.FillRect(m_rectClient, &m_brushBack) ;
  250.   // finally, force the plot area to redraw
  251.   InvalidateRect(m_rectClient) ;
  252. } // InvalidateCtrl
  253. /////////////////////////////////////////////////////////////////////////////
  254. double COScopeCtrl::AppendPoint(double dNewPoint)
  255. {
  256.   // append a data point to the plot
  257.   // return the previous point
  258.   double dPrevious ;
  259.   
  260.   dPrevious = m_dCurrentPosition ;
  261.   m_dCurrentPosition = dNewPoint ;
  262.   DrawPoint() ;
  263.   Invalidate() ;
  264.   return dPrevious ;
  265. } // AppendPoint
  266.  
  267. ////////////////////////////////////////////////////////////////////////////
  268. void COScopeCtrl::OnPaint() 
  269. {
  270.   CPaintDC dc(this) ;  // device context for painting
  271.   CDC memDC ;
  272.   CBitmap memBitmap ;
  273.   CBitmap* oldBitmap ; // bitmap originally found in CMemDC
  274.   // no real plotting work is performed here, 
  275.   // just putting the existing bitmaps on the client
  276.   // to avoid flicker, establish a memory dc, draw to it 
  277.   // and then BitBlt it to the client
  278.   memDC.CreateCompatibleDC(&dc) ;
  279.   memBitmap.CreateCompatibleBitmap(&dc, m_nClientWidth, m_nClientHeight) ;
  280.   oldBitmap = (CBitmap *)memDC.SelectObject(&memBitmap) ;
  281.   if (memDC.GetSafeHdc() != NULL)
  282.   {
  283.     // first drop the grid on the memory dc
  284.     memDC.BitBlt(0, 0, m_nClientWidth, m_nClientHeight, 
  285.                  &m_dcGrid, 0, 0, SRCCOPY) ;
  286.     // now add the plot on top as a "pattern" via SRCPAINT.
  287.     // works well with dark background and a light plot
  288.     memDC.BitBlt(0, 0, m_nClientWidth, m_nClientHeight, 
  289.                  &m_dcPlot, 0, 0, SRCPAINT) ;  //SRCPAINT
  290.     // finally send the result to the display
  291.     dc.BitBlt(0, 0, m_nClientWidth, m_nClientHeight, 
  292.               &memDC, 0, 0, SRCCOPY) ;
  293.   }
  294.   memDC.SelectObject(oldBitmap) ;
  295. } // OnPaint
  296. /////////////////////////////////////////////////////////////////////////////
  297. void COScopeCtrl::DrawPoint()
  298. {
  299.   // this does the work of "scrolling" the plot to the left
  300.   // and appending a new data point all of the plotting is 
  301.   // directed to the memory based bitmap associated with m_dcPlot
  302.   // the will subsequently be BitBlt'd to the client in OnPaint
  303.   
  304.   int currX, prevX, currY, prevY ;
  305.   CPen *oldPen ;
  306.   CRect rectCleanUp ;
  307.   if (m_dcPlot.GetSafeHdc() != NULL)
  308.   {
  309.     // shift the plot by BitBlt'ing it to itself 
  310.     // note: the m_dcPlot covers the entire client
  311.     //       but we only shift bitmap that is the size 
  312.     //       of the plot rectangle
  313.     // grab the right side of the plot (exluding m_nShiftPixels on the left)
  314.     // move this grabbed bitmap to the left by m_nShiftPixels
  315.     m_dcPlot.BitBlt(m_rectPlot.left, m_rectPlot.top+1, 
  316.                     m_nPlotWidth, m_nPlotHeight, &m_dcPlot, 
  317.                     m_rectPlot.left+m_nShiftPixels, m_rectPlot.top+1, 
  318.                     SRCCOPY) ;
  319.     // establish a rectangle over the right side of plot
  320.     // which now needs to be cleaned up proir to adding the new point
  321.     rectCleanUp = m_rectPlot ;
  322.     rectCleanUp.left  = rectCleanUp.right - m_nShiftPixels ;
  323.     // fill the cleanup area with the background
  324.     m_dcPlot.FillRect(rectCleanUp, &m_brushBack) ;
  325.     // draw the next line segement
  326.     // grab the plotting pen
  327.     oldPen = m_dcPlot.SelectObject(&m_penPlot) ;
  328.     // move to the previous point
  329.     prevX = m_rectPlot.right-m_nPlotShiftPixels ;
  330.     prevY = m_rectPlot.bottom - 
  331.             (long)((m_dPreviousPosition - m_dLowerLimit) * m_dVerticalFactor) ;
  332.     m_dcPlot.MoveTo (prevX, prevY) ;
  333.     // draw to the current point
  334.     currX = m_rectPlot.right-m_nHalfShiftPixels ;
  335.     currY = m_rectPlot.bottom -
  336.             (long)((m_dCurrentPosition - m_dLowerLimit) * m_dVerticalFactor) ;
  337.     m_dcPlot.LineTo (currX, currY) ;
  338.     // restore the pen 
  339.     m_dcPlot.SelectObject(oldPen) ;
  340.     // if the data leaks over the upper or lower plot boundaries
  341.     // fill the upper and lower leakage with the background
  342.     // this will facilitate clipping on an as needed basis
  343.     // as opposed to always calling IntersectClipRect
  344.     if ((prevY <= m_rectPlot.top) || (currY <= m_rectPlot.top))
  345.       m_dcPlot.FillRect(CRect(prevX, m_rectClient.top, currX+1, m_rectPlot.top+1), &m_brushBack) ;
  346.     if ((prevY >= m_rectPlot.bottom) || (currY >= m_rectPlot.bottom))
  347.       m_dcPlot.FillRect(CRect(prevX, m_rectPlot.bottom+1, currX+1, m_rectClient.bottom+1), &m_brushBack) ;
  348.     // store the current point for connection to the next point
  349.     m_dPreviousPosition = m_dCurrentPosition ;
  350.   }
  351. } // end DrawPoint
  352. /////////////////////////////////////////////////////////////////////////////
  353. void COScopeCtrl::OnSize(UINT nType, int cx, int cy) 
  354. {
  355.   CWnd::OnSize(nType, cx, cy) ;
  356.   // NOTE: OnSize automatically gets called during the setup of the control
  357.   
  358.   GetClientRect(m_rectClient) ;
  359.   // set some member variables to avoid multiple function calls
  360.   m_nClientHeight = m_rectClient.Height() ;
  361.   m_nClientWidth  = m_rectClient.Width() ;
  362.   // the "left" coordinate and "width" will be modified in 
  363.   // InvalidateCtrl to be based on the width of the y axis scaling
  364.   m_rectPlot.left   = 20 ;  
  365.   m_rectPlot.top    = 10 ;
  366.   m_rectPlot.right  = m_rectClient.right-10 ;
  367.   m_rectPlot.bottom = m_rectClient.bottom-25 ;
  368.   // set some member variables to avoid multiple function calls
  369.   m_nPlotHeight = m_rectPlot.Height() ;
  370.   m_nPlotWidth  = m_rectPlot.Width() ;
  371.   // set the scaling factor for now, this can be adjusted 
  372.   // in the SetRange functions
  373.   m_dVerticalFactor = (double)m_nPlotHeight / m_dRange ; 
  374. } // OnSize
  375. /////////////////////////////////////////////////////////////////////////////
  376. void COScopeCtrl::Reset()
  377. {
  378.   // to clear the existing data (in the form of a bitmap)
  379.   // simply invalidate the entire control
  380.   InvalidateCtrl() ;
  381. }