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

Windows编程

开发平台:

Visual C++

  1. // drawobj.cpp - implementation for drawing objects
  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 "drawcli.h"
  14. #include "drawdoc.h"
  15. #include "drawvw.h"
  16. #include "drawobj.h"
  17. #include "cntritem.h"
  18. #include "rectdlg.h"
  19. IMPLEMENT_SERIAL(CDrawObj, CObject, 0)
  20. CDrawObj::CDrawObj()
  21. {
  22. }
  23. CDrawObj::~CDrawObj()
  24. {
  25. }
  26. CDrawObj::CDrawObj(const CRect& position)
  27. {
  28. m_position = position;
  29. m_pDocument = NULL;
  30. m_bPen = TRUE;
  31. m_logpen.lopnStyle = PS_INSIDEFRAME;
  32. m_logpen.lopnWidth.x = 1;
  33. m_logpen.lopnWidth.y = 1;
  34. m_logpen.lopnColor = RGB(0, 0, 0);
  35. m_bBrush = TRUE;
  36. m_logbrush.lbStyle = BS_SOLID;
  37. m_logbrush.lbColor = RGB(192, 192, 192);
  38. m_logbrush.lbHatch = HS_HORIZONTAL;
  39. }
  40. void CDrawObj::Serialize(CArchive& ar)
  41. {
  42. CObject::Serialize(ar);
  43. if (ar.IsStoring())
  44. {
  45. ar << m_position;
  46. ar << (WORD)m_bPen;
  47. ar.Write(&m_logpen, sizeof(LOGPEN));
  48. ar << (WORD)m_bBrush;
  49. ar.Write(&m_logbrush, sizeof(LOGBRUSH));
  50. }
  51. else
  52. {
  53. // get the document back pointer from the archive
  54. m_pDocument = (CDrawDoc*)ar.m_pDocument;
  55. ASSERT_VALID(m_pDocument);
  56. ASSERT_KINDOF(CDrawDoc, m_pDocument);
  57. WORD wTemp;
  58. ar >> m_position;
  59. ar >> wTemp; m_bPen = (BOOL)wTemp;
  60. ar.Read(&m_logpen,sizeof(LOGPEN));
  61. ar >> wTemp; m_bBrush = (BOOL)wTemp;
  62. ar.Read(&m_logbrush, sizeof(LOGBRUSH));
  63. }
  64. }
  65. void CDrawObj::Remove()
  66. {
  67. delete this;
  68. }
  69. void CDrawObj::Draw(CDC*)
  70. {
  71. }
  72. void CDrawObj::DrawTracker(CDC* pDC, TrackerState state)
  73. {
  74. ASSERT_VALID(this);
  75. switch (state)
  76. {
  77. case normal:
  78. break;
  79. case selected:
  80. case active:
  81. {
  82. int nHandleCount = GetHandleCount();
  83. for (int nHandle = 1; nHandle <= nHandleCount; nHandle += 1)
  84. {
  85. CPoint handle = GetHandle(nHandle);
  86. pDC->PatBlt(handle.x - 3, handle.y - 3, 7, 7, DSTINVERT);
  87. }
  88. }
  89. break;
  90. }
  91. }
  92. // position is in logical
  93. void CDrawObj::MoveTo(const CRect& position, CDrawView* pView)
  94. {
  95. ASSERT_VALID(this);
  96. if (position == m_position)
  97. return;
  98. if (pView == NULL)
  99. {
  100. Invalidate();
  101. m_position = position;
  102. Invalidate();
  103. }
  104. else
  105. {
  106. pView->InvalObj(this);
  107. m_position = position;
  108. pView->InvalObj(this);
  109. }
  110. m_pDocument->SetModifiedFlag();
  111. }
  112. // Note: if bSelected, hit-codes start at one for the top-left
  113. // and increment clockwise, 0 means no hit.
  114. // If !bSelected, 0 = no hit, 1 = hit (anywhere)
  115. // point is in logical coordinates
  116. int CDrawObj::HitTest(CPoint point, CDrawView* pView, BOOL bSelected)
  117. {
  118. ASSERT_VALID(this);
  119. ASSERT(pView != NULL);
  120. if (bSelected)
  121. {
  122. int nHandleCount = GetHandleCount();
  123. for (int nHandle = 1; nHandle <= nHandleCount; nHandle += 1)
  124. {
  125. // GetHandleRect returns in logical coords
  126. CRect rc = GetHandleRect(nHandle,pView);
  127. if (point.x >= rc.left && point.x < rc.right &&
  128. point.y <= rc.top && point.y > rc.bottom)
  129. return nHandle;
  130. }
  131. }
  132. else
  133. {
  134. if (point.x >= m_position.left && point.x < m_position.right &&
  135. point.y <= m_position.top && point.y > m_position.bottom)
  136. return 1;
  137. }
  138. return 0;
  139. }
  140. // rect must be in logical coordinates
  141. BOOL CDrawObj::Intersects(const CRect& rect)
  142. {
  143. ASSERT_VALID(this);
  144. CRect fixed = m_position;
  145. fixed.NormalizeRect();
  146. CRect rectT = rect;
  147. rectT.NormalizeRect();
  148. return !(rectT & fixed).IsRectEmpty();
  149. }
  150. int CDrawObj::GetHandleCount()
  151. {
  152. ASSERT_VALID(this);
  153. return 8;
  154. }
  155. // returns logical coords of center of handle
  156. CPoint CDrawObj::GetHandle(int nHandle)
  157. {
  158. ASSERT_VALID(this);
  159. int x, y, xCenter, yCenter;
  160. // this gets the center regardless of left/right and top/bottom ordering
  161. xCenter = m_position.left + m_position.Width() / 2;
  162. yCenter = m_position.top + m_position.Height() / 2;
  163. switch (nHandle)
  164. {
  165. default:
  166. ASSERT(FALSE);
  167. case 1:
  168. x = m_position.left;
  169. y = m_position.top;
  170. break;
  171. case 2:
  172. x = xCenter;
  173. y = m_position.top;
  174. break;
  175. case 3:
  176. x = m_position.right;
  177. y = m_position.top;
  178. break;
  179. case 4:
  180. x = m_position.right;
  181. y = yCenter;
  182. break;
  183. case 5:
  184. x = m_position.right;
  185. y = m_position.bottom;
  186. break;
  187. case 6:
  188. x = xCenter;
  189. y = m_position.bottom;
  190. break;
  191. case 7:
  192. x = m_position.left;
  193. y = m_position.bottom;
  194. break;
  195. case 8:
  196. x = m_position.left;
  197. y = yCenter;
  198. break;
  199. }
  200. return CPoint(x, y);
  201. }
  202. // return rectange of handle in logical coords
  203. CRect CDrawObj::GetHandleRect(int nHandleID, CDrawView* pView)
  204. {
  205. ASSERT_VALID(this);
  206. ASSERT(pView != NULL);
  207. CRect rect;
  208. // get the center of the handle in logical coords
  209. CPoint point = GetHandle(nHandleID);
  210. // convert to client/device coords
  211. pView->DocToClient(point);
  212. // return CRect of handle in device coords
  213. rect.SetRect(point.x-3, point.y-3, point.x+3, point.y+3);
  214. pView->ClientToDoc(rect);
  215. return rect;
  216. }
  217. HCURSOR CDrawObj::GetHandleCursor(int nHandle)
  218. {
  219. ASSERT_VALID(this);
  220. LPCTSTR id;
  221. switch (nHandle)
  222. {
  223. default:
  224. ASSERT(FALSE);
  225. case 1:
  226. case 5:
  227. id = IDC_SIZENWSE;
  228. break;
  229. case 2:
  230. case 6:
  231. id = IDC_SIZENS;
  232. break;
  233. case 3:
  234. case 7:
  235. id = IDC_SIZENESW;
  236. break;
  237. case 4:
  238. case 8:
  239. id = IDC_SIZEWE;
  240. break;
  241. }
  242. return AfxGetApp()->LoadStandardCursor(id);
  243. }
  244. // point must be in logical
  245. void CDrawObj::MoveHandleTo(int nHandle, CPoint point, CDrawView* pView)
  246. {
  247. ASSERT_VALID(this);
  248. CRect position = m_position;
  249. switch (nHandle)
  250. {
  251. default:
  252. ASSERT(FALSE);
  253. case 1:
  254. position.left = point.x;
  255. position.top = point.y;
  256. break;
  257. case 2:
  258. position.top = point.y;
  259. break;
  260. case 3:
  261. position.right = point.x;
  262. position.top = point.y;
  263. break;
  264. case 4:
  265. position.right = point.x;
  266. break;
  267. case 5:
  268. position.right = point.x;
  269. position.bottom = point.y;
  270. break;
  271. case 6:
  272. position.bottom = point.y;
  273. break;
  274. case 7:
  275. position.left = point.x;
  276. position.bottom = point.y;
  277. break;
  278. case 8:
  279. position.left = point.x;
  280. break;
  281. }
  282. MoveTo(position, pView);
  283. }
  284. void CDrawObj::Invalidate()
  285. {
  286. ASSERT_VALID(this);
  287. m_pDocument->UpdateAllViews(NULL, HINT_UPDATE_DRAWOBJ, this);
  288. }
  289. CDrawObj* CDrawObj::Clone(CDrawDoc* pDoc)
  290. {
  291. ASSERT_VALID(this);
  292. CDrawObj* pClone = new CDrawObj(m_position);
  293. pClone->m_bPen = m_bPen;
  294. pClone->m_logpen = m_logpen;
  295. pClone->m_bBrush = m_bBrush;
  296. pClone->m_logbrush = m_logbrush;
  297. ASSERT_VALID(pClone);
  298. if (pDoc != NULL)
  299. pDoc->Add(pClone);
  300. return pClone;
  301. }
  302. void CDrawObj::OnEditProperties()
  303. {
  304. ASSERT_VALID(this);
  305. CPropertySheet sheet( _T("Shape Properties") );
  306. CRectDlg dlg;
  307. dlg.m_bNoFill = !m_bBrush;
  308. dlg.m_penSize = m_bPen ? m_logpen.lopnWidth.x : 0;
  309. sheet.AddPage( &dlg );
  310. if (sheet.DoModal() != IDOK)
  311. return;
  312. m_bBrush = !dlg.m_bNoFill;
  313. m_bPen = dlg.m_penSize > 0;
  314. if (m_bPen)
  315. {
  316. m_logpen.lopnWidth.x = dlg.m_penSize;
  317. m_logpen.lopnWidth.y = dlg.m_penSize;
  318. }
  319. Invalidate();
  320. m_pDocument->SetModifiedFlag();
  321. }
  322. void CDrawObj::OnOpen(CDrawView* /*pView*/ )
  323. {
  324. OnEditProperties();
  325. }
  326. void CDrawObj::SetLineColor(COLORREF color)
  327. {
  328. ASSERT_VALID(this);
  329. m_logpen.lopnColor = color;
  330. Invalidate();
  331. m_pDocument->SetModifiedFlag();
  332. }
  333. void CDrawObj::SetFillColor(COLORREF color)
  334. {
  335. ASSERT_VALID(this);
  336. m_logbrush.lbColor = color;
  337. Invalidate();
  338. m_pDocument->SetModifiedFlag();
  339. }
  340. #ifdef _DEBUG
  341. void CDrawObj::AssertValid()
  342. {
  343. ASSERT(m_position.left <= m_position.right);
  344. ASSERT(m_position.bottom <= m_position.top);
  345. }
  346. #endif
  347. ////////////////////////////////////////////////////////////////////////////
  348. // CDrawRect
  349. IMPLEMENT_SERIAL(CDrawRect, CDrawObj, 0)
  350. CDrawRect::CDrawRect()
  351. {
  352. }
  353. CDrawRect::CDrawRect(const CRect& position)
  354. : CDrawObj(position)
  355. {
  356. ASSERT_VALID(this);
  357. m_nShape = rectangle;
  358. m_roundness.x = 16;
  359. m_roundness.y = 16;
  360. }
  361. void CDrawRect::Serialize(CArchive& ar)
  362. {
  363. ASSERT_VALID(this);
  364. CDrawObj::Serialize(ar);
  365. if (ar.IsStoring())
  366. {
  367. ar << (WORD) m_nShape;
  368. ar << m_roundness;
  369. }
  370. else
  371. {
  372. WORD wTemp;
  373. ar >> wTemp; m_nShape = (Shape)wTemp;
  374. ar >> m_roundness;
  375. }
  376. }
  377. void CDrawRect::Draw(CDC* pDC)
  378. {
  379. ASSERT_VALID(this);
  380. CBrush brush;
  381. if (!brush.CreateBrushIndirect(&m_logbrush))
  382. return;
  383. CPen pen;
  384. if (!pen.CreatePenIndirect(&m_logpen))
  385. return;
  386. CBrush* pOldBrush;
  387. CPen* pOldPen;
  388. if (m_bBrush)
  389. pOldBrush = pDC->SelectObject(&brush);
  390. else
  391. pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
  392. if (m_bPen)
  393. pOldPen = pDC->SelectObject(&pen);
  394. else
  395. pOldPen = (CPen*)pDC->SelectStockObject(NULL_PEN);
  396. CRect rect = m_position;
  397. switch (m_nShape)
  398. {
  399. case rectangle:
  400. pDC->Rectangle(rect);
  401. break;
  402. case roundRectangle:
  403. pDC->RoundRect(rect, m_roundness);
  404. break;
  405. case ellipse:
  406. pDC->Ellipse(rect);
  407. break;
  408. case line:
  409. if (rect.top > rect.bottom)
  410. {
  411. rect.top -= m_logpen.lopnWidth.y / 2;
  412. rect.bottom += (m_logpen.lopnWidth.y + 1) / 2;
  413. }
  414. else
  415. {
  416. rect.top += (m_logpen.lopnWidth.y + 1) / 2;
  417. rect.bottom -= m_logpen.lopnWidth.y / 2;
  418. }
  419. if (rect.left > rect.right)
  420. {
  421. rect.left -= m_logpen.lopnWidth.x / 2;
  422. rect.right += (m_logpen.lopnWidth.x + 1) / 2;
  423. }
  424. else
  425. {
  426. rect.left += (m_logpen.lopnWidth.x + 1) / 2;
  427. rect.right -= m_logpen.lopnWidth.x / 2;
  428. }
  429. pDC->MoveTo(rect.TopLeft());
  430. pDC->LineTo(rect.BottomRight());
  431. break;
  432. }
  433. pDC->SelectObject(pOldBrush);
  434. pDC->SelectObject(pOldPen);
  435. }
  436. int CDrawRect::GetHandleCount()
  437. {
  438. ASSERT_VALID(this);
  439. return m_nShape == line ? 2 :
  440. CDrawObj::GetHandleCount() + (m_nShape == roundRectangle);
  441. }
  442. // returns center of handle in logical coordinates
  443. CPoint CDrawRect::GetHandle(int nHandle)
  444. {
  445. ASSERT_VALID(this);
  446. if (m_nShape == line && nHandle == 2)
  447. nHandle = 5;
  448. else if (m_nShape == roundRectangle && nHandle == 9)
  449. {
  450. CRect rect = m_position;
  451. rect.NormalizeRect();
  452. CPoint point = rect.BottomRight();
  453. point.x -= m_roundness.x / 2;
  454. point.y -= m_roundness.y / 2;
  455. return point;
  456. }
  457. return CDrawObj::GetHandle(nHandle);
  458. }
  459. HCURSOR CDrawRect::GetHandleCursor(int nHandle)
  460. {
  461. ASSERT_VALID(this);
  462. if (m_nShape == line && nHandle == 2)
  463. nHandle = 5;
  464. else if (m_nShape == roundRectangle && nHandle == 9)
  465. return AfxGetApp()->LoadStandardCursor(IDC_SIZEALL);
  466. return CDrawObj::GetHandleCursor(nHandle);
  467. }
  468. // point is in logical coordinates
  469. void CDrawRect::MoveHandleTo(int nHandle, CPoint point, CDrawView* pView)
  470. {
  471. ASSERT_VALID(this);
  472. if (m_nShape == line && nHandle == 2)
  473. nHandle = 5;
  474. else if (m_nShape == roundRectangle && nHandle == 9)
  475. {
  476. CRect rect = m_position;
  477. rect.NormalizeRect();
  478. if (point.x > rect.right - 1)
  479. point.x = rect.right - 1;
  480. else if (point.x < rect.left + rect.Width() / 2)
  481. point.x = rect.left + rect.Width() / 2;
  482. if (point.y > rect.bottom - 1)
  483. point.y = rect.bottom - 1;
  484. else if (point.y < rect.top + rect.Height() / 2)
  485. point.y = rect.top + rect.Height() / 2;
  486. m_roundness.x = 2 * (rect.right - point.x);
  487. m_roundness.y = 2 * (rect.bottom - point.y);
  488. m_pDocument->SetModifiedFlag();
  489. if (pView == NULL)
  490. Invalidate();
  491. else
  492. pView->InvalObj(this);
  493. return;
  494. }
  495. CDrawObj::MoveHandleTo(nHandle, point, pView);
  496. }
  497. // rect must be in logical coordinates
  498. BOOL CDrawRect::Intersects(const CRect& rect)
  499. {
  500. ASSERT_VALID(this);
  501. CRect rectT = rect;
  502. rectT.NormalizeRect();
  503. CRect fixed = m_position;
  504. fixed.NormalizeRect();
  505. if ((rectT & fixed).IsRectEmpty())
  506. return FALSE;
  507. CRgn rgn;
  508. switch (m_nShape)
  509. {
  510. case rectangle:
  511. return TRUE;
  512. case roundRectangle:
  513. rgn.CreateRoundRectRgn(fixed.left, fixed.top, fixed.right, fixed.bottom,
  514. m_roundness.x, m_roundness.y);
  515. break;
  516. case ellipse:
  517. rgn.CreateEllipticRgnIndirect(fixed);
  518. break;
  519. case line:
  520. {
  521. int x = (m_logpen.lopnWidth.x + 5) / 2;
  522. int y = (m_logpen.lopnWidth.y + 5) / 2;
  523. POINT points[4];
  524. points[0].x = fixed.left;
  525. points[0].y = fixed.top;
  526. points[1].x = fixed.left;
  527. points[1].y = fixed.top;
  528. points[2].x = fixed.right;
  529. points[2].y = fixed.bottom;
  530. points[3].x = fixed.right;
  531. points[3].y = fixed.bottom;
  532. if (fixed.left < fixed.right)
  533. {
  534. points[0].x -= x;
  535. points[1].x += x;
  536. points[2].x += x;
  537. points[3].x -= x;
  538. }
  539. else
  540. {
  541. points[0].x += x;
  542. points[1].x -= x;
  543. points[2].x -= x;
  544. points[3].x += x;
  545. }
  546. if (fixed.top < fixed.bottom)
  547. {
  548. points[0].y -= y;
  549. points[1].y += y;
  550. points[2].y += y;
  551. points[3].y -= y;
  552. }
  553. else
  554. {
  555. points[0].y += y;
  556. points[1].y -= y;
  557. points[2].y -= y;
  558. points[3].y += y;
  559. }
  560. rgn.CreatePolygonRgn(points, 4, ALTERNATE);
  561. }
  562. break;
  563. }
  564. return rgn.RectInRegion(fixed);
  565. }
  566. CDrawObj* CDrawRect::Clone(CDrawDoc* pDoc)
  567. {
  568. ASSERT_VALID(this);
  569. CDrawRect* pClone = new CDrawRect(m_position);
  570. pClone->m_bPen = m_bPen;
  571. pClone->m_logpen = m_logpen;
  572. pClone->m_bBrush = m_bBrush;
  573. pClone->m_logbrush = m_logbrush;
  574. pClone->m_nShape = m_nShape;
  575. pClone->m_roundness = m_roundness;
  576. ASSERT_VALID(pClone);
  577. if (pDoc != NULL)
  578. pDoc->Add(pClone);
  579. ASSERT_VALID(pClone);
  580. return pClone;
  581. }
  582. ////////////////////////////////////////////////////////////////////////////
  583. // CDrawPoly
  584. IMPLEMENT_SERIAL(CDrawPoly, CDrawObj, 0)
  585. CDrawPoly::CDrawPoly()
  586. {
  587. m_points = NULL;
  588. m_nPoints = 0;
  589. m_nAllocPoints = 0;
  590. }
  591. CDrawPoly::CDrawPoly(const CRect& position)
  592. : CDrawObj(position)
  593. {
  594. m_points = NULL;
  595. m_nPoints = 0;
  596. m_nAllocPoints = 0;
  597. m_bPen = TRUE;
  598. m_bBrush = FALSE;
  599. }
  600. CDrawPoly::~CDrawPoly()
  601. {
  602. if (m_points != NULL)
  603. delete[] m_points;
  604. }
  605. void CDrawPoly::Serialize( CArchive& ar )
  606. {
  607. int i;
  608. CDrawObj::Serialize( ar );
  609. if( ar.IsStoring() )
  610. {
  611. ar << (WORD) m_nPoints;
  612. ar << (WORD) m_nAllocPoints;
  613. for (i = 0;i< m_nPoints; i++)
  614. ar << m_points[i];
  615. }
  616. else
  617. {
  618. WORD wTemp;
  619. ar >> wTemp; m_nPoints = wTemp;
  620. ar >> wTemp; m_nAllocPoints = wTemp;
  621. m_points = new CPoint[m_nAllocPoints];
  622. for (i = 0;i < m_nPoints; i++)
  623. ar >> m_points[i];
  624. }
  625. }
  626. void CDrawPoly::Draw(CDC* pDC)
  627. {
  628. ASSERT_VALID(this);
  629. CBrush brush;
  630. if (!brush.CreateBrushIndirect(&m_logbrush))
  631. return;
  632. CPen pen;
  633. if (!pen.CreatePenIndirect(&m_logpen))
  634. return;
  635. CBrush* pOldBrush;
  636. CPen* pOldPen;
  637. if (m_bBrush)
  638. pOldBrush = pDC->SelectObject(&brush);
  639. else
  640. pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
  641. if (m_bPen)
  642. pOldPen = pDC->SelectObject(&pen);
  643. else
  644. pOldPen = (CPen*)pDC->SelectStockObject(NULL_PEN);
  645. pDC->Polygon(m_points, m_nPoints);
  646. pDC->SelectObject(pOldBrush);
  647. pDC->SelectObject(pOldPen);
  648. }
  649. // position must be in logical coordinates
  650. void CDrawPoly::MoveTo(const CRect& position, CDrawView* pView)
  651. {
  652. ASSERT_VALID(this);
  653. if (position == m_position)
  654. return;
  655. if (pView == NULL)
  656. Invalidate();
  657. else
  658. pView->InvalObj(this);
  659. for (int i = 0; i < m_nPoints; i += 1)
  660. {
  661. m_points[i].x += position.left - m_position.left;
  662. m_points[i].y += position.top - m_position.top;
  663. }
  664. m_position = position;
  665. if (pView == NULL)
  666. Invalidate();
  667. else
  668. pView->InvalObj(this);
  669. m_pDocument->SetModifiedFlag();
  670. }
  671. int CDrawPoly::GetHandleCount()
  672. {
  673. return m_nPoints;
  674. }
  675. CPoint CDrawPoly::GetHandle(int nHandle)
  676. {
  677. ASSERT_VALID(this);
  678. ASSERT(nHandle >= 1 && nHandle <= m_nPoints);
  679. return m_points[nHandle - 1];
  680. }
  681. HCURSOR CDrawPoly::GetHandleCursor(int )
  682. {
  683. return AfxGetApp()->LoadStandardCursor(IDC_ARROW);
  684. }
  685. // point is in logical coordinates
  686. void CDrawPoly::MoveHandleTo(int nHandle, CPoint point, CDrawView* pView)
  687. {
  688. ASSERT_VALID(this);
  689. ASSERT(nHandle >= 1 && nHandle <= m_nPoints);
  690. if (m_points[nHandle - 1] == point)
  691. return;
  692. m_points[nHandle - 1] = point;
  693. RecalcBounds(pView);
  694. if (pView == NULL)
  695. Invalidate();
  696. else
  697. pView->InvalObj(this);
  698. m_pDocument->SetModifiedFlag();
  699. }
  700. // rect must be in logical coordinates
  701. BOOL CDrawPoly::Intersects(const CRect& rect)
  702. {
  703. ASSERT_VALID(this);
  704. CRgn rgn;
  705. rgn.CreatePolygonRgn(m_points, m_nPoints, ALTERNATE);
  706. return rgn.RectInRegion(rect);
  707. }
  708. CDrawObj* CDrawPoly::Clone(CDrawDoc* pDoc)
  709. {
  710. ASSERT_VALID(this);
  711. CDrawPoly* pClone = new CDrawPoly(m_position);
  712. pClone->m_bPen = m_bPen;
  713. pClone->m_logpen = m_logpen;
  714. pClone->m_bBrush = m_bBrush;
  715. pClone->m_logbrush = m_logbrush;
  716. pClone->m_points = new CPoint[m_nAllocPoints];
  717. memcpy(pClone->m_points, m_points, sizeof(CPoint) * m_nPoints);
  718. pClone->m_nAllocPoints = m_nAllocPoints;
  719. pClone->m_nPoints = m_nPoints;
  720. ASSERT_VALID(pClone);
  721. if (pDoc != NULL)
  722. pDoc->Add(pClone);
  723. ASSERT_VALID(pClone);
  724. return pClone;
  725. }
  726. // point is in logical coordinates
  727. void CDrawPoly::AddPoint(const CPoint& point, CDrawView* pView)
  728. {
  729. ASSERT_VALID(this);
  730. if (m_nPoints == m_nAllocPoints)
  731. {
  732. CPoint* newPoints = new CPoint[m_nAllocPoints + 10];
  733. if (m_points != NULL)
  734. {
  735. memcpy(newPoints, m_points, sizeof(CPoint) * m_nAllocPoints);
  736. delete[] m_points;
  737. }
  738. m_points = newPoints;
  739. m_nAllocPoints += 10;
  740. }
  741. if (m_nPoints == 0 || m_points[m_nPoints - 1] != point)
  742. {
  743. m_points[m_nPoints++] = point;
  744. if (!RecalcBounds(pView))
  745. {
  746. if (pView == NULL)
  747. Invalidate();
  748. else
  749. pView->InvalObj(this);
  750. }
  751. m_pDocument->SetModifiedFlag();
  752. }
  753. }
  754. BOOL CDrawPoly::RecalcBounds(CDrawView* pView)
  755. {
  756. ASSERT_VALID(this);
  757. if (m_nPoints == 0)
  758. return FALSE;
  759. CRect bounds(m_points[0], CSize(0, 0));
  760. for (int i = 1; i < m_nPoints; ++i)
  761. {
  762. if (m_points[i].x < bounds.left)
  763. bounds.left = m_points[i].x;
  764. if (m_points[i].x > bounds.right)
  765. bounds.right = m_points[i].x;
  766. if (m_points[i].y < bounds.top)
  767. bounds.top = m_points[i].y;
  768. if (m_points[i].y > bounds.bottom)
  769. bounds.bottom = m_points[i].y;
  770. }
  771. if (bounds == m_position)
  772. return FALSE;
  773. if (pView == NULL)
  774. Invalidate();
  775. else
  776. pView->InvalObj(this);
  777. m_position = bounds;
  778. if (pView == NULL)
  779. Invalidate();
  780. else
  781. pView->InvalObj(this);
  782. return TRUE;
  783. }
  784. ////////////////////////////////////////////////////////////////////////////
  785. IMPLEMENT_SERIAL(CDrawOleObj, CDrawObj, 0)
  786. BOOL CDrawOleObj::c_bShowItems = TRUE;
  787. CDrawOleObj::CDrawOleObj() : m_extent(0,0)
  788. {
  789. m_pClientItem = NULL;
  790. }
  791. CDrawOleObj::CDrawOleObj(const CRect& position)
  792. : CDrawObj(position), m_extent(0, 0)
  793. {
  794. m_pClientItem = NULL;
  795. }
  796. CDrawOleObj::~CDrawOleObj()
  797. {
  798. if (m_pClientItem != NULL)
  799. {
  800. m_pClientItem->Release();
  801. m_pClientItem = NULL;
  802. }
  803. }
  804. void CDrawOleObj::Remove()
  805. {
  806. if (m_pClientItem != NULL)
  807. {
  808. m_pClientItem->Delete();
  809. m_pClientItem = NULL;
  810. }
  811. CDrawObj::Remove();
  812. }
  813. void CDrawOleObj::Serialize( CArchive& ar )
  814. {
  815. ASSERT_VALID(this);
  816. CDrawObj::Serialize(ar);
  817. if (ar.IsStoring())
  818. {
  819. ar << m_extent;
  820. ar << m_pClientItem;
  821. }
  822. else
  823. {
  824. ar >> m_extent;
  825. ar >> m_pClientItem;
  826. m_pClientItem->m_pDrawObj = this;
  827. }
  828. }
  829. CDrawObj* CDrawOleObj::Clone(CDrawDoc* pDoc)
  830. {
  831. ASSERT_VALID(this);
  832. AfxGetApp()->BeginWaitCursor();
  833. CDrawOleObj* pClone = NULL;
  834. CDrawItem* pItem = NULL;
  835. TRY
  836. {
  837. // perform a "deep copy" -- need to copy CDrawOleObj and the CDrawItem
  838. //  that it points to.
  839. CDrawOleObj* pClone = new CDrawOleObj(m_position);
  840. CDrawItem* pItem = new CDrawItem(m_pDocument, pClone);
  841. if (!pItem->CreateCloneFrom(m_pClientItem))
  842. AfxThrowMemoryException();
  843. pClone->m_pClientItem = pItem;
  844. pClone->m_bPen = m_bPen;
  845. pClone->m_logpen = m_logpen;
  846. pClone->m_bBrush = m_bBrush;
  847. pClone->m_logbrush = m_logbrush;
  848. ASSERT_VALID(pClone);
  849. if (pDoc != NULL)
  850. pDoc->Add(pClone);
  851. }
  852. CATCH_ALL(e)
  853. {
  854. pItem->Delete();
  855. pClone->m_pClientItem = NULL;
  856. pClone->Remove();
  857. AfxGetApp()->EndWaitCursor();
  858. THROW_LAST();
  859. }
  860. END_CATCH_ALL
  861. AfxGetApp()->EndWaitCursor();
  862. return pClone;
  863. }
  864. void CDrawOleObj::Draw(CDC* pDC)
  865. {
  866. ASSERT_VALID(this);
  867. CDrawItem* pItem = m_pClientItem;
  868. if (pItem != NULL)
  869. {
  870. // draw the OLE item itself
  871. pItem->Draw(pDC, m_position);
  872. // don't draw tracker in print preview or on printer
  873. if (!pDC->IsPrinting())
  874. {
  875. // use a CRectTracker to draw the standard effects
  876. CRectTracker tracker;
  877. tracker.m_rect = m_position;
  878. pDC->LPtoDP(tracker.m_rect);
  879. if (c_bShowItems)
  880. {
  881. // put correct border depending on item type
  882. if (pItem->GetType() == OT_LINK)
  883. tracker.m_nStyle |= CRectTracker::dottedLine;
  884. else
  885. tracker.m_nStyle |= CRectTracker::solidLine;
  886. }
  887. // put hatching over the item if it is currently open
  888. if (pItem->GetItemState() == COleClientItem::openState ||
  889. pItem->GetItemState() == COleClientItem::activeUIState)
  890. {
  891. tracker.m_nStyle |= CRectTracker::hatchInside;
  892. }
  893. tracker.Draw(pDC);
  894. }
  895. }
  896. }
  897. void CDrawOleObj::OnOpen(CDrawView* pView)
  898. {
  899. AfxGetApp()->BeginWaitCursor();
  900. m_pClientItem->DoVerb(
  901. GetKeyState(VK_CONTROL) < 0 ? OLEIVERB_OPEN : OLEIVERB_PRIMARY,
  902. pView);
  903. AfxGetApp()->EndWaitCursor();
  904. }
  905. void CDrawOleObj::OnEditProperties()
  906. {
  907. // using COlePropertiesDialog directly means no scaling
  908. COlePropertiesDialog dlg(m_pClientItem, 100, 100, NULL);
  909. dlg.DoModal();
  910. }
  911. // position is in logical
  912. void CDrawOleObj::MoveTo(const CRect& position, CDrawView* pView)
  913. {
  914. ASSERT_VALID(this);
  915. if (position == m_position)
  916. return;
  917. // call base class to update position
  918. CDrawObj::MoveTo(position, pView);
  919. // update position of in-place editing session on position change
  920. if (m_pClientItem->IsInPlaceActive())
  921. m_pClientItem->SetItemRects();
  922. }
  923. /////////////////////////////////////////////////////////////////////////////