home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / bindscrb / scribvw.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  10.5 KB  |  370 lines

  1. // scribvw.cpp : implementation of the CScribView class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 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 related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "scribble.h"
  15.  
  16. #include "scribdoc.h"
  17. #include "scribvw.h"
  18.  
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char BASED_CODE THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CScribView
  26.  
  27. IMPLEMENT_DYNCREATE(CScribView, CScrollView)
  28.  
  29. BEGIN_MESSAGE_MAP(CScribView, CScrollView)
  30.     //{{AFX_MSG_MAP(CScribView)
  31.     ON_WM_LBUTTONDOWN()
  32.     ON_WM_LBUTTONUP()
  33.     ON_WM_MOUSEMOVE()
  34.     ON_WM_SIZE()
  35.     //}}AFX_MSG_MAP
  36.  
  37.     // Standard printing commands
  38.     ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
  39.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
  40. END_MESSAGE_MAP()
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CScribView construction/destruction
  44.  
  45. CScribView::CScribView()
  46. {
  47.     SetScrollSizes(MM_TEXT, CSize(0, 0));
  48. }
  49.  
  50. CScribView::~CScribView()
  51. {
  52. }
  53.  
  54.  
  55.  
  56. /////////////////////////////////////////////////////////////////////////////
  57. // CScribView drawing
  58.  
  59. void CScribView::OnDraw(CDC* pDC)
  60. {
  61.     CScribDoc* pDoc = GetDocument();
  62.     ASSERT_VALID(pDoc);
  63.  
  64.  
  65.     // Get the invalidated rectangle of the view, or in the case
  66.     // of printing, the clipping region of the printer dc.
  67.     CRect rectClip;
  68.     CRect rectStroke;
  69.     pDC->GetClipBox(&rectClip);
  70.     pDC->LPtoDP(&rectClip);
  71.     rectClip.InflateRect(1, 1); // avoid rounding to nothing
  72.  
  73.     // Note: CScrollView::OnPaint() will have already adjusted the
  74.     // viewport origin before calling OnDraw(), to reflect the
  75.     // currently scrolled position.
  76.  
  77.     // The view delegates the drawing of individual strokes to
  78.     // CStroke::DrawStroke().
  79.     CTypedPtrList<CObList,CStroke*>& strokeList = pDoc->m_strokeList;
  80.     POSITION pos = strokeList.GetHeadPosition();
  81.     while (pos != NULL)
  82.     {
  83.         CStroke* pStroke = strokeList.GetNext(pos);
  84.         rectStroke = pStroke->GetBoundingRect();
  85.         pDC->LPtoDP(&rectStroke);
  86.         rectStroke.InflateRect(1, 1); // avoid rounding to nothing
  87.         if (!rectStroke.IntersectRect(&rectStroke, &rectClip))
  88.             continue;
  89.         pStroke->DrawStroke(pDC);
  90.     }
  91. }
  92.  
  93. /////////////////////////////////////////////////////////////////////////////
  94. // CScribView printing
  95.  
  96. BOOL CScribView::OnPreparePrinting(CPrintInfo* pInfo)
  97. {
  98.     pInfo->SetMaxPage(2);   // the document is two pages long:
  99.                             // the first page is the title page
  100.                             // the second is the drawing
  101.     BOOL bRet = DoPreparePrinting(pInfo);   // default preparation
  102.     pInfo->m_nNumPreviewPages = 2;  // Preview 2 pages at a time
  103.     // Set this value after calling DoPreparePrinting to override
  104.     // value read from .INI file
  105.     return bRet;
  106. }
  107.  
  108. void CScribView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  109. {
  110.     // TODO: add extra initialization before printing
  111. }
  112.  
  113. void CScribView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  114. {
  115.     // TODO: add cleanup after printing
  116. }
  117.  
  118.  
  119. /////////////////////////////////////////////////////////////////////////////
  120. // CScribView diagnostics
  121.  
  122. #ifdef _DEBUG
  123. void CScribView::AssertValid() const
  124. {
  125.     CScrollView::AssertValid();
  126. }
  127.  
  128. void CScribView::Dump(CDumpContext& dc) const
  129. {
  130.     CScrollView::Dump(dc);
  131. }
  132.  
  133. CScribDoc* CScribView::GetDocument() // non-debug version is inline
  134. {
  135.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CScribDoc)));
  136.     return (CScribDoc*) m_pDocument;
  137. }
  138.  
  139. #endif //_DEBUG
  140.  
  141. /////////////////////////////////////////////////////////////////////////////
  142. // CScribView message handlers
  143.  
  144. void CScribView::OnLButtonDown(UINT, CPoint point)
  145. {
  146.     // When the user presses the mouse button, she may be
  147.     // starting a new stroke, or selecting or de-selecting a stroke.
  148.  
  149.     // CScrollView changes the viewport origin and mapping mode.
  150.     // It's necessary to convert the point from device coordinates
  151.     // to logical coordinates, such as are stored in the document.
  152.     CClientDC dc(this);
  153.     OnPrepareDC(&dc);
  154.     dc.DPtoLP(&point);
  155.  
  156.     m_pStrokeCur = GetDocument()->NewStroke();
  157.     // Add first point to the new stroke
  158.     m_pStrokeCur->m_pointArray.Add(point);
  159.  
  160.     SetCapture();       // Capture the mouse until button up.
  161.     m_ptPrev = point;   // Serves as the MoveTo() anchor point for the
  162.                         // LineTo() the next point, as the user drags the
  163.                         // mouse.
  164.  
  165.     return;
  166.  
  167. }
  168.  
  169.  
  170. void CScribView::OnLButtonUp(UINT, CPoint point)
  171. {
  172.     // Mouse button up is interesting in the Scribble application
  173.     // only if the user is currently drawing a new stroke by dragging
  174.     // the captured mouse.
  175.  
  176.     if (GetCapture() != this)
  177.         return; // If this window (view) didn't capture the mouse,
  178.                 // then the user isn't drawing in this window.
  179.  
  180.     CScribDoc* pDoc = GetDocument();
  181.  
  182.     CClientDC dc(this);
  183.  
  184.     // CScrollView changes the viewport origin and mapping mode.
  185.     // It's necessary to convert the point from device coordinates
  186.     // to logical coordinates, such as are stored in the document.
  187.     OnPrepareDC(&dc);  // set up mapping mode and viewport origin
  188.     dc.DPtoLP(&point);
  189.  
  190.     CPen* pOldPen = dc.SelectObject(pDoc->GetCurrentPen());
  191.     dc.MoveTo(m_ptPrev);
  192.     dc.LineTo(point);
  193.     dc.SelectObject(pOldPen);
  194.     m_pStrokeCur->m_pointArray.Add(point);
  195.  
  196.     // Tell the stroke item that we're done adding points to it.
  197.     // This is so it can finish computing its bounding rectangle.
  198.     m_pStrokeCur->FinishStroke();
  199.  
  200.     // Tell the other views that this stroke has been added
  201.     // so that they can invalidate this stroke's area in their
  202.     // client area.
  203.     pDoc->UpdateAllViews(this, 0L, m_pStrokeCur);
  204.  
  205.     ReleaseCapture();   // Release the mouse capture established at
  206.                         // the beginning of the mouse drag.
  207.     pDoc->NotifyChanged();
  208.     return;
  209. }
  210.  
  211.  
  212. void CScribView::OnMouseMove(UINT, CPoint point)
  213. {
  214.     // Mouse movement is interesting in the Scribble application
  215.     // only if the user is currently drawing a new stroke by dragging
  216.     // the captured mouse.
  217.  
  218.     if (GetCapture() != this)
  219.         return; // If this window (view) didn't capture the mouse,
  220.                 // then the user isn't drawing in this window.
  221.  
  222.     CClientDC dc(this);
  223.     // CScrollView changes the viewport origin and mapping mode.
  224.     // It's necessary to convert the point from device coordinates
  225.     // to logical coordinates, such as are stored in the document.
  226.     OnPrepareDC(&dc);
  227.     dc.DPtoLP(&point);
  228.  
  229.     m_pStrokeCur->m_pointArray.Add(point);
  230.  
  231.     // Draw a line from the previous detected point in the mouse
  232.     // drag to the current point.
  233.     CPen* pOldPen = dc.SelectObject(GetDocument()->GetCurrentPen());
  234.     dc.MoveTo(m_ptPrev);
  235.     dc.LineTo(point);
  236.     dc.SelectObject(pOldPen);
  237.     m_ptPrev = point;
  238.     return;
  239. }
  240.  
  241. void CScribView::OnUpdate(CView* /* pSender */, LPARAM /* lHint */,
  242.     CObject* pHint)
  243. {
  244.     // The document has informed this view that some data has changed.
  245.  
  246.     if (pHint != NULL)
  247.     {
  248.         if (pHint->IsKindOf(RUNTIME_CLASS(CStroke)))
  249.         {
  250.             // The hint is that a stroke as been added (or changed).
  251.             // So, invalidate its rectangle.
  252.             CStroke* pStroke = (CStroke*)pHint;
  253.             CClientDC dc(this);
  254.             OnPrepareDC(&dc);
  255.             CRect rectInvalid = pStroke->GetBoundingRect();
  256.             dc.LPtoDP(&rectInvalid);
  257.             InvalidateRect(&rectInvalid);
  258.             return;
  259.         }
  260.     }
  261.     // We can't interpret the hint, so assume that anything might
  262.     // have been updated.
  263.     Invalidate(TRUE);
  264.     return;
  265. }
  266.  
  267. void CScribView::OnInitialUpdate()
  268. {
  269.     SetScrollInfo();
  270.     CScrollView::OnInitialUpdate();
  271. }
  272.  
  273. void CScribView::SetScrollInfo()
  274. {
  275.     CClientDC dc(NULL);
  276.     OnPrepareDC(&dc);
  277.     CSize sizeDoc = GetDocument()->GetDocSize();
  278.     dc.LPtoDP(&sizeDoc);
  279.     SetScrollSizes(MM_TEXT, sizeDoc);
  280. }
  281.  
  282. void CScribView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
  283. {
  284.     if (pInfo->m_nCurPage == 1)  // page no. 1 is the title page
  285.     {
  286.         PrintTitlePage(pDC, pInfo);
  287.         return; // nothing else to print on page 1 but the page title
  288.     }
  289.     CString strHeader = GetDocument()->GetTitle();
  290.  
  291.     PrintPageHeader(pDC, pInfo, strHeader);
  292.     // PrintPageHeader() subtracts out from the pInfo->m_rectDraw the
  293.     // amount of the page used for the header.
  294.  
  295.     pDC->SetWindowOrg(pInfo->m_rectDraw.left,-pInfo->m_rectDraw.top);
  296.  
  297.     // Now print the rest of the page
  298.     OnDraw(pDC);
  299. }
  300.  
  301. void CScribView::PrintTitlePage(CDC* pDC, CPrintInfo* pInfo)
  302. {
  303.     // Prepare a font size for displaying the file name
  304.     LOGFONT logFont;
  305.     memset(&logFont, 0, sizeof(LOGFONT));
  306.     logFont.lfHeight = 75;  //  3/4th inch high in MM_LOENGLISH
  307.                             // (1/100th inch)
  308.     CFont font;
  309.     CFont* pOldFont = NULL;
  310.     if (font.CreateFontIndirect(&logFont))
  311.         pOldFont = pDC->SelectObject(&font);
  312.  
  313.     // Get the file name, to be displayed on title page
  314.     CString strPageTitle = GetDocument()->GetTitle();
  315.  
  316.     // Display the file name 1 inch below top of the page,
  317.     // centered horizontally
  318.     pDC->SetTextAlign(TA_CENTER);
  319.     pDC->TextOut(pInfo->m_rectDraw.right/2, -100, strPageTitle);
  320.  
  321.     if (pOldFont != NULL)
  322.         pDC->SelectObject(pOldFont);
  323. }
  324.  
  325. void CScribView::PrintPageHeader(CDC* pDC, CPrintInfo* pInfo,
  326.     CString& strHeader)
  327. {
  328.     // Print a page header consisting of the name of
  329.     // the document and a horizontal line
  330.     pDC->TextOut(0,-25, strHeader);  // 1/4 inch down
  331.  
  332.     // Draw a line across the page, below the header
  333.     TEXTMETRIC textMetric;
  334.     pDC->GetTextMetrics(&textMetric);
  335.     int y = -35 - textMetric.tmHeight;          // line 1/10th inch below text
  336.     pDC->MoveTo(0, y);                          // from left margin
  337.     pDC->LineTo(pInfo->m_rectDraw.right, y);    // to right margin
  338.  
  339.     // Subtract out from the drawing rectange the space used by the header.
  340.     y -= 25;    // space 1/4 inch below (top of) line
  341.     pInfo->m_rectDraw.top += y;
  342. }
  343.  
  344. void CScribView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  345. {
  346.     CScribDoc* pDoc = GetDocument();
  347.     CScrollView::OnPrepareDC(pDC, pInfo);
  348.  
  349.     pDC->SetMapMode(MM_ANISOTROPIC);
  350.     CSize sizeDoc = pDoc->GetDocSize();
  351.     sizeDoc.cy = -sizeDoc.cy;
  352.     pDC->SetWindowExt(sizeDoc);
  353.  
  354.     // Binder objects don't scale
  355.  
  356.     int xLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSX);
  357.     int yLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSY);
  358.  
  359.     long xExt = (long)(sizeDoc.cx * xLogPixPerInch) / 100;
  360.     long yExt = (long)(sizeDoc.cy * yLogPixPerInch) / 100;
  361.  
  362.     pDC->SetViewportExt((int)xExt, (int)-yExt);
  363. }
  364.  
  365. void CScribView::OnSize(UINT nType, int cx, int cy)
  366. {
  367.     SetScrollInfo();    // ensure that scroll info is up-to-date
  368.     CScrollView::OnSize(nType, cx, cy);
  369. }
  370.