home *** CD-ROM | disk | FTP | other *** search
/ Mastering MFC Development / MMD.ISO / samples / c07 / tmpgraph / grafview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-02-20  |  5.5 KB  |  194 lines

  1. // GrafView.cpp : implementation of the CTemperatureGraphView class
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "TmpGraph.h"
  6. #include "TGrafDoc.h"
  7. #include "GrafView.h"
  8.  
  9. #include <math.h>  // for fabs()
  10.  
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16.  
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CTemperatureGraphView
  19.  
  20. IMPLEMENT_DYNCREATE(CTemperatureGraphView, CView)
  21.  
  22. BEGIN_MESSAGE_MAP(CTemperatureGraphView, CView)
  23.     //{{AFX_MSG_MAP(CTemperatureGraphView)
  24.         // NOTE - the ClassWizard will add and remove mapping macros here.
  25.         //    DO NOT EDIT what you see in these blocks of generated code!
  26.     //}}AFX_MSG_MAP
  27.     // Standard printing commands
  28.     ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
  29.     ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
  30.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
  31. END_MESSAGE_MAP()
  32.  
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CTemperatureGraphView construction/destruction
  35.  
  36. CTemperatureGraphView::CTemperatureGraphView()
  37. {
  38. }
  39.  
  40. CTemperatureGraphView::~CTemperatureGraphView()
  41. {
  42. }
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45. // CTemperatureGraphView drawing
  46.  
  47. const int MAXTEMP = 40;
  48. const int MINTEMP = -10;
  49.  
  50. const int PERCENTAGE = 85;
  51. const int MARGIN = (100 - PERCENTAGE) / 2;
  52.  
  53. void CTemperatureGraphView::OnDraw(CDC* pDC)
  54. {
  55.     SetMappingMode(pDC);
  56.     DrawAxes(pDC);
  57.  
  58.     CFont *    prevFont = (CFont*) pDC->SelectStockObject(ANSI_FIXED_FONT);
  59.         DrawHorizontalDecorations(pDC);
  60.         DrawVerticalDecorations(pDC);
  61.     pDC->SelectObject(prevFont);
  62.     
  63.     DrawGraph(pDC);
  64. }
  65.  
  66. void CTemperatureGraphView::DrawGraph(CDC* pDC)
  67. {
  68.     CTemperatureGraphDoc * pDoc = GetDocument();
  69.  
  70.     CPen redPen, *oldPen;
  71.     redPen.CreatePen(PS_SOLID,0,RGB(255,0,0));
  72.     oldPen = pDC->SelectObject(&redPen);
  73.  
  74.     pDC->Polyline(pDoc->temps.GetData(), pDoc->temps.GetSize());
  75.     
  76.     pDC->SelectObject(oldPen);
  77. }
  78.  
  79. void CTemperatureGraphView::DrawVerticalDecorations(CDC* pDC)
  80. {
  81.     const int LINE_WIDTH = 1;
  82.     int xpos, ypos;
  83.  
  84.     // Draw tics on the vertical axis every 10 degrees
  85.     for (xpos = LINE_WIDTH, ypos = MAXTEMP; ypos >= MINTEMP; ypos -= 10)
  86.     {
  87.         pDC->MoveTo(-xpos, ypos);
  88.         pDC->LineTo(0, ypos);
  89.     }
  90.  
  91.     // Draw labels on the vertical axis.
  92.     pDC->SetTextAlign(TA_RIGHT | TA_BASELINE);
  93.     CString s;
  94.     for (xpos = -2, ypos = MAXTEMP; ypos >= MINTEMP; ypos -= 10)
  95.     {
  96.         s.Format("%3d", ypos);
  97.         pDC->TextOut(xpos, ypos, s);
  98.     }
  99. }    
  100.  
  101. void CTemperatureGraphView::DrawHorizontalDecorations(CDC* pDC)
  102. {
  103.     const int LINE_HEIGHT = 2;
  104.     int xpos, ypos;
  105.     
  106.     // Draw tics on the horizontal axis.
  107.     for (xpos = 1, ypos = LINE_HEIGHT; xpos <= 30; xpos ++)
  108.     {
  109.         pDC->MoveTo(xpos, ypos);
  110.         pDC->LineTo(xpos, -ypos);
  111.     }
  112.  
  113.     // Draw labels on the horizontal axis.
  114.     pDC->SetTextAlign(TA_CENTER);
  115.     int xval = 3;
  116.     CString s;
  117.     for (xpos = 1, ypos = -LINE_HEIGHT; xpos < 31; xval +=3, xpos += 3)
  118.     {
  119.         s.Format("%2d", xval);
  120.         pDC->TextOut(xpos, ypos, s);
  121.     }
  122. }
  123.  
  124. void CTemperatureGraphView::SetMappingMode(CDC* pDC)
  125. {
  126.     // Establish a coordinate system that lets me map my own reality.
  127.     pDC->SetMapMode(MM_ANISOTROPIC);
  128.     
  129.     // Set the size of my logical window. There are 31 days in the
  130.     // month, and the temperature varies from MAXTEMP to MINTEMP.
  131.     pDC->SetWindowExt(31, abs(MAXTEMP - MINTEMP));
  132.  
  133.     CRect me;
  134.     GetClientRect(&me);
  135.     // By default, the viewport considers 
  136.     //        1 that the origin is at the upper left corner and
  137.     //        2 that x increases to the right and y increases downwards
  138.     // We need to alter both of these to make it appropriate for a
  139.     // temperature graph, where the origin is at the left.
  140.  
  141.     // First, we make it so that Y increases in an upward direction.
  142.     // This is done by making the 2nd argument negative.
  143.     // X is OK as is. To allow a bit of room for some whitespace around
  144.     // the graph, only PERCENTAGE % of the available area is used.
  145.     pDC->SetViewportExt(PERCENTAGE * me.right / 100,
  146.                         -(PERCENTAGE * me.bottom / 100));
  147.  
  148.     // Next, we move the origin to the lower left side, but not all
  149.     // the way to the bottom. X increases to the right of this 
  150.     // point and decreases to the left. Y increases above this point
  151.     // and decreases below it.
  152.     
  153.     // To get the x axis in the right place, we have to do some complicated
  154.     // calculations to the y coordinate. The graph occupies PERCANTAGE
  155.     // of the client area. y = 0 lies MARGIN + the positive amount
  156.     // of the graph. 
  157.     // thus is a fraction of PERCENTAGE.
  158.     int y = MARGIN +
  159.         (int) (fabs(MAXTEMP * 1.0 / (MAXTEMP - MINTEMP)) * PERCENTAGE);
  160.     pDC->SetViewportOrg(2 * MARGIN * me.right / 100, y * me.bottom / 100);
  161. }
  162.  
  163. void CTemperatureGraphView::DrawAxes(CDC* pDC)
  164. {
  165.     pDC->MoveTo(0, 0);
  166.     pDC->LineTo(30, 0);
  167.     pDC->MoveTo(0, MINTEMP);
  168.     pDC->LineTo(0, MAXTEMP);
  169. }
  170.  
  171. /////////////////////////////////////////////////////////////////////////////
  172. // CTemperatureGraphView diagnostics
  173.  
  174. #ifdef _DEBUG
  175. void CTemperatureGraphView::AssertValid() const
  176. {
  177.     CView::AssertValid();
  178. }
  179.  
  180. void CTemperatureGraphView::Dump(CDumpContext& dc) const
  181. {
  182.     CView::Dump(dc);
  183. }
  184.  
  185. CTemperatureGraphDoc* CTemperatureGraphView::GetDocument() // non-debug version is inline
  186. {
  187.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTemperatureGraphDoc)));
  188.     return (CTemperatureGraphDoc*)m_pDocument;
  189. }
  190. #endif //_DEBUG
  191.  
  192. /////////////////////////////////////////////////////////////////////////////
  193. // CTemperatureGraphView message handlers
  194.