DRAWOBJ.CPP
上传用户:sesekoo
上传日期:2020-07-18
资源大小:21543k
文件大小:23k
源码类别:

界面编程

开发平台:

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