This chapter is from the book
Exploring the Program Listings
Listings 3.25 and 3.26 show the complete code for the CGraphics2DView class, including the Graphics2DView.h header file and the Graphics2DView.cpp implementation file. Many other files were created by AppWizard when you started the Graphics2D application project. Because you didn't modify those files, they aren't shown here. However, you can easily view any of the project's files by loading them with Visual C++'s editor (or any other text editor).
Listing 3.25 The CGraphics2DView Class's Header File
// Graphics2DView.h : interface of the CGraphics2DView class // #pragma once typedef double MATRIX3X3[3][3]; typedef struct vector { int x, y, w; } VECTOR; typedef struct shape { int numVerts; VECTOR* vertices; } SHAPE; class CGraphics2DView : public CView { protected: // create from serialization only CGraphics2DView(); DECLARE_DYNCREATE(CGraphics2DView) // Attributes public: CGraphics2DDoc* GetDocument() const; protected: SHAPE m_polygon; VECTOR m_vectors[4]; int m_rotate; double m_xScale, m_yScale; double m_xTranslate, m_yTranslate; // Operations public: // Overrides public: virtual void OnDraw(CDC* pDC); // overridden to draw this view virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: // Implementation public: virtual ~CGraphics2DView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: void DrawShape(CDC* pDC, SHAPE& shape1); void Translate(MATRIX3X3& m, int xTrans, int yTrans); void Scale(MATRIX3X3& m, double xScale, double yScale); void Rotate(MATRIX3X3& m, int degrees); void Transform(SHAPE& shape, MATRIX3X3& m); void MultMatrix(MATRIX3X3& product, MATRIX3X3& matrix1, MATRIX3X3& matrix2); void InitMatrix(MATRIX3X3& m); void CopyMatrix(MATRIX3X3& dst, MATRIX3X3& src); // Generated message map functions protected: DECLARE_MESSAGE_MAP() public: afx_msg void OnTransformRotate(); afx_msg void OnTransformScale(); afx_msg void OnTransformTranslate(); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); }; #ifndef _DEBUG // debug version in Graphics2DView.cpp inline CGraphics2DDoc* CGraphics2DView::GetDocument() const { return reinterpret_cast<CGraphics2DDoc*>(m_pDocument); } #endif
Listing 3.26 The CGraphics2DView Class's Implementation File
// Graphics2DView.cpp : implementation of the CGraphics2DView class // #include "stdafx.h" #include "Graphics2D.h" #include "Graphics2DDoc.h" #include "Graphics2DView.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #include <math.h> #include "TransformDlg.h" // CGraphics2DView IMPLEMENT_DYNCREATE(CGraphics2DView, CView) BEGIN_MESSAGE_MAP(CGraphics2DView, CView) ON_COMMAND(ID_TRANSFORM_ROTATE, OnTransformRotate) ON_COMMAND(ID_TRANSFORM_SCALE, OnTransformScale) ON_COMMAND(ID_TRANSFORM_TRANSLATE, OnTransformTranslate) ON_WM_RBUTTONDOWN() END_MESSAGE_MAP() // CGraphics2DView construction/destruction CGraphics2DView::CGraphics2DView() { // TODO: add construction code here m_polygon.numVerts = 4; m_polygon.vertices = m_vectors; m_vectors[0].x = 0; m_vectors[0].y = 0; m_vectors[0].w = 1; m_vectors[1].x = 100; m_vectors[1].y = 0; m_vectors[1].w = 1; m_vectors[2].x = 100; m_vectors[2].y = 50; m_vectors[2].w = 1; m_vectors[3].x = 0; m_vectors[3].y = 75; m_vectors[3].w = 1; m_rotate = 0; m_xScale = 1; m_yScale = 1; m_xTranslate = 0; m_yTranslate = 0; } CGraphics2DView::~CGraphics2DView() { } BOOL CGraphics2DView::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CView::PreCreateWindow(cs); } // CGraphics2DView drawing void CGraphics2DView::OnDraw(CDC* pDC) { CGraphics2DDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here DrawShape(pDC, m_polygon); } // CGraphics2DView diagnostics #ifdef _DEBUG void CGraphics2DView::AssertValid() const { CView::AssertValid(); } void CGraphics2DView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CGraphics2DDoc* CGraphics2DView::GetDocument() const { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGraphics2DDoc))); return (CGraphics2DDoc*)m_pDocument; } #endif //_DEBUG // CGraphics2DView message handlers void CGraphics2DView::OnTransformRotate() { // TODO: Add your command handler code here CTransformDlg dlg; dlg.m_xAxis = 0; dlg.m_yAxis = 0; INT_PTR response = dlg.DoModal(); if (response == IDOK) m_rotate = (int) dlg.m_xAxis; } void CGraphics2DView::OnTransformScale() { // TODO: Add your command handler code here CTransformDlg dlg; dlg.m_xAxis = 1; dlg.m_yAxis = 1; INT_PTR response = dlg.DoModal(); if (response == IDOK) { m_xScale = dlg.m_xAxis; m_yScale = dlg.m_yAxis; } } void CGraphics2DView::OnTransformTranslate() { // TODO: Add your command handler code here CTransformDlg dlg; dlg.m_xAxis = 0; dlg.m_yAxis = 0; INT_PTR response = dlg.DoModal(); if (response == IDOK) { m_xTranslate = dlg.m_xAxis; m_yTranslate = dlg.m_yAxis; } } void CGraphics2DView::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default MATRIX3X3 m; InitMatrix(m); Translate(m, (int) m_xTranslate, (int) m_yTranslate); Scale(m, m_xScale, m_yScale); Rotate(m, m_rotate); Transform(m_polygon, m); m_rotate = 0; m_xScale = 1; m_yScale = 1; m_xTranslate = 0; m_yTranslate = 0; Invalidate(TRUE); CView::OnRButtonDown(nFlags, point); } void CGraphics2DView::InitMatrix(MATRIX3X3& m) { m[0][0]=1; m[0][1]=0; m[0][2]=0; m[1][0]=0; m[1][1]=1; m[1][2]=0; m[2][0]=0; m[2][1]=0; m[2][2]=1; } void CGraphics2DView::CopyMatrix(MATRIX3X3& dst, MATRIX3X3& src) { for (int i=0; i<3; ++i) for (int j=0; j<3; ++j) dst[i][j] = src[i][j]; } void CGraphics2DView::MultMatrix(MATRIX3X3& product, MATRIX3X3& matrix1, MATRIX3X3& matrix2) { for (int x=0; x<3; ++x) for (int y=0; y<3; ++y) { double sum = 0; for (int z=0; z<3; ++z) sum += matrix1[x][z] * matrix2[z][y]; product[x][y] = sum; } } void CGraphics2DView::Translate(MATRIX3X3& m, int xTrans, int yTrans) { MATRIX3X3 m1, m2; m1[0][0]=1; m1[0][1]=0; m1[0][2]=0; m1[1][0]=0; m1[1][1]=1; m1[1][2]=0; m1[2][0]=xTrans; m1[2][1]=yTrans; m1[2][2]=1; MultMatrix(m2, m1, m); CopyMatrix(m, m2); } void CGraphics2DView::Scale(MATRIX3X3& m, double xScale, double yScale) { MATRIX3X3 m1, m2; m1[0][0]=xScale; m1[0][1]=0; m1[0][2]=0; m1[1][0]=0; m1[1][1]=yScale; m1[1][2]=0; m1[2][0]=0; m1[2][1]=0; m1[2][2]=1; MultMatrix(m2, m1, m); CopyMatrix(m, m2); } void CGraphics2DView::Rotate(MATRIX3X3& m, int degrees) { MATRIX3X3 m1, m2; if (degrees == 0) return; double radians = 6.283185308 / (360.0 / degrees); double c = cos(radians); double s = sin(radians); m1[0][0]=c; m1[0][1]=s; m1[0][2]=0; m1[1][0]=-s; m1[1][1]=c; m1[1][2]=0; m1[2][0]=0; m1[2][1]=0; m1[2][2]=1; MultMatrix(m2, m1, m); CopyMatrix(m, m2); } void CGraphics2DView::Transform(SHAPE& shape, MATRIX3X3& m) { int transformedX, transformedY; for (int x=0; x<shape.numVerts; ++x) { transformedX = (int) (shape.vertices[x].x * m[0][0] + shape.vertices[x].y * m[1][0] + m[2][0]); transformedY = (int) (shape.vertices[x].x * m[0][1] + shape.vertices[x].y * m[1][1] + m[2][1]); shape.vertices[x].x = transformedX; shape.vertices[x].y = transformedY; } } void CGraphics2DView::DrawShape(CDC* pDC, SHAPE& shape1) { int newX, newY, startX, startY; RECT clientRect; GetClientRect(&clientRect); int maxY = clientRect.bottom; for (int x=0; x<shape1.numVerts; ++x) { newX = shape1.vertices[x].x; newY = maxY - shape1.vertices[x].y; if (x == 0) { pDC->MoveTo(newX, newY); startX = newX; startY = newY; } else pDC->LineTo(newX, newY); } pDC->LineTo(startX, startY); }