home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / drawcli / drawtool.cpp < prev    next >
C/C++ Source or Header  |  1998-03-26  |  11KB  |  468 lines

  1. // drawtool.cpp - implementation for drawing tools
  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.  
  14. #include "stdafx.h"
  15. #include "drawcli.h"
  16. #include "drawdoc.h"
  17. #include "drawvw.h"
  18. #include "drawobj.h"
  19. #include "drawtool.h"
  20.  
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CDrawTool implementation
  23.  
  24. CPtrList CDrawTool::c_tools;
  25.  
  26. static CSelectTool selectTool;
  27. static CRectTool lineTool(line);
  28. static CRectTool rectTool(rect);
  29. static CRectTool roundRectTool(roundRect);
  30. static CRectTool ellipseTool(ellipse);
  31. static CPolyTool polyTool;
  32.  
  33. CPoint CDrawTool::c_down;
  34. UINT CDrawTool::c_nDownFlags;
  35. CPoint CDrawTool::c_last;
  36. DrawShape CDrawTool::c_drawShape = selection;
  37.  
  38. CDrawTool::CDrawTool(DrawShape drawShape)
  39. {
  40.     m_drawShape = drawShape;
  41.     c_tools.AddTail(this);
  42. }
  43.  
  44. CDrawTool* CDrawTool::FindTool(DrawShape drawShape)
  45. {
  46.     POSITION pos = c_tools.GetHeadPosition();
  47.     while (pos != NULL)
  48.     {
  49.         CDrawTool* pTool = (CDrawTool*)c_tools.GetNext(pos);
  50.         if (pTool->m_drawShape == drawShape)
  51.             return pTool;
  52.     }
  53.  
  54.     return NULL;
  55. }
  56.  
  57. void CDrawTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  58. {
  59.     // deactivate any in-place active item on this view!
  60.     COleClientItem* pActiveItem = pView->GetDocument()->GetInPlaceActiveItem(pView);
  61.     if (pActiveItem != NULL)
  62.     {
  63.         pActiveItem->Close();
  64.         ASSERT(pView->GetDocument()->GetInPlaceActiveItem(pView) == NULL);
  65.     }
  66.  
  67.     pView->SetCapture();
  68.     c_nDownFlags = nFlags;
  69.     c_down = point;
  70.     c_last = point;
  71. }
  72.  
  73. void CDrawTool::OnLButtonDblClk(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& /*point*/)
  74. {
  75. }
  76.  
  77. void CDrawTool::OnLButtonUp(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& point)
  78. {
  79.     ReleaseCapture();
  80.  
  81.     if (point == c_down)
  82.         c_drawShape = selection;
  83. }
  84.  
  85. void CDrawTool::OnMouseMove(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& point)
  86. {
  87.     c_last = point;
  88.     SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  89. }
  90.  
  91. void CDrawTool::OnEditProperties(CDrawView* /*pView*/)
  92. {
  93. }
  94.  
  95. void CDrawTool::OnCancel()
  96. {
  97.     c_drawShape = selection;
  98. }
  99.  
  100. ////////////////////////////////////////////////////////////////////////////
  101. // CResizeTool
  102.  
  103. enum SelectMode
  104. {
  105.     none,
  106.     netSelect,
  107.     move,
  108.     size
  109. };
  110.  
  111. SelectMode selectMode = none;
  112. int nDragHandle;
  113.  
  114. CPoint lastPoint;
  115.  
  116. CSelectTool::CSelectTool()
  117.     : CDrawTool(selection)
  118. {
  119. }
  120.  
  121. void CSelectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  122. {
  123.     CPoint local = point;
  124.     pView->ClientToDoc(local);
  125.  
  126.     CDrawObj* pObj;
  127.     selectMode = none;
  128.  
  129.     // Check for resizing (only allowed on single selections)
  130.     if (pView->m_selection.GetCount() == 1)
  131.     {
  132.         pObj = pView->m_selection.GetHead();
  133.         nDragHandle = pObj->HitTest(local, pView, TRUE);
  134.         if (nDragHandle != 0)
  135.             selectMode = size;
  136.     }
  137.  
  138.     // See if the click was on an object, select and start move if so
  139.     if (selectMode == none)
  140.     {
  141.         pObj = pView->GetDocument()->ObjectAt(local);
  142.  
  143.         if (pObj != NULL)
  144.         {
  145.             selectMode = move;
  146.  
  147.             if (!pView->IsSelected(pObj))
  148.                 pView->Select(pObj, (nFlags & MK_SHIFT) != 0);
  149.  
  150.             // Ctrl+Click clones the selection...
  151.             if ((nFlags & MK_CONTROL) != 0)
  152.                 pView->CloneSelection();
  153.         }
  154.     }
  155.  
  156.     // Click on background, start a net-selection
  157.     if (selectMode == none)
  158.     {
  159.         if ((nFlags & MK_SHIFT) == 0)
  160.             pView->Select(NULL);
  161.  
  162.         selectMode = netSelect;
  163.  
  164.         CClientDC dc(pView);
  165.         CRect rect(point.x, point.y, point.x, point.y);
  166.         rect.NormalizeRect();
  167.         dc.DrawFocusRect(rect);
  168.     }
  169.  
  170.     lastPoint = local;
  171.     CDrawTool::OnLButtonDown(pView, nFlags, point);
  172. }
  173.  
  174. void CSelectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
  175. {
  176.     if ((nFlags & MK_SHIFT) != 0)
  177.     {
  178.         // Shift+DblClk deselects object...
  179.         CPoint local = point;
  180.         pView->ClientToDoc(local);
  181.         CDrawObj* pObj = pView->GetDocument()->ObjectAt(local);
  182.         if (pObj != NULL)
  183.             pView->Deselect(pObj);
  184.     }
  185.     else
  186.     {
  187.         // "Normal" DblClk opens properties, or OLE server...
  188.         if (pView->m_selection.GetCount() == 1)
  189.             pView->m_selection.GetHead()->OnOpen(pView);
  190.     }
  191.  
  192.     CDrawTool::OnLButtonDblClk(pView, nFlags, point);
  193. }
  194.  
  195. void CSelectTool::OnEditProperties(CDrawView* pView)
  196. {
  197.     if (pView->m_selection.GetCount() == 1)
  198.         pView->m_selection.GetHead()->OnEditProperties();
  199. }
  200.  
  201. void CSelectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
  202. {
  203.     if (pView->GetCapture() == pView)
  204.     {
  205.         if (selectMode == netSelect)
  206.         {
  207.             CClientDC dc(pView);
  208.             CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
  209.             rect.NormalizeRect();
  210.             dc.DrawFocusRect(rect);
  211.  
  212.             pView->SelectWithinRect(rect, TRUE);
  213.         }
  214.         else if (selectMode != none)
  215.         {
  216.             pView->GetDocument()->UpdateAllViews(pView);
  217.         }
  218.     }
  219.  
  220.     CDrawTool::OnLButtonUp(pView, nFlags, point);
  221. }
  222.  
  223. void CSelectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
  224. {
  225.     if (pView->GetCapture() != pView)
  226.     {
  227.         if (c_drawShape == selection && pView->m_selection.GetCount() == 1)
  228.         {
  229.             CDrawObj* pObj = pView->m_selection.GetHead();
  230.             CPoint local = point;
  231.             pView->ClientToDoc(local);
  232.             int nHandle = pObj->HitTest(local, pView, TRUE);
  233.             if (nHandle != 0)
  234.             {
  235.                 SetCursor(pObj->GetHandleCursor(nHandle));
  236.                 return; // bypass CDrawTool
  237.             }
  238.         }
  239.         if (c_drawShape == selection)
  240.             CDrawTool::OnMouseMove(pView, nFlags, point);
  241.         return;
  242.     }
  243.  
  244.     if (selectMode == netSelect)
  245.     {
  246.         CClientDC dc(pView);
  247.         CRect rect(c_down.x, c_down.y, c_last.x, c_last.y);
  248.         rect.NormalizeRect();
  249.         dc.DrawFocusRect(rect);
  250.         rect.SetRect(c_down.x, c_down.y, point.x, point.y);
  251.         rect.NormalizeRect();
  252.         dc.DrawFocusRect(rect);
  253.  
  254.         CDrawTool::OnMouseMove(pView, nFlags, point);
  255.         return;
  256.     }
  257.  
  258.     CPoint local = point;
  259.     pView->ClientToDoc(local);
  260.     CPoint delta = (CPoint)(local - lastPoint);
  261.  
  262.     POSITION pos = pView->m_selection.GetHeadPosition();
  263.     while (pos != NULL)
  264.     {
  265.         CDrawObj* pObj = pView->m_selection.GetNext(pos);
  266.         CRect position = pObj->m_position;
  267.  
  268.         if (selectMode == move)
  269.         {
  270.             position += delta;
  271.             pObj->MoveTo(position, pView);
  272.         }
  273.         else if (nDragHandle != 0)
  274.         {
  275.             pObj->MoveHandleTo(nDragHandle, local, pView);
  276.         }
  277.     }
  278.  
  279.     lastPoint = local;
  280.  
  281.     if (selectMode == size && c_drawShape == selection)
  282.     {
  283.         c_last = point;
  284.         SetCursor(pView->m_selection.GetHead()->GetHandleCursor(nDragHandle));
  285.         return; // bypass CDrawTool
  286.     }
  287.  
  288.     c_last = point;
  289.  
  290.     if (c_drawShape == selection)
  291.         CDrawTool::OnMouseMove(pView, nFlags, point);
  292. }
  293.  
  294. ////////////////////////////////////////////////////////////////////////////
  295. // CRectTool (does rectangles, round-rectangles, and ellipses)
  296.  
  297. CRectTool::CRectTool(DrawShape drawShape)
  298.     : CDrawTool(drawShape)
  299. {
  300. }
  301.  
  302. void CRectTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  303. {
  304.     CDrawTool::OnLButtonDown(pView, nFlags, point);
  305.  
  306.     CPoint local = point;
  307.     pView->ClientToDoc(local);
  308.  
  309.     CDrawRect* pObj = new CDrawRect(CRect(local, CSize(0, 0)));
  310.     switch (m_drawShape)
  311.     {
  312.     default:
  313.         ASSERT(FALSE); // unsuported shape!
  314.  
  315.     case rect:
  316.         pObj->m_nShape = CDrawRect::rectangle;
  317.         break;
  318.  
  319.     case roundRect:
  320.         pObj->m_nShape = CDrawRect::roundRectangle;
  321.         break;
  322.  
  323.     case ellipse:
  324.         pObj->m_nShape = CDrawRect::ellipse;
  325.         break;
  326.  
  327.     case line:
  328.         pObj->m_nShape = CDrawRect::line;
  329.         break;
  330.     }
  331.     pView->GetDocument()->Add(pObj);
  332.     pView->Select(pObj);
  333.  
  334.     selectMode = size;
  335.     nDragHandle = 1;
  336.     lastPoint = local;
  337. }
  338.  
  339. void CRectTool::OnLButtonDblClk(CDrawView* pView, UINT nFlags, const CPoint& point)
  340. {
  341.     CDrawTool::OnLButtonDblClk(pView, nFlags, point);
  342. }
  343.  
  344. void CRectTool::OnLButtonUp(CDrawView* pView, UINT nFlags, const CPoint& point)
  345. {
  346.     if (point == c_down)
  347.     {
  348.         // Don't create empty objects...
  349.         CDrawObj *pObj = pView->m_selection.GetTail();
  350.         pView->GetDocument()->Remove(pObj);
  351.         pObj->Remove();
  352.         selectTool.OnLButtonDown(pView, nFlags, point); // try a select!
  353.     }
  354.  
  355.     selectTool.OnLButtonUp(pView, nFlags, point);
  356. }
  357.  
  358. void CRectTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
  359. {
  360.     SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
  361.     selectTool.OnMouseMove(pView, nFlags, point);
  362. }
  363.  
  364.  
  365. ////////////////////////////////////////////////////////////////////////////
  366. // CPolyTool
  367.  
  368. CPolyTool::CPolyTool()
  369.     : CDrawTool(poly)
  370. {
  371.     m_pDrawObj = NULL;
  372. }
  373.  
  374. void CPolyTool::OnLButtonDown(CDrawView* pView, UINT nFlags, const CPoint& point)
  375. {
  376.     CDrawTool::OnLButtonDown(pView, nFlags, point);
  377.  
  378.     CPoint local = point;
  379.     pView->ClientToDoc(local);
  380.  
  381.     if (m_pDrawObj == NULL)
  382.     {
  383.         pView->SetCapture();
  384.  
  385.         m_pDrawObj = new CDrawPoly(CRect(local, CSize(0, 0)));
  386.         pView->GetDocument()->Add(m_pDrawObj);
  387.         pView->Select(m_pDrawObj);
  388.         m_pDrawObj->AddPoint(local, pView);
  389.     }
  390.     else if (local == m_pDrawObj->m_points[0])
  391.     {
  392.         // Stop when the first point is repeated...
  393.         ReleaseCapture();
  394.         m_pDrawObj->m_nPoints -= 1;
  395.         if (m_pDrawObj->m_nPoints < 2)
  396.         {
  397.             m_pDrawObj->Remove();
  398.         }
  399.         else
  400.         {
  401.             pView->InvalObj(m_pDrawObj);
  402.         }
  403.         m_pDrawObj = NULL;
  404.         c_drawShape = selection;
  405.         return;
  406.     }
  407.  
  408.     local.x += 1; // adjacent points can't be the same!
  409.     m_pDrawObj->AddPoint(local, pView);
  410.  
  411.     selectMode = size;
  412.     nDragHandle = m_pDrawObj->GetHandleCount();
  413.     lastPoint = local;
  414. }
  415.  
  416. void CPolyTool::OnLButtonUp(CDrawView* /*pView*/, UINT /*nFlags*/, const CPoint& /*point*/)
  417. {
  418.     // Don't release capture yet!
  419. }
  420.  
  421. void CPolyTool::OnMouseMove(CDrawView* pView, UINT nFlags, const CPoint& point)
  422. {
  423.     if (m_pDrawObj != NULL && (nFlags & MK_LBUTTON) != 0)
  424.     {
  425.         CPoint local = point;
  426.         pView->ClientToDoc(local);
  427.         m_pDrawObj->AddPoint(local);
  428.         nDragHandle = m_pDrawObj->GetHandleCount();
  429.         lastPoint = local;
  430.         c_last = point;
  431.         SetCursor(AfxGetApp()->LoadCursor(IDC_PENCIL));
  432.     }
  433.     else
  434.     {
  435.         SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS));
  436.         selectTool.OnMouseMove(pView, nFlags, point);
  437.     }
  438. }
  439.  
  440. void CPolyTool::OnLButtonDblClk(CDrawView* pView, UINT , const CPoint& )
  441. {
  442.     ReleaseCapture();
  443.  
  444.     int nPoints = m_pDrawObj->m_nPoints;
  445.     if (nPoints > 2 &&
  446.         (m_pDrawObj->m_points[nPoints - 1] == m_pDrawObj->m_points[nPoints - 2] ||
  447.         m_pDrawObj->m_points[nPoints - 1].x - 1 == m_pDrawObj->m_points[nPoints - 2].x &&
  448.         m_pDrawObj->m_points[nPoints - 1].y == m_pDrawObj->m_points[nPoints - 2].y))
  449.  
  450.     {
  451.         // Nuke the last point if it's the same as the next to last...
  452.         m_pDrawObj->m_nPoints -= 1;
  453.         pView->InvalObj(m_pDrawObj);
  454.     }
  455.  
  456.     m_pDrawObj = NULL;
  457.     c_drawShape = selection;
  458. }
  459.  
  460. void CPolyTool::OnCancel()
  461. {
  462.     CDrawTool::OnCancel();
  463.  
  464.     m_pDrawObj = NULL;
  465. }
  466.  
  467. /////////////////////////////////////////////////////////////////////////////
  468.