home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 19.ddi / MFC / SAMPLES / SCRIBBLE / STEP4 / SCRIBDOC.CP_ / SCRIBDOC.CP
Encoding:
Text File  |  1993-02-08  |  8.1 KB  |  312 lines

  1. // scribdoc.cpp : implementation of the CScribDoc class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and Microsoft
  9. // QuickHelp and/or WinHelp documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13.  
  14. #include "stdafx.h"
  15. #include "scribble.h"
  16.  
  17. #include "scribdoc.h"
  18. #include "pendlg.h"
  19.  
  20. #ifdef _DEBUG
  21. #undef THIS_FILE
  22. static char BASED_CODE THIS_FILE[] = __FILE__;
  23. #endif
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CScribDoc
  27.  
  28. IMPLEMENT_DYNCREATE(CScribDoc, CDocument)
  29.  
  30. BEGIN_MESSAGE_MAP(CScribDoc, CDocument)
  31.     //{{AFX_MSG_MAP(CScribDoc)
  32.         // NOTE - the ClassWizard will add and remove mapping macros here.
  33.         //    DO NOT EDIT what you see in these blocks of generated code !
  34.     ON_COMMAND(ID_EDIT_CLEAR_ALL, OnEditClearAll)
  35.     ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR_ALL, OnUpdateEditClearAll)
  36.     ON_COMMAND(ID_PEN_THICK_OR_THIN, OnPenThickOrThin)
  37.     ON_UPDATE_COMMAND_UI(ID_PEN_THICK_OR_THIN, OnUpdatePenThickOrThin)
  38.     ON_COMMAND(ID_PEN_WIDTHS, OnPenWidths)
  39.     //}}AFX_MSG_MAP
  40. END_MESSAGE_MAP()
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CScribDoc construction/destruction
  44.  
  45. CScribDoc::CScribDoc()
  46. {
  47.     // TODO: add one-time construction code here
  48. }
  49.  
  50. CScribDoc::~CScribDoc()
  51. {
  52. }
  53.  
  54. /////////////////////////////////////////////////////////////////////////////
  55. void CScribDoc::DeleteContents()
  56. {
  57.     while (!m_strokeList.IsEmpty())
  58.     {
  59.         delete m_strokeList.RemoveHead();
  60.     }
  61. }
  62.  
  63. void CScribDoc::InitDocument()
  64. {
  65.     m_bThickPen = FALSE;
  66.     m_nThinWidth = 2;   // default thin pen is 2 pixels wide
  67.     m_nThickWidth = 5;  // default thick pen is 5 pixels wide
  68.     ReplacePen();       // initialze pen according to current width
  69.  
  70.     // default document size is 800 x 900 screen pixels
  71.     m_sizeDoc = CSize(800,900);
  72.  
  73. }
  74.  
  75. BOOL CScribDoc::OnNewDocument()
  76. {
  77.     if (!CDocument::OnNewDocument())
  78.         return FALSE;
  79.     InitDocument();
  80.     return TRUE;
  81. }
  82.  
  83. BOOL CScribDoc::OnOpenDocument(const char* pszPathName)
  84. {
  85.     if (!CDocument::OnOpenDocument(pszPathName))
  86.         return FALSE;
  87.     InitDocument();
  88.     return TRUE;
  89. }
  90.  
  91. /////////////////////////////////////////////////////////////////////////////
  92. // CScribDoc serialization
  93.  
  94. void CScribDoc::Serialize(CArchive& ar)
  95. {
  96.     if (ar.IsStoring())
  97.     {
  98.         ar << m_sizeDoc;
  99.     }
  100.     else
  101.     {
  102.         ar >> m_sizeDoc;
  103.     }
  104.     m_strokeList.Serialize(ar);
  105. }
  106.  
  107.  
  108. /////////////////////////////////////////////////////////////////////////////
  109. // CScribDoc diagnostics
  110.  
  111. #ifdef _DEBUG
  112. void CScribDoc::AssertValid() const
  113. {
  114.     CDocument::AssertValid();
  115. }
  116.  
  117. void CScribDoc::Dump(CDumpContext& dc) const
  118. {
  119.     CDocument::Dump(dc);
  120. }
  121.  
  122. #endif //_DEBUG
  123.  
  124. /////////////////////////////////////////////////////////////////////////////
  125. // CScribDoc commands
  126.  
  127. void CScribDoc::OnEditClearAll()
  128. {
  129.     DeleteContents();
  130.     SetModifiedFlag();  // Mark the document as having been modified, for 
  131.                         // purposes of confirming File Close.
  132.     UpdateAllViews(NULL);
  133. }
  134.  
  135. void CScribDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI)
  136. {
  137.     // Enable the command user interface object (menu item or tool bar
  138.     // button) if the document is non-empty, i.e., has at least one stroke.
  139.     pCmdUI->Enable(!m_strokeList.IsEmpty());
  140. }
  141.  
  142.  
  143. /////////////////////////////////////////////////////////////////////////////
  144. void CScribDoc::OnPenThickOrThin()
  145. {
  146.     // Toggle the state of the pen between thin or thick.
  147.     m_bThickPen = !m_bThickPen;
  148.  
  149.     // Change the current pen to reflect the new user-specified width.
  150.     ReplacePen();
  151. }
  152.  
  153.  
  154. /////////////////////////////////////////////////////////////////////////////
  155. void CScribDoc::OnUpdatePenThickOrThin(CCmdUI* pCmdUI)
  156. {
  157.     // Add check mark to Draw Thick Line menu item, if the current
  158.     // pen width is "thick".
  159.     pCmdUI->SetCheck(m_bThickPen);
  160. }
  161.  
  162.  
  163. /////////////////////////////////////////////////////////////////////////////
  164. void CScribDoc::OnPenWidths()
  165. {
  166.     CPenWidthsDlg dlg;
  167.     // Initialize dialog data
  168.     dlg.m_nThinWidth = m_nThinWidth;
  169.     dlg.m_nThickWidth = m_nThickWidth;
  170.  
  171.     // Invoke the dialog box
  172.     if (dlg.DoModal() == IDOK)
  173.     {
  174.         // retrieve the dialog data
  175.         m_nThinWidth = dlg.m_nThinWidth;
  176.         m_nThickWidth = dlg.m_nThickWidth;
  177.  
  178.         // Update the pen that is used by views when drawing new strokes,
  179.         // to reflect the new pen width definitions for "thick" and "thin".
  180.         ReplacePen();
  181.     }
  182. }
  183.  
  184. /////////////////////////////////////////////////////////////////////////////
  185. void CScribDoc::ReplacePen()
  186. {
  187.     m_nPenWidth = m_bThickPen? m_nThickWidth : m_nThinWidth;
  188.  
  189.     // Change the current pen to reflect the new user-specified width.
  190.     m_penCur.DeleteObject();
  191.     m_penCur.CreatePen(PS_SOLID, m_nPenWidth, RGB(0,0,0)); // solid black
  192. }
  193.  
  194. /////////////////////////////////////////////////////////////////////////////
  195. CStroke* CScribDoc::NewStroke()
  196. {
  197.     CStroke* pStrokeItem = new CStroke(m_nPenWidth);
  198.     m_strokeList.AddTail(pStrokeItem);
  199.     SetModifiedFlag();  // Mark the document as having been modified, for
  200.                         // purposes of confirming File Close.
  201.     return pStrokeItem;
  202. }
  203.  
  204. /////////////////////////////////////////////////////////////////////////////
  205. POSITION CScribDoc::GetFirstStrokePos()
  206. {
  207.     return m_strokeList.GetHeadPosition();
  208. }
  209.  
  210.  
  211. /////////////////////////////////////////////////////////////////////////////
  212. CStroke* CScribDoc::GetNextStroke(POSITION& pos)
  213. {
  214.     return (CStroke*)m_strokeList.GetNext(pos);
  215. }
  216.  
  217.  
  218. /////////////////////////////////////////////////////////////////////////////
  219. // CStroke
  220.  
  221. // Each time we change what gets serialized, we change the
  222. // schema number.
  223. IMPLEMENT_SERIAL(CStroke, CObject, 2)
  224. /////////////////////////////////////////////////////////////////////////////
  225. CStroke::CStroke()
  226. {
  227.     // this empty constructor should be used by serialization only
  228. }
  229.  
  230. /////////////////////////////////////////////////////////////////////////////
  231. CStroke::CStroke(UINT nPenWidth)
  232. {
  233.     m_nPenWidth = nPenWidth;
  234.     m_rectBounding.SetRectEmpty();
  235. }
  236.  
  237. /////////////////////////////////////////////////////////////////////////////
  238. void CStroke::AddPoint(CPoint pt)
  239. {
  240.     m_pointArray.Add(MAKELONG(pt.x, pt.y));
  241. }
  242.  
  243. /////////////////////////////////////////////////////////////////////////////
  244. BOOL CStroke::DrawStroke(CDC* pDC)
  245. {
  246.     CPen penStroke;
  247.     if (!penStroke.CreatePen(PS_SOLID, m_nPenWidth, RGB(0,0,0)))
  248.         return FALSE;
  249.     CPen* pOldPen = pDC->SelectObject(&penStroke);
  250.     pDC->MoveTo(GetPoint(0));
  251.     for (int i=1; i < m_pointArray.GetSize(); i++)
  252.     {
  253.         pDC->LineTo(GetPoint(i));
  254.     }
  255.  
  256.     pDC->SelectObject(pOldPen);
  257.     return TRUE;
  258. }
  259.  
  260. /////////////////////////////////////////////////////////////////////////////
  261. void CStroke::Serialize(CArchive& ar)
  262. {
  263.     if (ar.IsStoring())
  264.     {
  265.         ar << m_rectBounding;
  266.         ar << (WORD)m_nPenWidth;
  267.         m_pointArray.Serialize(ar);
  268.     }
  269.     else
  270.     {
  271.         ar >> m_rectBounding;
  272.         WORD w;
  273.         ar >> w;
  274.         m_nPenWidth = w;
  275.         m_pointArray.Serialize(ar);
  276.     }
  277. }
  278.  
  279. /////////////////////////////////////////////////////////////////////////////
  280. void CStroke::FinishStroke()
  281. {
  282.     // Calculate the bounding rectangle.  It's needed for smart
  283.     // repainting.
  284.  
  285.     if (m_pointArray.GetSize()==0)
  286.     {
  287.         m_rectBounding.SetRectEmpty();
  288.         return;
  289.     }
  290.     CPoint pt = GetPoint(0);
  291.     m_rectBounding = CRect(pt.x, pt.y, pt.x, pt.y);
  292.  
  293.     for (int i=1; i < m_pointArray.GetSize(); i++)
  294.     {
  295.         // If the point lies outside of the accumulated bounding
  296.         // rectangle, then inflate the bounding rect to include it.
  297.         pt = GetPoint(i);
  298.         m_rectBounding.left     = min(m_rectBounding.left, pt.x);
  299.         m_rectBounding.right    = max(m_rectBounding.right, pt.x);
  300.         m_rectBounding.top      = min(m_rectBounding.top, pt.y);
  301.         m_rectBounding.bottom   = max(m_rectBounding.bottom, pt.y);
  302.     }
  303.  
  304.     // Add the pen width to the bounding rectangle.  This is necessary
  305.     // to account for the width of the stroke when invalidating
  306.     // the screen.
  307.     m_rectBounding.InflateRect(CSize(m_nPenWidth, m_nPenWidth));
  308.     return;
  309. }
  310.  
  311.  
  312.