home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / DRAWCL.PAK / DRAWVW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  31.9 KB  |  1,317 lines

  1. // drawvw.cpp : implementation of the CDrawView class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 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 <afxpriv.h>
  16.  
  17. #include "drawcli.h"
  18.  
  19. #include "drawdoc.h"
  20. #include "drawobj.h"
  21. #include "cntritem.h"
  22. #include "drawvw.h"
  23.  
  24. #include "drawobj.h"
  25. #include "drawtool.h"
  26. #include "mainfrm.h"
  27.  
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char BASED_CODE THIS_FILE[] = __FILE__;
  31. #endif
  32.  
  33. // private clipboard format (list of Draw objects)
  34. CLIPFORMAT CDrawView::m_cfDraw = (CLIPFORMAT)
  35. #ifdef _MAC
  36.     ::RegisterClipboardFormat(_T("DCLI"));
  37. #else
  38.     ::RegisterClipboardFormat(_T("MFC Draw Sample"));
  39. #endif
  40. CLIPFORMAT CDrawView::m_cfObjectDescriptor = NULL;
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CDrawView
  44.  
  45. IMPLEMENT_DYNCREATE(CDrawView, CScrollView)
  46.  
  47. BEGIN_MESSAGE_MAP(CDrawView, CScrollView)
  48.     //{{AFX_MSG_MAP(CDrawView)
  49.     ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject)
  50.     ON_COMMAND(ID_CANCEL_EDIT, OnCancelEdit)
  51.     ON_WM_LBUTTONDOWN()
  52.     ON_WM_LBUTTONUP()
  53.     ON_WM_MOUSEMOVE()
  54.     ON_WM_LBUTTONDBLCLK()
  55.     ON_COMMAND(ID_DRAW_SELECT, OnDrawSelect)
  56.     ON_COMMAND(ID_DRAW_ROUNDRECT, OnDrawRoundRect)
  57.     ON_COMMAND(ID_DRAW_RECT, OnDrawRect)
  58.     ON_COMMAND(ID_DRAW_LINE, OnDrawLine)
  59.     ON_COMMAND(ID_DRAW_ELLIPSE, OnDrawEllipse)
  60.     ON_UPDATE_COMMAND_UI(ID_DRAW_ELLIPSE, OnUpdateDrawEllipse)
  61.     ON_UPDATE_COMMAND_UI(ID_DRAW_LINE, OnUpdateDrawLine)
  62.     ON_UPDATE_COMMAND_UI(ID_DRAW_RECT, OnUpdateDrawRect)
  63.     ON_UPDATE_COMMAND_UI(ID_DRAW_ROUNDRECT, OnUpdateDrawRoundRect)
  64.     ON_UPDATE_COMMAND_UI(ID_DRAW_SELECT, OnUpdateDrawSelect)
  65.     ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVEBACK, OnUpdateSingleSelect)
  66.     ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
  67.     ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
  68.     ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateAnySelect)
  69.     ON_COMMAND(ID_DRAW_POLYGON, OnDrawPolygon)
  70.     ON_UPDATE_COMMAND_UI(ID_DRAW_POLYGON, OnUpdateDrawPolygon)
  71.     ON_WM_SIZE()
  72.     ON_COMMAND(ID_VIEW_GRID, OnViewGrid)
  73.     ON_UPDATE_COMMAND_UI(ID_VIEW_GRID, OnUpdateViewGrid)
  74.     ON_WM_ERASEBKGND()
  75.     ON_COMMAND(ID_OBJECT_FILLCOLOR, OnObjectFillColor)
  76.     ON_COMMAND(ID_OBJECT_LINECOLOR, OnObjectLineColor)
  77.     ON_COMMAND(ID_OBJECT_MOVEBACK, OnObjectMoveBack)
  78.     ON_COMMAND(ID_OBJECT_MOVEFORWARD, OnObjectMoveForward)
  79.     ON_COMMAND(ID_OBJECT_MOVETOBACK, OnObjectMoveToBack)
  80.     ON_COMMAND(ID_OBJECT_MOVETOFRONT, OnObjectMoveToFront)
  81.     ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  82.     ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
  83.     ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  84.     ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
  85.     ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  86.     ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
  87.     ON_WM_SETFOCUS()
  88.     ON_COMMAND(ID_VIEW_SHOWOBJECTS, OnViewShowObjects)
  89.     ON_UPDATE_COMMAND_UI(ID_VIEW_SHOWOBJECTS, OnUpdateViewShowObjects)
  90.     ON_COMMAND(ID_EDIT_PROPERTIES, OnEditProperties)
  91.     ON_UPDATE_COMMAND_UI(ID_EDIT_PROPERTIES, OnUpdateEditProperties)
  92.     ON_WM_DESTROY()
  93.     ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll)
  94.     ON_WM_CREATE()
  95.     ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVEFORWARD, OnUpdateSingleSelect)
  96.     ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVETOBACK, OnUpdateSingleSelect)
  97.     ON_UPDATE_COMMAND_UI(ID_OBJECT_MOVETOFRONT, OnUpdateSingleSelect)
  98.     ON_WM_CONTEXTMENU()
  99.     //}}AFX_MSG_MAP
  100.     // Standard printing commands
  101.     ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
  102.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
  103. END_MESSAGE_MAP()
  104.  
  105. /////////////////////////////////////////////////////////////////////////////
  106. // CDrawView construction/destruction
  107.  
  108. CDrawView::CDrawView()
  109. {
  110.     m_bGrid = TRUE;
  111.     m_gridColor = RGB(0, 0, 128);
  112.     m_bActive = FALSE;
  113. // new
  114.     if( m_cfObjectDescriptor == NULL )
  115.         m_cfObjectDescriptor = (CLIPFORMAT)::RegisterClipboardFormat(_T("Object Descriptor") );
  116.     m_prevDropEffect = DROPEFFECT_NONE;
  117. // end new
  118. }
  119.  
  120. CDrawView::~CDrawView()
  121. {
  122. }
  123.  
  124. BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs)
  125. {
  126.     ASSERT(cs.style & WS_CHILD);
  127.     if (cs.lpszClass == NULL)
  128.         cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS);
  129.     return TRUE;
  130. }
  131.  
  132. void CDrawView::OnActivateView(BOOL bActivate, CView* pActiveView,
  133.     CView* pDeactiveView)
  134. {
  135.     CView::OnActivateView(bActivate, pActiveView, pDeactiveView);
  136.  
  137.     // invalidate selections when active status changes
  138.     if (m_bActive != bActivate)
  139.     {
  140.         if (bActivate)  // if becoming active update as if active
  141.             m_bActive = bActivate;
  142.         if (!m_selection.IsEmpty())
  143.             OnUpdate(NULL, HINT_UPDATE_SELECTION, NULL);
  144.         m_bActive = bActivate;
  145.     }
  146. }
  147.  
  148. /////////////////////////////////////////////////////////////////////////////
  149. // CDrawView drawing
  150.  
  151. void CDrawView::InvalObj(CDrawObj* pObj)
  152. {
  153.     CRect rect = pObj->m_position;
  154.     DocToClient(rect);
  155.     if (m_bActive && IsSelected(pObj))
  156.     {
  157.         rect.left -= 4;
  158.         rect.top -= 5;
  159.         rect.right += 5;
  160.         rect.bottom += 4;
  161.     }
  162.     rect.InflateRect(1, 1); // handles CDrawOleObj objects
  163.  
  164.     InvalidateRect(rect, FALSE);
  165. }
  166.  
  167. void CDrawView::OnUpdate(CView* , LPARAM lHint, CObject* pHint)
  168. {
  169.     switch (lHint)
  170.     {
  171.     case HINT_UPDATE_WINDOW:    // redraw entire window
  172.         Invalidate(FALSE);
  173.         break;
  174.  
  175.     case HINT_UPDATE_DRAWOBJ:   // a single object has changed
  176.         InvalObj((CDrawObj*)pHint);
  177.         break;
  178.  
  179.     case HINT_UPDATE_SELECTION: // an entire selection has changed
  180.         {
  181.             CDrawObjList* pList = pHint != NULL ?
  182.                 (CDrawObjList*)pHint : &m_selection;
  183.             POSITION pos = pList->GetHeadPosition();
  184.             while (pos != NULL)
  185.                 InvalObj(pList->GetNext(pos));
  186.         }
  187.         break;
  188.  
  189.     case HINT_DELETE_SELECTION: // an entire selection has been removed
  190.         if (pHint != &m_selection)
  191.         {
  192.             CDrawObjList* pList = (CDrawObjList*)pHint;
  193.             POSITION pos = pList->GetHeadPosition();
  194.             while (pos != NULL)
  195.             {
  196.                 CDrawObj* pObj = pList->GetNext(pos);
  197.                 InvalObj(pObj);
  198.                 Remove(pObj);   // remove it from this view's selection
  199.             }
  200.         }
  201.         break;
  202.  
  203.     case HINT_UPDATE_OLE_ITEMS:
  204.         {
  205.             CDrawDoc* pDoc = GetDocument();
  206.             POSITION pos = pDoc->GetObjects()->GetHeadPosition();
  207.             while (pos != NULL)
  208.             {
  209.                 CDrawObj* pObj = pDoc->GetObjects()->GetNext(pos);
  210.                 if (pObj->IsKindOf(RUNTIME_CLASS(CDrawOleObj)))
  211.                     InvalObj(pObj);
  212.             }
  213.         }
  214.         break;
  215.  
  216.     default:
  217.         ASSERT(FALSE);
  218.         break;
  219.     }
  220. }
  221.  
  222. void CDrawView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  223. {
  224.     CScrollView::OnPrepareDC(pDC, pInfo);
  225.  
  226.     // mapping mode is MM_ANISOTROPIC
  227.     // these extents setup a mode similar to MM_LOENGLISH
  228.     // MM_LOENGLISH is in .01 physical inches
  229.     // these extents provide .01 logical inches
  230.  
  231.     pDC->SetMapMode(MM_ANISOTROPIC);
  232.     pDC->SetViewportExt(pDC->GetDeviceCaps(LOGPIXELSX),
  233.         pDC->GetDeviceCaps(LOGPIXELSY));
  234.     pDC->SetWindowExt(100, -100);
  235.  
  236.     // set the origin of the coordinate system to the center of the page
  237.     CPoint ptOrg;
  238.     ptOrg.x = GetDocument()->GetSize().cx / 2;
  239.     ptOrg.y = GetDocument()->GetSize().cy / 2;
  240.  
  241.     // ptOrg is in logical coordinates
  242.     pDC->OffsetWindowOrg(-ptOrg.x,ptOrg.y);
  243. }
  244.  
  245. BOOL CDrawView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll)
  246. {
  247.     // do the scroll
  248.     if (!CScrollView::OnScrollBy(sizeScroll, bDoScroll))
  249.         return FALSE;
  250.  
  251.     // update the position of any in-place active item
  252.     if (bDoScroll)
  253.     {
  254.         UpdateActiveItem();
  255.         UpdateWindow();
  256.     }
  257.     return TRUE;
  258. }
  259.  
  260. void CDrawView::OnDraw(CDC* pDC)
  261. {
  262.     CDrawDoc* pDoc = GetDocument();
  263.     ASSERT_VALID(pDoc);
  264.  
  265.     CDC dc;
  266.     CDC* pDrawDC = pDC;
  267.     CBitmap bitmap;
  268.     CBitmap* pOldBitmap;
  269.  
  270.     // only paint the rect that needs repainting
  271.     CRect client;
  272.     pDC->GetClipBox(client);
  273.     CRect rect = client;
  274.     DocToClient(rect);
  275.  
  276.     if (!pDC->IsPrinting())
  277.     {
  278.         // draw to offscreen bitmap for fast looking repaints
  279.         if (dc.CreateCompatibleDC(pDC))
  280.         {
  281.             if (bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()))
  282.             {
  283.                 OnPrepareDC(&dc, NULL);
  284.                 pDrawDC = &dc;
  285.  
  286.                 // offset origin more because bitmap is just piece of the whole drawing
  287.                 dc.OffsetViewportOrg(-rect.left, -rect.top);
  288.                 pOldBitmap = dc.SelectObject(&bitmap);
  289.                 dc.SetBrushOrg(rect.left % 8, rect.top % 8);
  290.  
  291.                 // might as well clip to the same rectangle
  292.                 dc.IntersectClipRect(client);
  293.             }
  294.         }
  295.     }
  296.  
  297.     // paint background
  298.     CBrush brush;
  299.     if (!brush.CreateSolidBrush(pDoc->GetPaperColor()))
  300.         return;
  301.  
  302.     brush.UnrealizeObject();
  303.     pDrawDC->FillRect(client, &brush);
  304.  
  305.     if (!pDC->IsPrinting() && m_bGrid)
  306.         DrawGrid(pDrawDC);
  307.  
  308.     pDoc->Draw(pDrawDC, this);
  309.  
  310.     if (pDrawDC != pDC)
  311.     {
  312.         pDC->SetViewportOrg(0, 0);
  313.         pDC->SetWindowOrg(0,0);
  314.         pDC->SetMapMode(MM_TEXT);
  315.         dc.SetViewportOrg(0, 0);
  316.         dc.SetWindowOrg(0,0);
  317.         dc.SetMapMode(MM_TEXT);
  318.         pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
  319.             &dc, 0, 0, SRCCOPY);
  320.         dc.SelectObject(pOldBitmap);
  321.     }
  322. }
  323.  
  324. void CDrawView::Remove(CDrawObj* pObj)
  325. {
  326.     POSITION pos = m_selection.Find(pObj);
  327.     if (pos != NULL)
  328.         m_selection.RemoveAt(pos);
  329. }
  330.  
  331. void CDrawView::PasteNative(COleDataObject& dataObject)
  332. {
  333.     // get file refering to clipboard data
  334.     CFile* pFile = dataObject.GetFileData(m_cfDraw);
  335.     if (pFile == NULL)
  336.         return;
  337.  
  338.     // connect the file to the archive
  339.     CArchive ar(pFile, CArchive::load);
  340.     TRY
  341.     {
  342.         ar.m_pDocument = GetDocument(); // set back-pointer in archive
  343.  
  344.         // read the selection
  345.         m_selection.Serialize(ar);
  346.     }
  347.     CATCH_ALL(e)
  348.     {
  349.         ar.Close();
  350.         delete pFile;
  351.         THROW_LAST();
  352.     }
  353.     END_CATCH_ALL
  354.  
  355.     ar.Close();
  356.     delete pFile;
  357. }
  358.  
  359. void CDrawView::PasteEmbedded(COleDataObject& dataObject, CPoint point )
  360. {
  361.     BeginWaitCursor();
  362.  
  363.     // paste embedded
  364.     CDrawOleObj* pObj = new CDrawOleObj(GetInitialPosition());
  365.     ASSERT_VALID(pObj);
  366.     CDrawItem* pItem = new CDrawItem(GetDocument(), pObj);
  367.     ASSERT_VALID(pItem);
  368.     pObj->m_pClientItem = pItem;
  369.  
  370.     TRY
  371.     {
  372.         if (!pItem->CreateFromData(&dataObject) &&
  373.             !pItem->CreateStaticFromData(&dataObject))
  374.         {
  375.             AfxThrowMemoryException();      // any exception will do
  376.         }
  377.  
  378.         // add the object to the document
  379.         GetDocument()->Add(pObj);
  380.         m_selection.AddTail(pObj);
  381.         ClientToDoc( point );
  382.         pObj->MoveTo( CRect( point, pObj->m_extent ), this );
  383.  
  384.         // try to get initial presentation data
  385.         pItem->UpdateLink();
  386.         pItem->UpdateExtent();
  387.     }
  388.     CATCH_ALL(e)
  389.     {
  390.         // clean up item
  391.         pItem->Delete();
  392.         pObj->m_pClientItem = NULL;
  393.         GetDocument()->Remove(pObj);
  394.         pObj->Remove();
  395.  
  396.         AfxMessageBox(IDP_FAILED_TO_CREATE);
  397.     }
  398.     END_CATCH_ALL
  399.  
  400.     EndWaitCursor();
  401. }
  402.  
  403. void CDrawView::DrawGrid(CDC* pDC)
  404. {
  405.     CDrawDoc* pDoc = GetDocument();
  406.  
  407.     COLORREF oldBkColor = pDC->SetBkColor(pDoc->GetPaperColor());
  408.  
  409.     CRect rect;
  410.     rect.left = -pDoc->GetSize().cx / 2;
  411.     rect.top = -pDoc->GetSize().cy / 2;
  412.     rect.right = rect.left + pDoc->GetSize().cx;
  413.     rect.bottom = rect.top + pDoc->GetSize().cy;
  414.  
  415.     // Center lines
  416.     CPen penDash;
  417.     penDash.CreatePen(PS_DASH, 1, m_gridColor);
  418.     CPen* pOldPen = pDC->SelectObject(&penDash);
  419.  
  420.     pDC->MoveTo(0, rect.top);
  421.     pDC->LineTo(0, rect.bottom);
  422.     pDC->MoveTo(rect.left, 0);
  423.     pDC->LineTo(rect.right, 0);
  424.  
  425.     // Major unit lines
  426.     CPen penDot;
  427.     penDot.CreatePen(PS_DOT, 1, m_gridColor);
  428.     pDC->SelectObject(&penDot);
  429.  
  430.     for (int x = rect.left / 100 * 100; x < rect.right; x += 100)
  431.     {
  432.         if (x != 0)
  433.         {
  434.             pDC->MoveTo(x, rect.top);
  435.             pDC->LineTo(x, rect.bottom);
  436.         }
  437.     }
  438.  
  439.     for (int y = rect.top / 100 * 100; y < rect.bottom; y += 100)
  440.     {
  441.         if (y != 0)
  442.         {
  443.             pDC->MoveTo(rect.left, y);
  444.             pDC->LineTo(rect.right, y);
  445.         }
  446.     }
  447.  
  448.     // Outlines
  449.     CPen penSolid;
  450.     penSolid.CreatePen(PS_SOLID, 1, m_gridColor);
  451.     pDC->SelectObject(&penSolid);
  452.     pDC->MoveTo(rect.left, rect.top);
  453.     pDC->LineTo(rect.right, rect.top);
  454.     pDC->LineTo(rect.right, rect.bottom);
  455.     pDC->LineTo(rect.left, rect.bottom);
  456.     pDC->LineTo(rect.left, rect.top);
  457.  
  458.     pDC->SelectObject(pOldPen);
  459.     pDC->SetBkColor(oldBkColor);
  460. }
  461.  
  462. void CDrawView::OnInitialUpdate()
  463. {
  464.     CSize size = GetDocument()->GetSize();
  465.     CClientDC dc(NULL);
  466.     size.cx = MulDiv(size.cx, dc.GetDeviceCaps(LOGPIXELSX), 100);
  467.     size.cy = MulDiv(size.cy, dc.GetDeviceCaps(LOGPIXELSY), 100);
  468.     SetScrollSizes(MM_TEXT, size);
  469. }
  470.  
  471. void CDrawView::SetPageSize(CSize size)
  472. {
  473.     CClientDC dc(NULL);
  474.     size.cx = MulDiv(size.cx, dc.GetDeviceCaps(LOGPIXELSX), 100);
  475.     size.cy = MulDiv(size.cy, dc.GetDeviceCaps(LOGPIXELSY), 100);
  476.     SetScrollSizes(MM_TEXT, size);
  477.     GetDocument()->UpdateAllViews(NULL, HINT_UPDATE_WINDOW, NULL);
  478. }
  479.  
  480. /////////////////////////////////////////////////////////////////////////////
  481. // CDrawView printing
  482.  
  483. BOOL CDrawView::OnPreparePrinting(CPrintInfo* pInfo)
  484. {
  485.     // default preparation
  486.     return DoPreparePrinting(pInfo);
  487. }
  488.  
  489. void CDrawView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
  490. {
  491.     CScrollView::OnBeginPrinting(pDC,pInfo);
  492.  
  493.     // check page size -- user could have gone into print setup
  494.     // from print dialog and changed paper or orientation
  495.     GetDocument()->ComputePageSize();
  496. }
  497.  
  498. void CDrawView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  499. {
  500.     // TODO: add cleanup after printing
  501. }
  502.  
  503. /////////////////////////////////////////////////////////////////////////////
  504. // OLE Client support and commands
  505.  
  506. BOOL CDrawView::IsSelected(const CObject* pDocItem) const
  507. {
  508.     CDrawObj* pDrawObj = (CDrawObj*)pDocItem;
  509.     if (pDocItem->IsKindOf(RUNTIME_CLASS(CDrawItem)))
  510.         pDrawObj = ((CDrawItem*)pDocItem)->m_pDrawObj;
  511.     return m_selection.Find(pDrawObj) != NULL;
  512. }
  513.  
  514. void CDrawView::OnInsertObject()
  515. {
  516.     // Invoke the standard Insert Object dialog box to obtain information
  517.     //  for new CDrawItem object.
  518.     COleInsertDialog dlg;
  519.     if (dlg.DoModal() != IDOK)
  520.         return;
  521.  
  522.     BeginWaitCursor();
  523.  
  524.     // First create the C++ object
  525.     CDrawOleObj* pObj = new CDrawOleObj(GetInitialPosition());
  526.     ASSERT_VALID(pObj);
  527.     CDrawItem* pItem = new CDrawItem(GetDocument(), pObj);
  528.     ASSERT_VALID(pItem);
  529.     pObj->m_pClientItem = pItem;
  530.  
  531.     // Now create the OLE object/item
  532.     TRY
  533.     {
  534.         if (!dlg.CreateItem(pObj->m_pClientItem))
  535.             AfxThrowMemoryException();
  536.  
  537.         // add the object to the document
  538.         GetDocument()->Add(pObj);
  539.  
  540.         // try to get initial presentation data
  541.         pItem->UpdateLink();
  542.         pItem->UpdateExtent();
  543.  
  544.         // if insert new object -- initially show the object
  545.         if (dlg.GetSelectionType() == COleInsertDialog::createNewItem)
  546.             pItem->DoVerb(OLEIVERB_SHOW, this);
  547.     }
  548.     CATCH_ALL(e)
  549.     {
  550.         // clean up item
  551.         pItem->Delete();
  552.         pObj->m_pClientItem = NULL;
  553.         GetDocument()->Remove(pObj);
  554.         pObj->Remove();
  555.  
  556.         AfxMessageBox(IDP_FAILED_TO_CREATE);
  557.     }
  558.     END_CATCH_ALL
  559.  
  560.     EndWaitCursor();
  561. }
  562.  
  563. // The following command handler provides the standard keyboard
  564. //  user interface to cancel an in-place editing session.
  565. void CDrawView::OnCancelEdit()
  566. {
  567.     // deactivate any in-place active item on this view!
  568.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  569.     if (pActiveItem != NULL)
  570.     {
  571.         // if we found one, deactivate it
  572.         pActiveItem->Close();
  573.     }
  574.     ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  575.  
  576.     // escape also brings us back into select mode
  577.     ReleaseCapture();
  578.  
  579.     CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
  580.     if (pTool != NULL)
  581.         pTool->OnCancel();
  582.  
  583.     CDrawTool::c_drawShape = selection;
  584. }
  585.  
  586. void CDrawView::OnSetFocus(CWnd* pOldWnd)
  587. {
  588.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  589.     if (pActiveItem != NULL &&
  590.         pActiveItem->GetItemState() == COleClientItem::activeUIState)
  591.     {
  592.         // need to set focus to this item if it is in the same view
  593.         CWnd* pWnd = pActiveItem->GetInPlaceWindow();
  594.         if (pWnd != NULL)
  595.         {
  596.             pWnd->SetFocus();
  597.             return;
  598.         }
  599.     }
  600.  
  601.     CScrollView::OnSetFocus(pOldWnd);
  602. }
  603.  
  604. CRect CDrawView::GetInitialPosition()
  605. {
  606.     CRect rect(10, 10, 10, 10);
  607.     ClientToDoc(rect);
  608.     return rect;
  609. }
  610.  
  611. void CDrawView::ClientToDoc(CPoint& point)
  612. {
  613.     CClientDC dc(this);
  614.     OnPrepareDC(&dc, NULL);
  615.     dc.DPtoLP(&point);
  616. }
  617.  
  618. void CDrawView::ClientToDoc(CRect& rect)
  619. {
  620.     CClientDC dc(this);
  621.     OnPrepareDC(&dc, NULL);
  622.     dc.DPtoLP(rect);
  623.     ASSERT(rect.left <= rect.right);
  624.     ASSERT(rect.bottom <= rect.top);
  625. }
  626.  
  627. void CDrawView::DocToClient(CPoint& point)
  628. {
  629.     CClientDC dc(this);
  630.     OnPrepareDC(&dc, NULL);
  631.     dc.LPtoDP(&point);
  632. }
  633.  
  634. void CDrawView::DocToClient(CRect& rect)
  635. {
  636.     CClientDC dc(this);
  637.     OnPrepareDC(&dc, NULL);
  638.     dc.LPtoDP(rect);
  639.     rect.NormalizeRect();
  640. }
  641.  
  642. void CDrawView::Select(CDrawObj* pObj, BOOL bAdd)
  643. {
  644.     if (!bAdd)
  645.     {
  646.         OnUpdate(NULL, HINT_UPDATE_SELECTION, NULL);
  647.         m_selection.RemoveAll();
  648.     }
  649.  
  650.     if (pObj == NULL || IsSelected(pObj))
  651.         return;
  652.  
  653.     m_selection.AddTail(pObj);
  654.     InvalObj(pObj);
  655. }
  656.  
  657. // rect is in device coordinates
  658. void CDrawView::SelectWithinRect(CRect rect, BOOL bAdd)
  659. {
  660.     if (!bAdd)
  661.         Select(NULL);
  662.  
  663.     ClientToDoc(rect);
  664.  
  665.     CDrawObjList* pObList = GetDocument()->GetObjects();
  666.     POSITION posObj = pObList->GetHeadPosition();
  667.     while (posObj != NULL)
  668.     {
  669.         CDrawObj* pObj = pObList->GetNext(posObj);
  670.         if (pObj->Intersects(rect))
  671.             Select(pObj, TRUE);
  672.     }
  673. }
  674.  
  675. void CDrawView::Deselect(CDrawObj* pObj)
  676. {
  677.     POSITION pos = m_selection.Find(pObj);
  678.     if (pos != NULL)
  679.     {
  680.         InvalObj(pObj);
  681.         m_selection.RemoveAt(pos);
  682.     }
  683. }
  684.  
  685. void CDrawView::CloneSelection()
  686. {
  687.     POSITION pos = m_selection.GetHeadPosition();
  688.     while (pos != NULL)
  689.     {
  690.         CDrawObj* pObj = m_selection.GetNext(pos);
  691.         pObj->Clone(pObj->m_pDocument);
  692.             // copies object and adds it to the document
  693.     }
  694. }
  695.  
  696. void CDrawView::UpdateActiveItem()
  697. {
  698.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  699.     if (pActiveItem != NULL &&
  700.         pActiveItem->GetItemState() == COleClientItem::activeUIState)
  701.     {
  702.         // this will update the item rectangles by calling
  703.         //  OnGetPosRect & OnGetClipRect.
  704.         pActiveItem->SetItemRects();
  705.     }
  706. }
  707.  
  708. /////////////////////////////////////////////////////////////////////////////
  709. // CDrawView message handlers
  710.  
  711. void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
  712. {
  713.     if (!m_bActive)
  714.         return;
  715.     CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
  716.     if (pTool != NULL)
  717.         pTool->OnLButtonDown(this, nFlags, point);
  718. }
  719.  
  720. void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
  721. {
  722.     if (!m_bActive)
  723.         return;
  724.     CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
  725.     if (pTool != NULL)
  726.         pTool->OnLButtonUp(this, nFlags, point);
  727. }
  728.  
  729. void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
  730. {
  731.     if (!m_bActive)
  732.         return;
  733.     CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
  734.     if (pTool != NULL)
  735.         pTool->OnMouseMove(this, nFlags, point);
  736. }
  737.  
  738. void CDrawView::OnLButtonDblClk(UINT nFlags, CPoint point)
  739. {
  740.     if (!m_bActive)
  741.         return;
  742.     CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
  743.     if (pTool != NULL)
  744.         pTool->OnLButtonDblClk(this, nFlags, point);
  745. }
  746.  
  747. void CDrawView::OnDestroy()
  748. {
  749.     CScrollView::OnDestroy();
  750.  
  751.     // deactivate the inplace active item on this view
  752.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  753.     if (pActiveItem != NULL && pActiveItem->GetActiveView() == this)
  754.     {
  755.         pActiveItem->Deactivate();
  756.         ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  757.     }
  758. }
  759.  
  760. void CDrawView::OnDrawSelect()
  761. {
  762.     CDrawTool::c_drawShape = selection;
  763. }
  764.  
  765. void CDrawView::OnDrawRoundRect()
  766. {
  767.     CDrawTool::c_drawShape = roundRect;
  768. }
  769.  
  770. void CDrawView::OnDrawRect()
  771. {
  772.     CDrawTool::c_drawShape = rect;
  773. }
  774.  
  775. void CDrawView::OnDrawLine()
  776. {
  777.     CDrawTool::c_drawShape = line;
  778. }
  779.  
  780. void CDrawView::OnDrawEllipse()
  781. {
  782.     CDrawTool::c_drawShape = ellipse;
  783. }
  784.  
  785. void CDrawView::OnDrawPolygon()
  786. {
  787.     CDrawTool::c_drawShape = poly;
  788. }
  789.  
  790. void CDrawView::OnUpdateDrawEllipse(CCmdUI* pCmdUI)
  791. {
  792.     pCmdUI->SetRadio(CDrawTool::c_drawShape == ellipse);
  793. }
  794.  
  795. void CDrawView::OnUpdateDrawLine(CCmdUI* pCmdUI)
  796. {
  797.     pCmdUI->SetRadio(CDrawTool::c_drawShape == line);
  798. }
  799.  
  800. void CDrawView::OnUpdateDrawRect(CCmdUI* pCmdUI)
  801. {
  802.     pCmdUI->SetRadio(CDrawTool::c_drawShape == rect);
  803. }
  804.  
  805. void CDrawView::OnUpdateDrawRoundRect(CCmdUI* pCmdUI)
  806. {
  807.     pCmdUI->SetRadio(CDrawTool::c_drawShape == roundRect);
  808. }
  809.  
  810. void CDrawView::OnUpdateDrawSelect(CCmdUI* pCmdUI)
  811. {
  812.     pCmdUI->SetRadio(CDrawTool::c_drawShape == selection);
  813. }
  814.  
  815. void CDrawView::OnUpdateSingleSelect(CCmdUI* pCmdUI)
  816. {
  817.     pCmdUI->Enable(m_selection.GetCount() == 1);
  818. }
  819.  
  820. void CDrawView::OnEditSelectAll()
  821. {
  822.     CDrawObjList* pObList = GetDocument()->GetObjects();
  823.     POSITION pos = pObList->GetHeadPosition();
  824.     while (pos != NULL)
  825.         Select(pObList->GetNext(pos), TRUE);
  826. }
  827.  
  828. void CDrawView::OnUpdateEditSelectAll(CCmdUI* pCmdUI)
  829. {
  830.     pCmdUI->Enable(GetDocument()->GetObjects()->GetCount() != 0);
  831. }
  832.  
  833. void CDrawView::OnEditClear()
  834. {
  835.     // update all the views before the selection goes away
  836.     GetDocument()->UpdateAllViews(NULL, HINT_DELETE_SELECTION, &m_selection);
  837.     OnUpdate(NULL, HINT_UPDATE_SELECTION, NULL);
  838.  
  839.     // now remove the selection from the document
  840.     POSITION pos = m_selection.GetHeadPosition();
  841.     while (pos != NULL)
  842.     {
  843.         CDrawObj* pObj = m_selection.GetNext(pos);
  844.         GetDocument()->Remove(pObj);
  845.         pObj->Remove();
  846.     }
  847.     m_selection.RemoveAll();
  848. }
  849.  
  850. void CDrawView::OnUpdateAnySelect(CCmdUI* pCmdUI)
  851. {
  852.     pCmdUI->Enable(!m_selection.IsEmpty());
  853. }
  854.  
  855. void CDrawView::OnUpdateDrawPolygon(CCmdUI* pCmdUI)
  856. {
  857.     pCmdUI->SetRadio(CDrawTool::c_drawShape == poly);
  858. }
  859.  
  860. void CDrawView::OnSize(UINT nType, int cx, int cy)
  861. {
  862.     CScrollView::OnSize(nType, cx, cy);
  863.     UpdateActiveItem();
  864. }
  865.  
  866. void CDrawView::OnViewGrid()
  867. {
  868.     m_bGrid = !m_bGrid;
  869.     Invalidate(FALSE);
  870. }
  871.  
  872. void CDrawView::OnUpdateViewGrid(CCmdUI* pCmdUI)
  873. {
  874.     pCmdUI->SetCheck(m_bGrid);
  875.  
  876. }
  877.  
  878. BOOL CDrawView::OnEraseBkgnd(CDC*)
  879. {
  880.     return TRUE;
  881. }
  882.  
  883. void CDrawView::OnObjectFillColor()
  884. {
  885.     CColorDialog dlg;
  886.     if (dlg.DoModal() != IDOK)
  887.         return;
  888.  
  889.     COLORREF color = dlg.GetColor();
  890.  
  891.     POSITION pos = m_selection.GetHeadPosition();
  892.     while (pos != NULL)
  893.     {
  894.         CDrawObj* pObj = m_selection.GetNext(pos);
  895.         pObj->SetFillColor(color);
  896.     }
  897. }
  898.  
  899. void CDrawView::OnObjectLineColor()
  900. {
  901.     CColorDialog dlg;
  902.     if (dlg.DoModal() != IDOK)
  903.         return;
  904.  
  905.     COLORREF color = dlg.GetColor();
  906.  
  907.     POSITION pos = m_selection.GetHeadPosition();
  908.     while (pos != NULL)
  909.     {
  910.         CDrawObj* pObj = m_selection.GetNext(pos);
  911.         pObj->SetLineColor(color);
  912.     }
  913. }
  914.  
  915. void CDrawView::OnObjectMoveBack()
  916. {
  917.     CDrawDoc* pDoc = GetDocument();
  918.     CDrawObj* pObj = m_selection.GetHead();
  919.     CDrawObjList* pObjects = pDoc->GetObjects();
  920.     POSITION pos = pObjects->Find(pObj);
  921.     ASSERT(pos != NULL);
  922.     if (pos != pObjects->GetHeadPosition())
  923.     {
  924.         POSITION posPrev = pos;
  925.         pObjects->GetPrev(posPrev);
  926.         pObjects->RemoveAt(pos);
  927.         pObjects->InsertBefore(posPrev, pObj);
  928.         InvalObj(pObj);
  929.     }
  930. }
  931.  
  932. void CDrawView::OnObjectMoveForward()
  933. {
  934.     CDrawDoc* pDoc = GetDocument();
  935.     CDrawObj* pObj = m_selection.GetHead();
  936.     CDrawObjList* pObjects = pDoc->GetObjects();
  937.     POSITION pos = pObjects->Find(pObj);
  938.     ASSERT(pos != NULL);
  939.     if (pos != pObjects->GetTailPosition())
  940.     {
  941.         POSITION posNext = pos;
  942.         pObjects->GetNext(posNext);
  943.         pObjects->RemoveAt(pos);
  944.         pObjects->InsertAfter(posNext, pObj);
  945.         InvalObj(pObj);
  946.     }
  947. }
  948.  
  949. void CDrawView::OnObjectMoveToBack()
  950. {
  951.     CDrawDoc* pDoc = GetDocument();
  952.     CDrawObj* pObj = m_selection.GetHead();
  953.     CDrawObjList* pObjects = pDoc->GetObjects();
  954.     POSITION pos = pObjects->Find(pObj);
  955.     ASSERT(pos != NULL);
  956.     pObjects->RemoveAt(pos);
  957.     pObjects->AddHead(pObj);
  958.     InvalObj(pObj);
  959. }
  960.  
  961. void CDrawView::OnObjectMoveToFront()
  962. {
  963.     CDrawDoc* pDoc = GetDocument();
  964.     CDrawObj* pObj = m_selection.GetHead();
  965.     CDrawObjList* pObjects = pDoc->GetObjects();
  966.     POSITION pos = pObjects->Find(pObj);
  967.     ASSERT(pos != NULL);
  968.     pObjects->RemoveAt(pos);
  969.     pObjects->AddTail(pObj);
  970.     InvalObj(pObj);
  971. }
  972.  
  973. void CDrawView::OnEditCopy()
  974. {
  975.     ASSERT_VALID(this);
  976.     ASSERT(m_cfDraw != NULL);
  977.  
  978.     // Create a shared file and associate a CArchive with it
  979.     CSharedFile file;
  980.     CArchive ar(&file, CArchive::store);
  981.  
  982.     // Serialize selected objects to the archive
  983.     m_selection.Serialize(ar);
  984.     ar.Close();
  985.  
  986.     COleDataSource* pDataSource = NULL;
  987.     TRY
  988.     {
  989.         pDataSource = new COleDataSource;
  990.         // put on local format instead of or in addation to
  991.         pDataSource->CacheGlobalData(m_cfDraw, file.Detach());
  992.  
  993.         // if only one item and it is a COleClientItem then also
  994.         // paste in that format
  995.         CDrawObj* pDrawObj = m_selection.GetHead();
  996.         if (m_selection.GetCount() == 1 &&
  997.             pDrawObj->IsKindOf(RUNTIME_CLASS(CDrawOleObj)))
  998.         {
  999.             CDrawOleObj* pDrawOle = (CDrawOleObj*)pDrawObj;
  1000.             pDrawOle->m_pClientItem->GetClipboardData(pDataSource, FALSE);
  1001.         }
  1002.         pDataSource->SetClipboard();
  1003.     }
  1004.     CATCH_ALL(e)
  1005.     {
  1006.         delete pDataSource;
  1007.         THROW_LAST();
  1008.     }
  1009.     END_CATCH_ALL
  1010. }
  1011.  
  1012. void CDrawView::OnUpdateEditCopy(CCmdUI* pCmdUI)
  1013. {
  1014.     pCmdUI->Enable(!m_selection.IsEmpty());
  1015. }
  1016.  
  1017. void CDrawView::OnEditCut()
  1018. {
  1019.     OnEditCopy();
  1020.     OnEditClear();
  1021. }
  1022.  
  1023. void CDrawView::OnUpdateEditCut(CCmdUI* pCmdUI)
  1024. {
  1025.     pCmdUI->Enable(!m_selection.IsEmpty());
  1026. }
  1027.  
  1028. void CDrawView::OnEditPaste()
  1029. {
  1030.     COleDataObject dataObject;
  1031.     dataObject.AttachClipboard();
  1032.  
  1033.     // invalidate current selection since it will be deselected
  1034.     OnUpdate(NULL, HINT_UPDATE_SELECTION, NULL);
  1035.     m_selection.RemoveAll();
  1036.     if (dataObject.IsDataAvailable(m_cfDraw))
  1037.     {
  1038.         PasteNative(dataObject);
  1039.  
  1040.         // now add all items in m_selection to document
  1041.         POSITION pos = m_selection.GetHeadPosition();
  1042.         while (pos != NULL)
  1043.             GetDocument()->Add(m_selection.GetNext(pos));
  1044.     }
  1045.     else
  1046.         PasteEmbedded(dataObject, GetInitialPosition().TopLeft() );
  1047.  
  1048.     GetDocument()->SetModifiedFlag();
  1049.  
  1050.     // invalidate new pasted stuff
  1051.     GetDocument()->UpdateAllViews(NULL, HINT_UPDATE_SELECTION, &m_selection);
  1052. }
  1053.  
  1054. void CDrawView::OnUpdateEditPaste(CCmdUI* pCmdUI)
  1055. {
  1056.     // determine if private or standard OLE formats are on the clipboard
  1057.     COleDataObject dataObject;
  1058.     BOOL bEnable = dataObject.AttachClipboard() &&
  1059.         (dataObject.IsDataAvailable(m_cfDraw) ||
  1060.          COleClientItem::CanCreateFromData(&dataObject));
  1061.  
  1062.     // enable command based on availability
  1063.     pCmdUI->Enable(bEnable);
  1064. }
  1065.  
  1066. void CDrawView::OnFilePrint()
  1067. {
  1068.     CScrollView::OnFilePrint();
  1069.     GetDocument()->ComputePageSize();
  1070. }
  1071.  
  1072. void CDrawView::OnViewShowObjects()
  1073. {
  1074.     CDrawOleObj::c_bShowItems = !CDrawOleObj::c_bShowItems;
  1075.     GetDocument()->UpdateAllViews(NULL, HINT_UPDATE_OLE_ITEMS, NULL);
  1076. }
  1077.  
  1078. void CDrawView::OnUpdateViewShowObjects(CCmdUI* pCmdUI)
  1079. {
  1080.     pCmdUI->SetCheck(CDrawOleObj::c_bShowItems);
  1081. }
  1082.  
  1083. void CDrawView::OnEditProperties()
  1084. {
  1085.     if (m_selection.GetCount() == 1 && CDrawTool::c_drawShape == selection)
  1086.     {
  1087.         CDrawTool* pTool = CDrawTool::FindTool(CDrawTool::c_drawShape);
  1088.         ASSERT(pTool != NULL);
  1089.         pTool->OnEditProperties(this);
  1090.     }
  1091. }
  1092.  
  1093. void CDrawView::OnUpdateEditProperties(CCmdUI* pCmdUI)
  1094. {
  1095.     pCmdUI->Enable(m_selection.GetCount() == 1 &&
  1096.                    CDrawTool::c_drawShape == selection);
  1097. }
  1098.  
  1099. /////////////////////////////////////////////////////////////////////////////
  1100. // CDrawView diagnostics
  1101.  
  1102. #ifdef _DEBUG
  1103. void CDrawView::AssertValid() const
  1104. {
  1105.     CScrollView::AssertValid();
  1106. }
  1107.  
  1108. void CDrawView::Dump(CDumpContext& dc) const
  1109. {
  1110.     CScrollView::Dump(dc);
  1111. }
  1112. #endif //_DEBUG
  1113.  
  1114. /////////////////////////////////////////////////////////////////////////////
  1115. // new
  1116. // support for drag/drop
  1117.  
  1118. int CDrawView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  1119. {
  1120.     if (CScrollView::OnCreate(lpCreateStruct) == -1)
  1121.         return -1;
  1122.     
  1123.     // register drop target
  1124.     if( m_dropTarget.Register( this ) )
  1125.         return 0;
  1126.     else
  1127.         return -1;
  1128. }
  1129.  
  1130. BOOL CDrawView::GetObjectInfo(COleDataObject* pDataObject,
  1131.     CSize* pSize, CSize* pOffset)
  1132. {
  1133.     ASSERT(pSize != NULL);
  1134.  
  1135.     // get object descriptor data
  1136.     HGLOBAL hObjDesc = pDataObject->GetGlobalData(m_cfObjectDescriptor);
  1137.     if (hObjDesc == NULL)
  1138.     {
  1139.         if (pOffset != NULL)
  1140.             *pOffset = CSize(0, 0); // fill in defaults instead
  1141.         *pSize = CSize(0, 0);
  1142.         return FALSE;
  1143.     }
  1144.     ASSERT(hObjDesc != NULL);
  1145.  
  1146.     // otherwise, got CF_OBJECTDESCRIPTOR ok.  Lock it down and extract size.
  1147.     LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObjDesc);
  1148.     ASSERT(pObjDesc != NULL);
  1149.     pSize->cx = (int)pObjDesc->sizel.cx;
  1150.     pSize->cy = (int)pObjDesc->sizel.cy;
  1151.     if (pOffset != NULL)
  1152.     {
  1153.         pOffset->cx = (int)pObjDesc->pointl.x;
  1154.         pOffset->cy = (int)pObjDesc->pointl.y;
  1155.     }
  1156.     GlobalUnlock(hObjDesc);
  1157.     GlobalFree(hObjDesc);
  1158.  
  1159.     // successfully retrieved pSize & pOffset info
  1160.     return TRUE;
  1161. }
  1162.  
  1163. DROPEFFECT CDrawView::OnDragEnter(COleDataObject* pDataObject,
  1164.     DWORD grfKeyState, CPoint point)
  1165. {
  1166.     ASSERT(m_prevDropEffect == DROPEFFECT_NONE);
  1167.     m_bDragDataAcceptable = FALSE;
  1168.     if (!COleClientItem::CanCreateFromData(pDataObject))
  1169.         return DROPEFFECT_NONE;
  1170.  
  1171.     m_bDragDataAcceptable = TRUE;
  1172.     GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);
  1173.     CClientDC dc(NULL);
  1174.     dc.HIMETRICtoDP(&m_dragSize);
  1175.     dc.HIMETRICtoDP(&m_dragOffset);
  1176.  
  1177.     return OnDragOver(pDataObject, grfKeyState, point);
  1178. }
  1179.  
  1180. DROPEFFECT CDrawView::OnDragOver(COleDataObject*,
  1181.     DWORD grfKeyState, CPoint point)
  1182. {
  1183.     if(m_bDragDataAcceptable == FALSE)
  1184.         return DROPEFFECT_NONE;
  1185.  
  1186.     point -= m_dragOffset;  // adjust target rect by original cursor offset
  1187.  
  1188.     // check for point outside logical area -- i.e. in hatched region
  1189.     // GetTotalSize() returns the size passed to SetScrollSizes
  1190.     CRect rectScroll(CPoint(0, 0), GetTotalSize());
  1191.  
  1192.     CRect rectItem(point,m_dragSize);
  1193.     rectItem.OffsetRect(GetDeviceScrollPosition());
  1194.  
  1195.     DROPEFFECT de = DROPEFFECT_NONE;
  1196.     CRect rectTemp;
  1197.     if (rectTemp.IntersectRect(rectScroll, rectItem))
  1198.     {
  1199.         // check for force link
  1200. #ifndef _MAC        
  1201.         if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
  1202. #else
  1203.         if ((grfKeyState & (MK_OPTION|MK_SHIFT)) == (MK_OPTION|MK_SHIFT))
  1204. #endif            
  1205.             de = DROPEFFECT_NONE; // DRAWCLI isn't a linking container
  1206.         // check for force copy
  1207. #ifndef _MAC                
  1208.         else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
  1209. #else
  1210.         else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
  1211. #endif        
  1212.             de = DROPEFFECT_COPY;
  1213.         // check for force move
  1214.         else if ((grfKeyState & MK_ALT) == MK_ALT)
  1215.             de = DROPEFFECT_MOVE;
  1216.         // default -- recommended action is move
  1217.         else
  1218.             de = DROPEFFECT_MOVE;
  1219.     }
  1220.  
  1221.     if (point == m_dragPoint)
  1222.         return de;
  1223.  
  1224.     // otherwise, cursor has moved -- need to update the drag feedback
  1225.     CClientDC dc(this);
  1226.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1227.     {
  1228.         // erase previous focus rect
  1229.         dc.DrawFocusRect(CRect(m_dragPoint, m_dragSize));
  1230.     }
  1231.     m_prevDropEffect = de;
  1232.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1233.     {
  1234.         m_dragPoint = point;
  1235.         dc.DrawFocusRect(CRect(point, m_dragSize));
  1236.     }
  1237.     return de;
  1238. }
  1239.  
  1240. BOOL CDrawView::OnDrop(COleDataObject* pDataObject,
  1241.     DROPEFFECT /*dropEffect*/, CPoint point)
  1242. {
  1243.     ASSERT_VALID(this);
  1244.  
  1245.     // clean up focus rect
  1246.     OnDragLeave();
  1247.  
  1248.     // offset point as appropriate for dragging
  1249.     GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);
  1250.     CClientDC dc(NULL);
  1251.     dc.HIMETRICtoDP(&m_dragSize);
  1252.     dc.HIMETRICtoDP(&m_dragOffset);
  1253.     point -= m_dragOffset;
  1254.  
  1255.     // invalidate current selection since it will be deselected
  1256.     OnUpdate(NULL, HINT_UPDATE_SELECTION, NULL);
  1257.     m_selection.RemoveAll();
  1258.     if (m_bDragDataAcceptable)
  1259.         PasteEmbedded(*pDataObject, point);
  1260.  
  1261.     // update the document and views
  1262.     GetDocument()->SetModifiedFlag();
  1263.     GetDocument()->UpdateAllViews(NULL, 0, NULL);      // including this view
  1264.  
  1265.     return TRUE;
  1266. }
  1267.  
  1268. void CDrawView::OnDragLeave()
  1269. {
  1270.     CClientDC dc(this);
  1271.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1272.     {
  1273.         dc.DrawFocusRect(CRect(m_dragPoint,m_dragSize)); // erase previous focus rect
  1274.         m_prevDropEffect = DROPEFFECT_NONE;
  1275.     }
  1276. }
  1277.  
  1278.  
  1279. void CDrawView::OnContextMenu(CWnd* /*pWnd*/, CPoint point) 
  1280. {
  1281.     // make sure window is active
  1282.     GetParentFrame()->ActivateFrame();
  1283.  
  1284.     CPoint local = point;
  1285.     ScreenToClient(&local);
  1286.     ClientToDoc(local);
  1287.  
  1288.     CDrawObj* pObj;
  1289.     pObj = GetDocument()->ObjectAt(local);
  1290.     if(pObj != NULL)
  1291.     {
  1292.         if(!IsSelected(pObj))
  1293.             Select( pObj, FALSE );            // reselect item if appropriate
  1294.         UpdateWindow();
  1295.  
  1296.         CMenu menu;
  1297.         if (menu.LoadMenu(ID_POPUP_MENU))
  1298.         {
  1299.             CMenu* pPopup = menu.GetSubMenu(0);
  1300.             ASSERT(pPopup != NULL);
  1301.  
  1302.             pPopup->TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN,
  1303.                                    point.x, point.y,
  1304.                                    AfxGetMainWnd()); // route commands through main window
  1305.         }
  1306.     }
  1307. }
  1308.  
  1309. void CDrawView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
  1310. {
  1311. #if !defined(_MAC)
  1312.     if (pInfo->m_bPreview == FALSE)
  1313.         ((CDrawDoc*)GetDocument())->m_pSummInfo->RecordPrintDate();
  1314. #endif
  1315.     OnDraw(pDC);
  1316. }
  1317.