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

界面编程

开发平台:

Visual C++

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