DRAWVW.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:32k
源码类别:

Windows编程

开发平台:

Visual C++

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