Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3023 lines
85 KiB

  1. #include "stdafx.h"
  2. #include "global.h"
  3. #include "pbrush.h"
  4. #include "pbrusdoc.h"
  5. #include "pbrusfrm.h"
  6. #include "pbrusvw.h"
  7. #include "minifwnd.h"
  8. #include "bmobject.h"
  9. #include "imgsuprt.h"
  10. #include "imgwnd.h"
  11. #include "imgbrush.h"
  12. #include "imgwell.h"
  13. #include "imgtools.h"
  14. #include "t_text.h"
  15. #include "toolbox.h"
  16. #include "imgcolor.h"
  17. #include "undo.h"
  18. #include "props.h"
  19. #include "colorsrc.h"
  20. #ifdef _DEBUG
  21. #undef THIS_FILE
  22. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  23. #endif
  24. IMPLEMENT_DYNAMIC(CImgTool, CObject)
  25. IMPLEMENT_DYNAMIC(CRubberTool, CImgTool)
  26. IMPLEMENT_DYNAMIC(CClosedFormTool, CRubberTool)
  27. IMPLEMENT_DYNAMIC(CFreehandTool, CImgTool)
  28. IMPLEMENT_DYNAMIC(CSketchTool, CFreehandTool)
  29. IMPLEMENT_DYNAMIC(CBrushTool, CFreehandTool)
  30. IMPLEMENT_DYNAMIC(CPencilTool, CFreehandTool)
  31. IMPLEMENT_DYNAMIC(CEraserTool, CFreehandTool)
  32. IMPLEMENT_DYNAMIC(CAirBrushTool, CFreehandTool)
  33. IMPLEMENT_DYNAMIC(CLineTool, CRubberTool)
  34. IMPLEMENT_DYNAMIC(CRectTool, CClosedFormTool)
  35. IMPLEMENT_DYNAMIC(CRoundRectTool, CClosedFormTool)
  36. IMPLEMENT_DYNAMIC(CEllipseTool, CClosedFormTool)
  37. IMPLEMENT_DYNAMIC(CPickColorTool, CImgTool)
  38. IMPLEMENT_DYNAMIC(CFloodTool, CImgTool)
  39. IMPLEMENT_DYNAMIC(CSelectTool, CImgTool)
  40. IMPLEMENT_DYNAMIC(CZoomTool, CImgTool)
  41. #include "memtrace.h"
  42. extern CRect rcDragBrush;
  43. extern HDC hRubberDC;
  44. BOOL g_bBrushVisible;
  45. BOOL g_bPickingColor;
  46. UINT g_nStrokeWidth = 1;
  47. /***************************************************************************/
  48. //
  49. // Drawing Tool Classes
  50. //
  51. CRectTool g_rectTool;
  52. CRoundRectTool g_roundRectTool;
  53. CEllipseTool g_ellipseTool;
  54. CLineTool g_lineTool;
  55. CSelectTool g_selectTool;
  56. CBrushTool g_brushTool;
  57. CSketchTool g_sketchTool;
  58. CPencilTool g_pencilTool;
  59. CEraserTool g_eraserTool;
  60. CAirBrushTool g_airBrushTool;
  61. CFloodTool g_floodTool;
  62. CPickColorTool g_pickColorTool;
  63. CZoomTool g_zoomTool;
  64. /***************************************************************************/
  65. CImgTool* CImgTool::c_pHeadImgTool = NULL;
  66. CImgTool* CImgTool::c_pCurrentImgTool = &g_pencilTool;
  67. CImgTool* CImgTool::c_pPreviousImgTool = &g_pencilTool;
  68. BOOL CImgTool::c_bDragging = FALSE;
  69. int CImgTool::c_nHideCount = 0;
  70. /***************************************************************************/
  71. CImgTool::CImgTool()
  72. {
  73. m_bUsesBrush = FALSE;
  74. m_bIsUndoable = TRUE;
  75. m_bCanBePrevTool = TRUE;
  76. m_bToggleWithPrev = FALSE;
  77. m_bFilled = FALSE;
  78. m_bBorder = TRUE;
  79. m_bMultPtOpInProgress = FALSE;
  80. m_eDrawDirection = eFREEHAND;
  81. m_nStrokeWidth = 0;
  82. m_nStrokeShape = roundBrush;
  83. m_nCursorID = LOWORD(IDC_CROSSHAIR);
  84. m_nCmdID = NULL;
  85. // Link into the list of tools...
  86. m_pNextImgTool = c_pHeadImgTool;
  87. c_pHeadImgTool = this;
  88. }
  89. /******************************************************************************/
  90. eDRAWCONSTRAINTDIRECTION CImgTool::DetermineDrawDirection(MTI *pmti)
  91. {
  92. eDRAWCONSTRAINTDIRECTION eDrawDirection;
  93. // 45 is dominant, test first
  94. if ( (pmti->pt.x > pmti->ptPrev.x) &&
  95. (pmti->pt.y > pmti->ptPrev.y) )
  96. {
  97. eDrawDirection = eSOUTH_EAST;
  98. }
  99. else
  100. {
  101. if ( (pmti->pt.x > pmti->ptPrev.x) &&
  102. (pmti->pt.y < pmti->ptPrev.y) )
  103. {
  104. eDrawDirection = eNORTH_EAST;
  105. }
  106. else
  107. {
  108. if ( (pmti->pt.x < pmti->ptPrev.x) &&
  109. (pmti->pt.y > pmti->ptPrev.y) )
  110. {
  111. eDrawDirection = eSOUTH_WEST;
  112. }
  113. else
  114. {
  115. if ( (pmti->pt.x < pmti->ptPrev.x) &&
  116. (pmti->pt.y < pmti->ptPrev.y) )
  117. {
  118. eDrawDirection = eNORTH_WEST;
  119. }
  120. else
  121. {
  122. // Horizontal is the next dominant, test before vertical
  123. if (pmti->ptPrev.x != pmti->pt.x)
  124. {
  125. eDrawDirection = eEAST_WEST;
  126. pmti->pt.y = pmti->ptPrev.y;
  127. }
  128. else
  129. {
  130. if (pmti->ptPrev.y != pmti->pt.y)
  131. {
  132. eDrawDirection = eNORTH_SOUTH;
  133. pmti->pt.x = pmti->ptPrev.x;
  134. }
  135. else
  136. {
  137. // we should never fall into here, but in any case...
  138. eDrawDirection = eFREEHAND;
  139. }
  140. }
  141. }
  142. }
  143. }
  144. }
  145. return eDrawDirection;
  146. }
  147. /******************************************************************************/
  148. void CImgTool::AdjustPointsForConstraint(MTI *pmti)
  149. {
  150. }
  151. /******************************************************************************/
  152. void CImgTool::PreProcessPoints(MTI *pmti)
  153. {
  154. if (pmti != NULL)
  155. {
  156. if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) //still in constrain mode
  157. {
  158. switch (m_eDrawDirection)
  159. {
  160. case eEAST_WEST:
  161. case eNORTH_SOUTH:
  162. case eNORTH_WEST:
  163. case eSOUTH_EAST:
  164. case eNORTH_EAST:
  165. case eSOUTH_WEST:
  166. AdjustPointsForConstraint(pmti);
  167. break;
  168. default: // not in constraint mode yet If shift down, check for
  169. // mode and save mode else nothing. Default is freehand
  170. m_eDrawDirection = DetermineDrawDirection(pmti);
  171. AdjustPointsForConstraint(pmti);
  172. break;
  173. }
  174. }
  175. else
  176. {
  177. // shift not down
  178. m_eDrawDirection = eFREEHAND;
  179. }
  180. }
  181. }
  182. /***************************************************************************/
  183. void CImgTool::HideDragger(CImgWnd* pImgWnd)
  184. {
  185. ASSERT(c_pCurrentImgTool != NULL);
  186. if (c_nHideCount == 0)
  187. c_pCurrentImgTool->OnShowDragger(pImgWnd, FALSE);
  188. c_nHideCount++;
  189. }
  190. /***************************************************************************/
  191. void CImgTool::ShowDragger(CImgWnd* pImgWnd)
  192. {
  193. ASSERT(c_pCurrentImgTool != NULL);
  194. if (--c_nHideCount == 0)
  195. c_pCurrentImgTool->OnShowDragger(pImgWnd, TRUE);
  196. }
  197. /***************************************************************************/
  198. void CImgTool::Select(UINT nCmdID)
  199. {
  200. CImgTool* p = FromID(nCmdID);
  201. if (p)
  202. {
  203. p->Select();
  204. }
  205. }
  206. /***************************************************************************/
  207. void CImgTool::Select()
  208. {
  209. ASSERT(this != NULL);
  210. if (this == c_pCurrentImgTool && m_bToggleWithPrev)
  211. {
  212. SelectPrevious();
  213. return;
  214. }
  215. if (g_bCustomBrush)
  216. {
  217. g_bCustomBrush = FALSE;
  218. SetCombineMode(combineColor);
  219. }
  220. HideBrush();
  221. if (c_pCurrentImgTool->m_bCanBePrevTool && c_pCurrentImgTool != this)
  222. c_pPreviousImgTool = c_pCurrentImgTool;
  223. // Make sure to Deactivate the old one BEFORE activating the new one, so
  224. // globals (like g_nStrokeWidth) get set correctly
  225. if (c_pCurrentImgTool != NULL)
  226. c_pCurrentImgTool->OnActivate(FALSE);
  227. c_pCurrentImgTool = this;
  228. OnActivate(TRUE);
  229. if (c_pCurrentImgTool != this)
  230. {
  231. // Some tools may give up activation...
  232. ASSERT(!m_bCanBePrevTool);
  233. return;
  234. }
  235. SetCombineMode(combineColor);
  236. if (g_pImgToolWnd)
  237. {
  238. g_pImgToolWnd->SelectTool( (WORD)m_nCmdID );
  239. if (g_pImgToolWnd->m_hWnd)
  240. g_pImgToolWnd->InvalidateOptions();
  241. }
  242. CImgWnd::SetToolCursor();
  243. }
  244. /***************************************************************************/
  245. CImgTool* CImgTool::FromID(UINT nCmdID)
  246. {
  247. CImgTool* pImgTool = c_pHeadImgTool;
  248. while (pImgTool != NULL && pImgTool->m_nCmdID != nCmdID)
  249. pImgTool = pImgTool->m_pNextImgTool;
  250. return pImgTool;
  251. }
  252. /***************************************************************************/
  253. void CImgTool::SetStrokeWidth(UINT nNewStrokeWidth)
  254. {
  255. if (nNewStrokeWidth == m_nStrokeWidth)
  256. return;
  257. HideBrush();
  258. g_bCustomBrush = FALSE;
  259. m_nStrokeWidth = nNewStrokeWidth;
  260. g_pImgToolWnd->InvalidateOptions();
  261. extern MTI mti;
  262. if (mti.fLeft || mti.fRight)
  263. OnDrag(CImgWnd::GetCurrent(), &mti);
  264. }
  265. /***************************************************************************/
  266. void CImgTool::SetStrokeShape(UINT nNewStrokeShape)
  267. {
  268. if (m_nStrokeShape == nNewStrokeShape)
  269. return;
  270. HideBrush();
  271. g_bCustomBrush = FALSE;
  272. m_nStrokeShape = nNewStrokeShape;
  273. g_pImgToolWnd->InvalidateOptions(FALSE);
  274. }
  275. /***************************************************************************/
  276. void CImgTool::OnActivate(BOOL bActivate)
  277. {
  278. if (bActivate)
  279. OnShowDragger(CImgWnd::GetCurrent(), TRUE);
  280. }
  281. /***************************************************************************/
  282. void CImgTool::OnEnter(CImgWnd* pImgWnd, MTI* pmti)
  283. {
  284. // No default action
  285. }
  286. /***************************************************************************/
  287. void CImgTool::OnLeave(CImgWnd* pImgWnd, MTI* pmti)
  288. {
  289. // No default action
  290. }
  291. /***************************************************************************/
  292. void CImgTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShowDragger)
  293. {
  294. // No default action
  295. }
  296. /***************************************************************************/
  297. void CImgTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  298. {
  299. c_bDragging = TRUE;
  300. }
  301. /***************************************************************************/
  302. void CImgTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  303. {
  304. c_bDragging = FALSE;
  305. if (m_bIsUndoable)
  306. DirtyImg(pImgWnd->m_pImg);
  307. }
  308. /***************************************************************************/
  309. void CImgTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  310. {
  311. ASSERT(c_bDragging);
  312. }
  313. /***************************************************************************/
  314. void CImgTool::OnMove(CImgWnd* pImgWnd, MTI* pmti)
  315. {
  316. // ASSERT(!c_bDragging);
  317. if (UsesBrush())
  318. {
  319. fDraggingBrush = TRUE;
  320. pImgWnd->ShowBrush(pmti->pt);
  321. }
  322. SetStatusBarPosition(pmti->pt);
  323. }
  324. /***************************************************************************/
  325. void CImgTool::OnTimer(CImgWnd* pImgWnd, MTI* pmti)
  326. {
  327. // Tools should not have started a timer unless it overrides this!
  328. ASSERT(FALSE);
  329. }
  330. /***************************************************************************/
  331. void CImgTool::OnCancel(CImgWnd* pImgWnd)
  332. {
  333. c_bDragging = FALSE;
  334. }
  335. /***************************************************************************/
  336. void CImgTool::OnPaintOptions(CDC* pDC, const CRect& paintRect,
  337. const CRect& optionsRect)
  338. {
  339. }
  340. /***************************************************************************/
  341. void CImgTool::PaintStdPattern(CDC* pDC, const CRect& paintRect,
  342. const CRect& optionsRect)
  343. {
  344. CBrush brush;
  345. CPalette *pcPaletteOld = NULL;
  346. CPalette *pcPaletteOld2 = NULL;
  347. CDC dc;
  348. if (!dc.CreateCompatibleDC(pDC))
  349. return;
  350. CBitmap bitmap, * pOldBitmap;
  351. if (!bitmap.CreateCompatibleBitmap(pDC, 8, 8))
  352. return;
  353. pOldBitmap = dc.SelectObject(&bitmap);
  354. if (theApp.m_pPalette)
  355. {
  356. pcPaletteOld = pDC->SelectPalette( theApp.m_pPalette, FALSE );
  357. pDC->RealizePalette();
  358. pcPaletteOld2 = dc.SelectPalette( theApp.m_pPalette, FALSE );
  359. dc.RealizePalette();
  360. }
  361. CBrush* pOldBrush = NULL;
  362. COLORREF rgb = crLeft;
  363. if (pImgCur->m_pBitmapObj->m_nColors == 0)
  364. {
  365. BOOL MonoRect(CDC* pDC, const CRect& rect, COLORREF rgb, BOOL bFrame);
  366. MonoRect(&dc, CRect(0, 0, 9, 9), rgb, FALSE);
  367. }
  368. else
  369. {
  370. brush.CreateSolidBrush(rgb);
  371. pOldBrush = dc.SelectObject(&brush);
  372. dc.PatBlt(0, 0, 8, 8, PATCOPY);
  373. dc.SelectObject(pOldBrush);
  374. brush.DeleteObject();
  375. }
  376. // Draw a black grid...
  377. for (int i = 0; i < 9; i++)
  378. {
  379. pDC->PatBlt(optionsRect.left + 2 + i * 7, optionsRect.top + 3,
  380. 1, 8 * 7 + 1, BLACKNESS);
  381. pDC->PatBlt(optionsRect.left + 2, optionsRect.top + 3 + i * 7,
  382. 8 * 7 + 1, 1, BLACKNESS);
  383. }
  384. // Fill in the boxes...
  385. COLORREF curColor = (COLORREF)0xffffffff;
  386. for (int y = 0; y < 8; y++)
  387. {
  388. for (int x = 0; x < 8; x++)
  389. {
  390. COLORREF color = dc.GetPixel(x, y) | 0x02000000L;
  391. if (color != curColor)
  392. {
  393. if (pOldBrush != NULL)
  394. pDC->SelectObject(pOldBrush);
  395. brush.DeleteObject();
  396. brush.CreateSolidBrush(color);
  397. pOldBrush = pDC->SelectObject(&brush);
  398. curColor = color;
  399. }
  400. pDC->PatBlt(optionsRect.left + 2 + 1 + x * 7,
  401. optionsRect.top + 3 + 1 + y * 7, 6, 6, PATCOPY);
  402. }
  403. }
  404. ASSERT(pOldBrush != NULL);
  405. pDC->SelectObject(pOldBrush);
  406. dc.SelectObject(pOldBitmap);
  407. if (pcPaletteOld)
  408. pDC->SelectPalette(pcPaletteOld, FALSE);
  409. if (pcPaletteOld2)
  410. dc.SelectPalette(pcPaletteOld2, FALSE);
  411. }
  412. /***************************************************************************/
  413. void CImgTool::ClickStdPattern(CImgToolWnd* pWnd, const CRect& optionsRect,
  414. const CPoint& clickPoint)
  415. {
  416. CImgTool::OnClickOptions(pWnd, optionsRect, clickPoint);
  417. }
  418. /***************************************************************************/
  419. void CImgTool::PaintStdBrushes(CDC* pDC, const CRect& paintRect,
  420. const CRect& optionsRect)
  421. {
  422. int cxBrush = optionsRect.Width() / 3;
  423. int cyBrush = optionsRect.Height() / 4;
  424. for (UINT nBrushShape = 0; nBrushShape < 4; nBrushShape++)
  425. {
  426. int x = 0;
  427. for (UINT nStrokeWidth = 8 - (nBrushShape == 0);
  428. (int)nStrokeWidth > 0; nStrokeWidth -= 3, x += cxBrush)
  429. {
  430. CRect rect;
  431. rect.left = optionsRect.left + x;
  432. rect.top = optionsRect.top + cyBrush * nBrushShape;
  433. rect.right = rect.left + cxBrush;
  434. rect.bottom = rect.top + cyBrush;
  435. rect.InflateRect(-3, -3);
  436. if ((paintRect & rect).IsRectEmpty())
  437. continue;
  438. BOOL bCur = (nStrokeWidth == m_nStrokeWidth
  439. && nBrushShape == m_nStrokeShape);
  440. CBrush* pOldBrush = pDC->SelectObject(GetSysBrush(bCur ?
  441. COLOR_HIGHLIGHT : COLOR_BTNFACE));
  442. if ((nStrokeWidth & 1) != 0)
  443. {
  444. // Adjust hilight rect so brush will be centered
  445. rect.right -= 1;
  446. rect.bottom -= 1;
  447. }
  448. pDC->PatBlt(rect.left + 1, rect.top - 1,
  449. rect.Width() - 2, rect.Height() + 2, PATCOPY);
  450. pDC->SelectObject(pOldBrush);
  451. CPoint pt(optionsRect.left + (cxBrush - nStrokeWidth) / 2 + x,
  452. optionsRect.top +
  453. (cyBrush - nStrokeWidth) / 2 + nBrushShape * cyBrush);
  454. pOldBrush = pDC->SelectObject(GetSysBrush(bCur ?
  455. COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  456. BrushLine(pDC, pt, pt, nStrokeWidth, nBrushShape);
  457. pDC->SelectObject(pOldBrush);
  458. }
  459. }
  460. }
  461. /***************************************************************************/
  462. void CImgTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect,
  463. const CPoint& clickPoint)
  464. {
  465. MessageBeep(0);
  466. }
  467. /******************************************************************************/
  468. void CImgTool::OnUpdateColors (CImgWnd* pImgWnd)
  469. {
  470. }
  471. /******************************************************************************/
  472. BOOL CImgTool::CanEndMultiptOperation(MTI* pmti )
  473. {
  474. return (! m_bMultPtOpInProgress); // if not in progress (FALSE) => can end (TRUE)
  475. }
  476. /******************************************************************************/
  477. void CImgTool::EndMultiptOperation(BOOL bAbort)
  478. {
  479. m_bMultPtOpInProgress = FALSE;
  480. }
  481. /******************************************************************************/
  482. BOOL CImgTool::IsToolModal(void)
  483. {
  484. return(IsDragging() || m_bMultPtOpInProgress || m_bToggleWithPrev);
  485. }
  486. /******************************************************************************/
  487. BOOL CImgTool::IsUndoable()
  488. {
  489. if (m_bMultPtOpInProgress)
  490. {
  491. return FALSE; // cannot undo in the middle of a multi-point operation.
  492. }
  493. else
  494. {
  495. return m_bIsUndoable;
  496. }
  497. }
  498. /******************************************************************************/
  499. void CImgTool::ClickStdBrushes(CImgToolWnd* pWnd, const CRect& optionsRect,
  500. const CPoint& clickPoint)
  501. {
  502. HideBrush();
  503. g_bCustomBrush = FALSE;
  504. m_nStrokeWidth = 2 + 3 * (2 - (clickPoint.x / (optionsRect.Width() / 3)));
  505. m_nStrokeShape = clickPoint.y / (optionsRect.Height() / 4);
  506. if (m_nStrokeShape == 0)
  507. m_nStrokeWidth -= 1;
  508. pWnd->InvalidateOptions(FALSE);
  509. }
  510. /******************************************************************************/
  511. UINT CImgTool::GetCursorID()
  512. {
  513. return m_nCursorID;
  514. }
  515. /******************************************************************************/
  516. CRect CRubberTool::rcPrev;
  517. // UINT CRubberTool::m_nStrokeWidth;
  518. CRubberTool::CRubberTool()
  519. {
  520. }
  521. /******************************************************************************/
  522. void CRubberTool::OnPaintOptions(CDC* pDC, const CRect& paintRect,
  523. const CRect& optionsRect)
  524. {
  525. if (m_bFilled)
  526. {
  527. PaintStdPattern(pDC, paintRect, optionsRect);
  528. return;
  529. }
  530. #define nLineWidths 5
  531. int cyEach = (optionsRect.Height() - 4) / nLineWidths;
  532. for (int i = 0; i < nLineWidths; i++)
  533. {
  534. UINT cyHeight = i + 1;
  535. CBrush* pOldBrush;
  536. BOOL bCur = (cyHeight == GetStrokeWidth());
  537. pOldBrush = pDC->SelectObject( GetSysBrush(bCur ?
  538. COLOR_HIGHLIGHT : COLOR_BTNFACE));
  539. pDC->PatBlt(optionsRect.left + 2,
  540. optionsRect.top + 3 + i * cyEach,
  541. optionsRect.Width() - 4, cyEach - 2, PATCOPY);
  542. pDC->SelectObject(pOldBrush);
  543. pOldBrush = pDC->SelectObject(GetSysBrush(bCur ?
  544. COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  545. pDC->PatBlt(optionsRect.left + 6,
  546. optionsRect.top + 2 + cyEach * i + (cyEach - cyHeight) / 2,
  547. optionsRect.Width() - 12, cyHeight, PATCOPY);
  548. pDC->SelectObject(pOldBrush);
  549. }
  550. }
  551. /******************************************************************************/
  552. void CRubberTool::OnClickOptions( CImgToolWnd* pWnd, const CRect& optionsRect,
  553. const CPoint& clickPoint )
  554. {
  555. if (m_bFilled)
  556. {
  557. CImgTool::OnClickOptions( pWnd, optionsRect, clickPoint );
  558. return;
  559. }
  560. m_nStrokeWidth = 1 + clickPoint.y /
  561. ((optionsRect.Height() - 4) / nLineWidths);
  562. // fix for rounding errors
  563. if (m_nStrokeWidth > nLineWidths)
  564. {
  565. m_nStrokeWidth = nLineWidths;
  566. }
  567. pWnd->InvalidateOptions(FALSE);
  568. }
  569. /******************************************************************************/
  570. void CClosedFormTool::OnPaintOptions( CDC* pDC, const CRect& paintRect,
  571. const CRect& optionsRect )
  572. {
  573. // Option 0 is Outlined Shape (border and no fill)
  574. // Option 1 is Filled Shape with border
  575. // Option 2 is Filled Shape NO border
  576. #define NUM_CLOSED_FORM_OPTIONS 3 //number of options high
  577. //*DK* Select Palette into DC
  578. CBrush* pOldBrush;
  579. CRect cRectOptionSel; // selection rectangle
  580. CRect cRectOption; //rectangle
  581. int cyEach = (optionsRect.Height() - 4) / NUM_CLOSED_FORM_OPTIONS; // max height of each option
  582. int cyHeight = cyEach - cyEach/2; //rectangle is 1/2 max height
  583. int bCurrSelected = FALSE;
  584. BOOL bFilled = CImgTool::GetCurrent()->IsFilled();
  585. BOOL bBorder = CImgTool::GetCurrent()->HasBorder();
  586. int i;
  587. for (i = 0; i < NUM_CLOSED_FORM_OPTIONS; i++)
  588. {
  589. // Setup the Rectangles for painting and for selection
  590. //Selection Rectangle
  591. cRectOptionSel.SetRect(optionsRect.left + 2,
  592. optionsRect.top + 3 + (i * cyEach),
  593. (optionsRect.left + 2) + optionsRect.Width() - 4,
  594. (optionsRect.top + 3 + (i* cyEach)) + cyEach - 2);
  595. //Option Rectangle
  596. cRectOption.SetRect(optionsRect.left + 6,
  597. optionsRect.top + 2 + i * cyEach + (cyEach - cyHeight) / 2,
  598. (optionsRect.left + 6) + optionsRect.Width() - 12,
  599. (optionsRect.top + 2 + i * cyEach + (cyEach - cyHeight) / 2)
  600. + cyHeight);
  601. // Determine the Selection state for the current item.
  602. bCurrSelected = FALSE;
  603. switch (i)
  604. {
  605. case 0: //Outlined Shape (border, no fill)
  606. if (! bFilled && bBorder)
  607. {
  608. bCurrSelected = TRUE;
  609. }
  610. break;
  611. case 1: // Filled Shape (border and fill)
  612. if ( (bFilled) && (bBorder) )
  613. {
  614. bCurrSelected = TRUE;
  615. }
  616. break;
  617. case 2: // Filled Shape No Border (no border, fill)
  618. if (bFilled && ! bBorder)
  619. {
  620. bCurrSelected = TRUE;
  621. }
  622. break;
  623. default:
  624. bCurrSelected = FALSE;
  625. break;
  626. }
  627. // Draw the selection State
  628. // If selected, use COLOR_HIGHLIGHT else use CMP_COLOR_LTGRAY
  629. pOldBrush = pDC->SelectObject( GetSysBrush( bCurrSelected ?
  630. COLOR_HIGHLIGHT : COLOR_BTNFACE ) );
  631. pDC->PatBlt( cRectOptionSel.left, cRectOptionSel.top,
  632. cRectOptionSel.Width(),cRectOptionSel.Height(), PATCOPY );
  633. pDC->SelectObject(pOldBrush);
  634. CBrush* pborderBrush;
  635. CBrush* pfillBrush;
  636. pborderBrush = GetSysBrush(bCurrSelected ?
  637. COLOR_BTNHIGHLIGHT : COLOR_BTNTEXT);
  638. pfillBrush = GetSysBrush(COLOR_BTNSHADOW);
  639. // Draw the Option
  640. switch (i)
  641. {
  642. case 0: //Outlined Shape (no border, no fill)
  643. pDC->FrameRect(&cRectOption, pborderBrush);
  644. break;
  645. case 1: // Filled Shape (border and fill)
  646. // using fillrect then frame rect instead of rectangle, since
  647. // don't have getsyspen facility in this program.
  648. pDC->FillRect(&cRectOption, pfillBrush);
  649. pDC->FrameRect(&cRectOption, pborderBrush);
  650. break;
  651. case 2: // Filled Shape No Border (no border, fill)
  652. pDC->FillRect(&cRectOption, pfillBrush);
  653. break;
  654. default:
  655. break;
  656. }
  657. }
  658. }
  659. /******************************************************************************/
  660. // clickpoint is from top of optionsrect (i.e. clickpoint if from 0 to optionsrect.height()
  661. // and thus clickpoint is always less than optionsrec.top
  662. void CClosedFormTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect,
  663. const CPoint& clickPoint)
  664. {
  665. int cyEach = (optionsRect.Height() - 4) / NUM_CLOSED_FORM_OPTIONS; // max height of each option
  666. // BOOL bCurrSelected = FALSE;
  667. int i;
  668. for (i = 0; i < NUM_CLOSED_FORM_OPTIONS; i++)
  669. {
  670. if ( clickPoint.y < 3 + ((i+1) * cyEach) )
  671. {
  672. // bCurrSelected = TRUE;
  673. switch (i)
  674. {
  675. default: // default is same as initial
  676. case 0: //Outlined Shape (border, no fill)
  677. m_bFilled = FALSE;
  678. m_bBorder = TRUE;
  679. break;
  680. case 1: // Filled Shape (border and fill)
  681. m_bFilled = TRUE;
  682. m_bBorder = TRUE;
  683. break;
  684. case 2: // Filled Shape No Border (no border, fill)
  685. m_bFilled = TRUE;
  686. m_bBorder = FALSE;
  687. break;
  688. }
  689. break; // point found, break out of loop test
  690. }
  691. }
  692. pWnd->InvalidateOptions(FALSE);
  693. }
  694. /******************************************************************************/
  695. void CRubberTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  696. {
  697. CImgTool::OnStartDrag(pImgWnd, pmti);
  698. SetupRubber(pImgWnd->m_pImg);
  699. OnDrag(pImgWnd, pmti);
  700. }
  701. /******************************************************************************/
  702. void CRubberTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  703. {
  704. OnDrag(pImgWnd, pmti);
  705. CRect rc(pmti->ptDown.x, pmti->ptDown.y, pmti->pt.x, pmti->pt.y);
  706. Render(CDC::FromHandle(pImgWnd->m_pImg->hDC), rc, pmti->fLeft, TRUE, pmti->fCtrlDown);
  707. InvalImgRect(pImgWnd->m_pImg, &rc);
  708. CommitImgRect(pImgWnd->m_pImg, &rc);
  709. pImgWnd->FinishUndo(rc);
  710. ClearStatusBarSize();
  711. CImgTool::OnEndDrag(pImgWnd, pmti);
  712. }
  713. /******************************************************************************/
  714. void CRubberTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  715. {
  716. HPALETTE hpalOld = NULL;
  717. if (theApp.m_pPalette && theApp.m_pPalette->m_hObject)
  718. {
  719. hpalOld = SelectPalette( hRubberDC,
  720. (HPALETTE)theApp.m_pPalette->m_hObject, FALSE ); // Background ??
  721. RealizePalette( hRubberDC );
  722. }
  723. BitBlt(pImgWnd->m_pImg->hDC, rcPrev.left , rcPrev.top,
  724. rcPrev.Width(), rcPrev.Height(),
  725. hRubberDC, rcPrev.left , rcPrev.top, SRCCOPY);
  726. if (hpalOld != NULL)
  727. SelectPalette( hRubberDC, hpalOld, FALSE ); // Background ??
  728. InvalImgRect(pImgWnd->m_pImg, &rcPrev);
  729. PreProcessPoints(pmti);
  730. CRect rc(pmti->ptDown.x, pmti->ptDown.y, pmti->pt.x, pmti->pt.y);
  731. Render(CDC::FromHandle(pImgWnd->m_pImg->hDC), rc, pmti->fLeft, FALSE, pmti->fCtrlDown);
  732. InvalImgRect(pImgWnd->m_pImg, &rc);
  733. rcPrev = rc;
  734. if (m_nCmdID != IDMB_POLYGONTOOL)
  735. {
  736. CSize size( pmti->pt - pmti->ptDown );
  737. if (size.cx < 0)
  738. size.cx -= 1;
  739. else
  740. size.cx += 1;
  741. if (size.cy < 0)
  742. size.cy -= 1;
  743. else
  744. size.cy += 1;
  745. SetStatusBarPosition( pmti->ptDown );
  746. SetStatusBarSize ( size );
  747. }
  748. }
  749. /******************************************************************************/
  750. void CRubberTool::AdjustPointsForConstraint(MTI *pmti)
  751. {
  752. if (pmti != NULL)
  753. {
  754. int iWidthHeight = min( abs(pmti->ptDown.x - pmti->pt.x),
  755. abs(pmti->ptDown.y - pmti->pt.y));
  756. // Set the x value
  757. if (pmti->pt.x < pmti->ptDown.x)
  758. {
  759. pmti->pt.x = pmti->ptDown.x - iWidthHeight;
  760. }
  761. else
  762. {
  763. pmti->pt.x = pmti->ptDown.x + iWidthHeight;
  764. }
  765. // Set the y value
  766. if (pmti->pt.y < pmti->ptDown.y)
  767. {
  768. pmti->pt.y = pmti->ptDown.y - iWidthHeight;
  769. }
  770. else
  771. {
  772. pmti->pt.y = pmti->ptDown.y + iWidthHeight;
  773. }
  774. }
  775. }
  776. /******************************************************************************/
  777. void CRubberTool::Render( CDC* pDC, CRect& rect, BOOL bLeft, BOOL bCommit, BOOL bCtrlDown )
  778. {
  779. int sx;
  780. int sy;
  781. int ex;
  782. int ey;
  783. HBRUSH hBr = NULL;
  784. HPEN hPen = NULL;
  785. HPEN hOldPen = NULL;
  786. HBRUSH hOldBr = NULL;
  787. CPoint pt1;
  788. CPoint pt2;
  789. HDC hDC = pDC->m_hDC;
  790. enum SHAPE { rectangle, roundRect, ellipse } shape;
  791. switch (m_nCmdID)
  792. {
  793. default:
  794. ASSERT(FALSE);
  795. case IDMB_RECTTOOL:
  796. shape = rectangle;
  797. break;
  798. case IDMB_FRECTTOOL:
  799. shape = rectangle;
  800. break;
  801. case IDMB_RNDRECTTOOL:
  802. shape = roundRect;
  803. break;
  804. case IDMB_FRNDRECTTOOL:
  805. shape = roundRect;
  806. break;
  807. case IDMB_ELLIPSETOOL:
  808. shape = ellipse;
  809. break;
  810. case IDMB_FELLIPSETOOL:
  811. shape = ellipse;
  812. break;
  813. }
  814. FixRect(&rect);
  815. pt1.x = rect.left;
  816. pt1.y = rect.top;
  817. pt2.x = rect.right;
  818. pt2.y = rect.bottom;
  819. StandardiseCoords(&pt1, &pt2);
  820. sx = pt1.x;
  821. sy = pt1.y;
  822. ex = pt2.x;
  823. ey = pt2.y;
  824. SetupPenBrush(hDC, bLeft, TRUE, bCtrlDown);
  825. CRect rc(sx, sy, ex, ey);
  826. switch (shape)
  827. {
  828. case rectangle:
  829. Rectangle(hDC, sx, sy, ex, ey);
  830. break;
  831. case roundRect:
  832. RoundRect(hDC, sx, sy, ex, ey, 16, 16);
  833. // The below draws an RoundRect with a mask first then bitblt
  834. // MyRoundRect(hDC, sx, sy, ex, ey, 16, 16, m_bFilled);
  835. // // if border and fill, draw border after fill
  836. // if ( (m_bBorder) && (m_bFilled) )
  837. // {
  838. // MyRoundRect(hDC, sx, sy, ex, ey, 16, 16, !m_bFilled);
  839. // }
  840. break;
  841. case ellipse:
  842. Ellipse(hDC, sx, sy, ex, ey);
  843. // The below draws an Elipse with a mask first then bitblt
  844. // Mylipse(hDC, sx, sy, ex, ey, m_bFilled);
  845. // // if border and fill, draw border after fill
  846. // if ( (m_bBorder) && (m_bFilled) )
  847. // {
  848. // Mylipse(hDC, sx, sy, ex, ey, !m_bFilled);
  849. // }
  850. break;
  851. }
  852. SetupPenBrush(hDC, bLeft, FALSE, bCtrlDown);
  853. }
  854. void CRubberTool::OnActivate( BOOL bActivate )
  855. {
  856. if (bActivate)
  857. {
  858. m_nStrokeWidth = g_nStrokeWidth;
  859. }
  860. else
  861. {
  862. g_nStrokeWidth = m_nStrokeWidth;
  863. }
  864. CImgTool::OnActivate( bActivate );
  865. }
  866. /******************************************************************************/
  867. /*bSetup is true to setup, False to Cleanup */
  868. BOOL CImgTool::SetupPenBrush(HDC hDC, BOOL bLeft, BOOL bSetup, BOOL bCtrlDown)
  869. {
  870. COLORREF colorBorder;
  871. COLORREF colorFill;
  872. if (bCtrlDown && crTrans != TRANS_COLOR_NONE)
  873. {
  874. if (HasBorder ())
  875. {
  876. colorBorder = bLeft ? crTrans : crRight;
  877. colorFill = bLeft ? crRight : crTrans;
  878. }
  879. else
  880. {
  881. colorBorder = bLeft ? crRight : crTrans;
  882. colorFill = bLeft ? crTrans : crRight;
  883. }
  884. }
  885. else
  886. {
  887. if (HasBorder())
  888. {
  889. colorBorder = bLeft ? crLeft : crRight;
  890. colorFill = bLeft ? crRight: crLeft;
  891. }
  892. else
  893. {
  894. colorBorder = bLeft ? crRight : crLeft;
  895. colorFill = bLeft ? crLeft: crRight;
  896. }
  897. }
  898. static HBRUSH hBr = NULL;
  899. static HPEN hPen = NULL;
  900. static HPEN hOldPen = NULL;
  901. static HBRUSH hOldBr = NULL;
  902. static BOOL bCurrentlySetup = FALSE;
  903. BOOL bRC = TRUE;
  904. if (bSetup)
  905. {
  906. if (! bCurrentlySetup)
  907. {
  908. bCurrentlySetup = TRUE;
  909. // select null objects into DC. Depending on drawing mode,
  910. // either or both will be re-selected in to override
  911. hPen = NULL;
  912. hBr = NULL;
  913. hOldPen = (HPEN)SelectObject( hDC, GetStockObject( NULL_PEN ) );
  914. hOldBr = (HBRUSH)SelectObject( hDC, GetStockObject( NULL_BRUSH ) );
  915. if (m_bFilled)
  916. {
  917. hBr = CreateSolidBrush( colorFill );
  918. SelectObject( hDC, hBr );
  919. }
  920. if (m_bBorder)
  921. {
  922. hPen = CreatePen( PS_INSIDEFRAME, m_nStrokeWidth, colorBorder );
  923. SelectObject(hDC, hPen);
  924. }
  925. else
  926. {
  927. //simulate no border by drawing the border the same as the fill.
  928. // since GDI does not draw small elipses, roundrects correctly
  929. // with NULL brush for no border.
  930. // Note the width is 2 so we will dither correctly
  931. hPen = CreatePen(PS_INSIDEFRAME, 2, colorFill);
  932. SelectObject(hDC, hPen);
  933. }
  934. }
  935. else
  936. {
  937. // Error: Will lose allocated Brush/Pen
  938. bRC = FALSE;
  939. }
  940. }
  941. else
  942. {
  943. if (bCurrentlySetup)
  944. {
  945. bCurrentlySetup = FALSE;
  946. SelectObject(hDC, hOldPen);
  947. if (hPen != NULL)
  948. {
  949. DeleteObject(hPen);
  950. }
  951. SelectObject(hDC, hOldBr);
  952. if (hBr != NULL)
  953. {
  954. DeleteObject( hBr );
  955. }
  956. }
  957. else
  958. {
  959. // Error: Cannot Free/cleanup Brush/Pen -- Never allocated.
  960. bRC = FALSE;
  961. }
  962. }
  963. return bRC;
  964. }
  965. #if 0 // unused code
  966. /******************************************************************************/
  967. /*bSetup is true to setup, False to Cleanup */
  968. BOOL CRubberTool::SetupMaskPenBrush(HDC hDC, BOOL bLeft, BOOL bSetup)
  969. {
  970. BOOL bRC = TRUE;
  971. static HBRUSH hBr = NULL;
  972. static HPEN hPen = NULL;
  973. static HPEN hOldPen = NULL;
  974. static HBRUSH hOldBr = NULL;
  975. static BOOL bCurrentlySetup = FALSE;
  976. if (bSetup)
  977. {
  978. if (bCurrentlySetup)
  979. {
  980. // Error: Will lose allocated Brush/Pen
  981. bRC = FALSE;
  982. }
  983. else
  984. {
  985. bCurrentlySetup = TRUE;
  986. // draw the shape on the mask:
  987. // select null objects into DC. Depending on drawing mode,
  988. // either or both will be re-selected in to override
  989. hPen = NULL;
  990. hBr = NULL;
  991. hOldPen = (HPEN)SelectObject(hDC, GetStockObject(NULL_PEN));
  992. hOldBr = (HBRUSH)SelectObject(hDC, GetStockObject(NULL_BRUSH));
  993. if (m_bFilled)
  994. {
  995. SelectObject(hDC, GetStockObject( BLACK_BRUSH ));
  996. }
  997. if (m_bBorder)
  998. {
  999. hPen = CreatePen(PS_INSIDEFRAME, m_nStrokeWidth, (COLORREF)0L );
  1000. SelectObject(hDC, hPen);
  1001. }
  1002. }
  1003. }
  1004. else
  1005. {
  1006. if (bCurrentlySetup)
  1007. {
  1008. bCurrentlySetup = FALSE;
  1009. SelectObject(hDC, hOldPen);
  1010. if (hPen != NULL)
  1011. {
  1012. DeleteObject(hPen);
  1013. }
  1014. SelectObject(hDC, hOldBr);
  1015. if (hBr != NULL)
  1016. {
  1017. DeleteObject(hBr);
  1018. }
  1019. }
  1020. else
  1021. {
  1022. // Error: Cannot Free/cleanup Brush/Pen -- Never allocated.
  1023. bRC = FALSE;
  1024. }
  1025. }
  1026. return bRC;
  1027. }
  1028. #endif // unused code
  1029. /******************************************************************************/
  1030. CRect CFreehandTool::c_undoRect;
  1031. /***************************************************************************/
  1032. CFreehandTool::CFreehandTool()
  1033. {
  1034. m_bUsesBrush = TRUE;
  1035. }
  1036. /******************************************************************************/
  1037. void CFreehandTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  1038. {
  1039. CImgTool::OnStartDrag(pImgWnd, pmti);
  1040. c_undoRect.TopLeft() = c_undoRect.BottomRight() = pmti->pt;
  1041. OnDrag(pImgWnd, pmti);
  1042. }
  1043. /******************************************************************************/
  1044. void CFreehandTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  1045. {
  1046. if (g_bCustomBrush)
  1047. {
  1048. c_undoRect.left -= theImgBrush.m_size.cx + theImgBrush.m_handle.cx;
  1049. c_undoRect.top -= theImgBrush.m_size.cy + theImgBrush.m_handle.cy;
  1050. c_undoRect.right += theImgBrush.m_size.cx - theImgBrush.m_handle.cx;
  1051. c_undoRect.bottom += theImgBrush.m_size.cy - theImgBrush.m_handle.cy;
  1052. }
  1053. else
  1054. {
  1055. // HACK: +1s are to cover bug in slanted line brushes
  1056. c_undoRect.left -= m_nStrokeWidth / 2 + 1;
  1057. c_undoRect.top -= m_nStrokeWidth / 2 + 1;
  1058. c_undoRect.right += (m_nStrokeWidth + 1) / 2 + 1;
  1059. c_undoRect.bottom += (m_nStrokeWidth + 1) / 2 + 1;
  1060. }
  1061. pImgWnd->FinishUndo(c_undoRect);
  1062. CImgTool::OnEndDrag(pImgWnd, pmti);
  1063. }
  1064. /******************************************************************************/
  1065. CSketchTool::CSketchTool()
  1066. {
  1067. m_nCursorID = IDC_BRUSH;
  1068. m_nCmdID = IDMZ_BRUSHTOOL;
  1069. m_bCanBePrevTool = FALSE;
  1070. }
  1071. /******************************************************************************/
  1072. void CSketchTool::OnDrag( CImgWnd* pImgWnd, MTI* pmti )
  1073. {
  1074. fDraggingBrush = FALSE;
  1075. DrawBrush( pImgWnd->m_pImg, pmti->pt, pmti->fLeft );
  1076. if (pmti->pt.x < c_undoRect.left)
  1077. c_undoRect.left = pmti->pt.x;
  1078. else
  1079. if (pmti->pt.x > c_undoRect.right)
  1080. c_undoRect.right = pmti->pt.x;
  1081. if (pmti->pt.y < c_undoRect.top)
  1082. c_undoRect.top = pmti->pt.y;
  1083. else
  1084. if (pmti->pt.y > c_undoRect.bottom)
  1085. c_undoRect.bottom = pmti->pt.y;
  1086. SetStatusBarPosition( pmti->pt );
  1087. }
  1088. /******************************************************************************/
  1089. void CSketchTool::OnCancel(CImgWnd* pImgWnd)
  1090. {
  1091. HideBrush();
  1092. g_bCustomBrush = FALSE;
  1093. SelectPrevious();
  1094. CImgTool::OnCancel( pImgWnd );
  1095. }
  1096. /******************************************************************************/
  1097. CBrushTool::CBrushTool()
  1098. {
  1099. m_nCursorID = IDC_BRUSH;
  1100. m_nCmdID = IDMB_CBRUSHTOOL;
  1101. m_nStrokeWidth = 4;
  1102. }
  1103. /***************************************************************************/
  1104. void CBrushTool::OnPaintOptions( CDC* pDC, const CRect& paintRect,
  1105. const CRect& optionsRect )
  1106. {
  1107. PaintStdBrushes(pDC, paintRect, optionsRect);
  1108. }
  1109. /***************************************************************************/
  1110. void CBrushTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect,
  1111. const CPoint& clickPoint)
  1112. {
  1113. ClickStdBrushes(pWnd, optionsRect, clickPoint);
  1114. }
  1115. /***************************************************************************/
  1116. void CBrushTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  1117. {
  1118. g_bCustomBrush = FALSE;
  1119. CPoint pt1, pt2;
  1120. fDraggingBrush = FALSE;
  1121. pt1 = pmti->ptPrev;
  1122. pt2 = pmti->pt;
  1123. // use transparent color if defined
  1124. if (pmti->fCtrlDown && crTrans != TRANS_COLOR_NONE)
  1125. {
  1126. DrawImgLine( pImgWnd->m_pImg, pt1, pt2, crTrans,
  1127. m_nStrokeWidth, m_nStrokeShape, TRUE);
  1128. }
  1129. else
  1130. {
  1131. DrawImgLine( pImgWnd->m_pImg, pt1, pt2,
  1132. pmti->fLeft ? crLeft : crRight,
  1133. m_nStrokeWidth, m_nStrokeShape, TRUE);
  1134. }
  1135. if (pmti->pt.x < c_undoRect.left)
  1136. c_undoRect.left = pmti->pt.x;
  1137. else if (pmti->pt.x > c_undoRect.right)
  1138. c_undoRect.right = pmti->pt.x;
  1139. if (pmti->pt.y < c_undoRect.top)
  1140. c_undoRect.top = pmti->pt.y;
  1141. else if (pmti->pt.y > c_undoRect.bottom)
  1142. c_undoRect.bottom = pmti->pt.y;
  1143. SetStatusBarPosition(pmti->pt);
  1144. }
  1145. /***************************************************************************/
  1146. void CBrushTool::OnMove(CImgWnd* pImgWnd, MTI* pmti)
  1147. {
  1148. g_bCustomBrush = FALSE;
  1149. CImgTool::OnMove(pImgWnd, pmti);
  1150. }
  1151. /***************************************************************************/
  1152. CPencilTool::CPencilTool()
  1153. {
  1154. m_nCursorID = IDC_PENCIL;
  1155. m_nCmdID = IDMB_PENCILTOOL;
  1156. m_bUsesBrush = FALSE;
  1157. m_nStrokeWidth = 1;
  1158. }
  1159. /***************************************************************************/
  1160. void CPencilTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  1161. {
  1162. CFreehandTool::OnStartDrag(pImgWnd, pmti);
  1163. m_eDrawDirection = eFREEHAND; // initialize to not have a direction
  1164. }
  1165. /***************************************************************************/
  1166. void CPencilTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  1167. {
  1168. g_bCustomBrush = FALSE;
  1169. fDraggingBrush = FALSE;
  1170. PreProcessPoints(pmti);
  1171. // use transparent color if defined
  1172. if (pmti->fCtrlDown && crTrans != TRANS_COLOR_NONE)
  1173. {
  1174. DrawImgLine (pImgWnd->m_pImg, pmti->ptPrev, pmti->pt,
  1175. crTrans, m_nStrokeWidth, m_nStrokeShape, TRUE);
  1176. }
  1177. else
  1178. {
  1179. DrawImgLine(pImgWnd->m_pImg, pmti->ptPrev, pmti->pt,
  1180. pmti->fLeft ? crLeft : crRight,
  1181. m_nStrokeWidth, m_nStrokeShape, TRUE);
  1182. }
  1183. if (pmti->pt.x < c_undoRect.left)
  1184. c_undoRect.left = pmti->pt.x;
  1185. else if (pmti->pt.x > c_undoRect.right)
  1186. c_undoRect.right = pmti->pt.x;
  1187. if (pmti->pt.y < c_undoRect.top)
  1188. c_undoRect.top = pmti->pt.y;
  1189. else if (pmti->pt.y > c_undoRect.bottom)
  1190. c_undoRect.bottom = pmti->pt.y;
  1191. SetStatusBarPosition(pmti->pt);
  1192. }
  1193. /***************************************************************************/
  1194. void CPencilTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  1195. {
  1196. c_undoRect.right += 1;
  1197. c_undoRect.bottom += 1;
  1198. pImgWnd->FinishUndo(c_undoRect);
  1199. CImgTool::OnEndDrag(pImgWnd, pmti); // Bypass CFreehandTool
  1200. }
  1201. /******************************************************************************/
  1202. void CPencilTool::AdjustPointsForConstraint(MTI *pmti)
  1203. {
  1204. eDRAWCONSTRAINTDIRECTION eDrawDirection = DetermineDrawDirection(pmti);
  1205. int iWidthHeight = min( abs(pmti->ptPrev.x - pmti->pt.x),
  1206. abs(pmti->ptPrev.y - pmti->pt.y));
  1207. switch (m_eDrawDirection)
  1208. {
  1209. case eEAST_WEST:
  1210. pmti->pt.y = pmti->ptPrev.y;
  1211. break;
  1212. case eNORTH_SOUTH:
  1213. pmti->pt.x = pmti->ptPrev.x;
  1214. break;
  1215. case eNORTH_WEST:
  1216. case eSOUTH_EAST:
  1217. // Set the SE movement
  1218. if ( (pmti->pt.x > pmti->ptPrev.x) ||
  1219. (pmti->pt.y > pmti->ptPrev.y) )
  1220. {
  1221. pmti->pt.x = pmti->ptPrev.x + iWidthHeight;
  1222. pmti->pt.y = pmti->ptPrev.y + iWidthHeight;
  1223. }
  1224. else
  1225. {
  1226. // Set the NW movement
  1227. if ( (pmti->pt.x < pmti->ptPrev.x) ||
  1228. (pmti->pt.y < pmti->ptPrev.y) )
  1229. {
  1230. pmti->pt.x = pmti->ptPrev.x - iWidthHeight;
  1231. pmti->pt.y = pmti->ptPrev.y - iWidthHeight;
  1232. }
  1233. else
  1234. {
  1235. //invalid movement, set to last known position
  1236. pmti->pt.x = pmti->ptPrev.x;
  1237. pmti->pt.y = pmti->ptPrev.y;
  1238. }
  1239. }
  1240. break;
  1241. case eNORTH_EAST:
  1242. case eSOUTH_WEST:
  1243. // Set the NE movement
  1244. if ( (pmti->pt.x > pmti->ptPrev.x) ||
  1245. (pmti->pt.y < pmti->ptPrev.y) )
  1246. {
  1247. pmti->pt.x = pmti->ptPrev.x + iWidthHeight;
  1248. pmti->pt.y = pmti->ptPrev.y - iWidthHeight;
  1249. }
  1250. else
  1251. {
  1252. // Set the SW movement
  1253. if ( (pmti->pt.x < pmti->ptPrev.x) ||
  1254. (pmti->pt.y > pmti->ptPrev.y) )
  1255. {
  1256. pmti->pt.x = pmti->ptPrev.x - iWidthHeight;
  1257. pmti->pt.y = pmti->ptPrev.y + iWidthHeight;
  1258. }
  1259. else
  1260. {
  1261. //invalid movement, set to last known position
  1262. pmti->pt.x = pmti->ptPrev.x;
  1263. pmti->pt.y = pmti->ptPrev.y;
  1264. }
  1265. }
  1266. break;
  1267. default: // not in constraint mode yet => do nothing.
  1268. // Default is freehand
  1269. break;
  1270. }
  1271. }
  1272. /***************************************************************************/
  1273. CEraserTool::CEraserTool()
  1274. {
  1275. m_nCmdID = IDMB_ERASERTOOL;
  1276. m_nStrokeWidth = 8;
  1277. m_nStrokeShape = squareBrush;
  1278. m_nCursorID = NULL;
  1279. }
  1280. /***************************************************************************/
  1281. void CEraserTool::OnPaintOptions( CDC* pDC, const CRect& paintRect,
  1282. const CRect& optionsRect )
  1283. {
  1284. CRect rect;
  1285. int cxOctant = (optionsRect.Width() + 1);
  1286. int cyOctant = (optionsRect.Height() + 1) / 4;
  1287. rect.left = optionsRect.left;
  1288. rect.top = optionsRect.top;
  1289. rect.right = rect.left + cxOctant;
  1290. rect.bottom = rect.top + cyOctant;
  1291. for (UINT nSize = 4; nSize <= 10; nSize += 2)
  1292. {
  1293. CBrush* pOldBrush;
  1294. if (nSize == m_nStrokeWidth)
  1295. {
  1296. pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT));
  1297. pDC->PatBlt(rect.left + (cxOctant - 14) / 2,
  1298. rect.top + (cyOctant - 14) / 2, 14, 14, PATCOPY);
  1299. pDC->SelectObject(pOldBrush);
  1300. }
  1301. pOldBrush = pDC->SelectObject(GetSysBrush(nSize == m_nStrokeWidth ?
  1302. COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  1303. pDC->PatBlt(rect.left + (cxOctant - nSize) / 2,
  1304. rect.top + (cyOctant - nSize) / 2, nSize, nSize, PATCOPY);
  1305. pDC->SelectObject(pOldBrush);
  1306. rect.top += cyOctant;
  1307. rect.bottom += cyOctant;
  1308. }
  1309. }
  1310. /***************************************************************************/
  1311. void CEraserTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect,
  1312. const CPoint& clickPoint)
  1313. {
  1314. int iOptionNumber;
  1315. int cyOctant = (optionsRect.Height() + 1) / 4;
  1316. iOptionNumber = (clickPoint.y / cyOctant);
  1317. if (iOptionNumber > 3) // there are 4 options, numbered 0,1,2,3
  1318. {
  1319. iOptionNumber = 3;
  1320. }
  1321. m_nStrokeWidth = 4 + 2 * iOptionNumber;
  1322. // int cyOctant = (optionsRect.Height() + 1) / 4;
  1323. // m_nStrokeWidth = 4 + 2 * (clickPoint.y / cyOctant);
  1324. pWnd->InvalidateOptions();
  1325. }
  1326. void CEraserTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  1327. {
  1328. if (pmti->fLeft)
  1329. {
  1330. COLORREF crRealLeftColor = crLeft;
  1331. COLORREF crRealRightColor = crRight;
  1332. crLeft = crRight;
  1333. g_bCustomBrush = FALSE;
  1334. fDraggingBrush = FALSE;
  1335. DrawImgLine(pImgWnd->m_pImg, pmti->ptPrev, pmti->pt, crRight,
  1336. m_nStrokeWidth, squareBrush, TRUE);
  1337. crLeft = crRealLeftColor;
  1338. crRight = crRealRightColor;
  1339. }
  1340. else
  1341. {
  1342. // Just erase pixels that match the drawing color...
  1343. g_bCustomBrush = FALSE;
  1344. fDraggingBrush = FALSE;
  1345. HideBrush();
  1346. CDC* pImageDC = CDC::FromHandle(pImgWnd->m_pImg->hDC);
  1347. CRect rc;
  1348. // Call with NULL DC to get the CRect to use
  1349. DrawDCLine(NULL, pmti->ptPrev, pmti->pt, RGB(255, 255, 255),
  1350. m_nStrokeWidth, squareBrush, rc);
  1351. CTempBitmap monoBitmap;
  1352. CDC monoDc;
  1353. // Create the mono DC and bitmap
  1354. if (!monoDc.CreateCompatibleDC(NULL) ||
  1355. !monoBitmap.CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL))
  1356. {
  1357. theApp.SetGdiEmergency();
  1358. return;
  1359. }
  1360. // Select the bitmap and change the window origin so the mono DC has
  1361. // the same coordinate system as the image
  1362. CBitmap* pOldMonoBitmap = monoDc.SelectObject(&monoBitmap);
  1363. monoDc.SetWindowOrg(rc.left, rc.top);
  1364. // Clear the mono DC and then draw the area that will be changed
  1365. monoDc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), BLACKNESS);
  1366. DrawDCLine(monoDc.m_hDC, pmti->ptPrev, pmti->pt, RGB(255, 255, 255),
  1367. m_nStrokeWidth, squareBrush, rc);
  1368. DebugShowBitmap(monoDc.m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
  1369. // Select the proper palette, and make sure the brush origin is set
  1370. // correctly for pattern brushes
  1371. CPalette* pcPaletteOld = theImgBrush.SetBrushPalette(pImageDC, FALSE);
  1372. pImageDC->SetBrushOrg(0, 0);
  1373. CBrush rightBrush;
  1374. rightBrush.CreateSolidBrush(crRight);
  1375. if (!QuickColorToMono(&monoDc, rc.left, rc.top, rc.Width(), rc.Height(),
  1376. pImageDC, rc.left, rc.top, SRCAND, crLeft))
  1377. {
  1378. // We will get her for DDB's (in which case we could be using a
  1379. // dithered brush) or for high color images (so no palette problems)
  1380. // Create the brush to erase
  1381. CBrush leftBrush;
  1382. leftBrush.CreateSolidBrush(crLeft);
  1383. leftBrush.UnrealizeObject();
  1384. //#define DPSxna 0x00820c49L
  1385. // #define PSDPxax 0x00B8074AL
  1386. // XOR with the pattern so black is where the pattern was
  1387. CBrush* pOldBrush = pImageDC->SelectObject(&leftBrush);
  1388. pImageDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
  1389. DebugShowBitmap(pImageDC->m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
  1390. // Color to mono bitblt to get the final mask
  1391. // The ROP will take all pixels in the source that match the pattern
  1392. // and and them with the white pixels in the dest
  1393. theImgBrush.ColorToMonoBitBlt(&monoDc, rc.left, rc.top, rc.Width(), rc.Height(),
  1394. pImageDC, rc.left, rc.top, SRCAND, RGB(0, 0, 0));
  1395. DebugShowBitmap(monoDc.m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
  1396. // XOR again to put the original back
  1397. pImageDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
  1398. DebugShowBitmap(pImageDC->m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
  1399. pImageDC->SelectObject(pOldBrush);
  1400. }
  1401. // Copy the pattern back into the image where the bitmap has white
  1402. CBrush *pOldBrush = pImageDC->SelectObject(&rightBrush);
  1403. COLORREF crNewBk, crNewText;
  1404. GetMonoBltColors(pImageDC->m_hDC, NULL, crNewBk, crNewText);
  1405. COLORREF crOldBk = pImageDC->SetBkColor(crNewBk);
  1406. COLORREF crOldText = pImageDC->SetTextColor(crNewText);
  1407. pImageDC->BitBlt(rc.left, rc.top, rc.Width(), rc.Height(),
  1408. &monoDc, rc.left, rc.top, DSPDxax);
  1409. pImageDC->SetBkColor(crOldBk);
  1410. pImageDC->SetTextColor(crOldText);
  1411. DebugShowBitmap(pImageDC->m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
  1412. // Clean up stuff we have selected
  1413. pImageDC->SelectObject(pOldBrush);
  1414. monoDc.SelectObject(pOldMonoBitmap);
  1415. if (pcPaletteOld)
  1416. pImageDC->SelectPalette(pcPaletteOld, FALSE);
  1417. InvalImgRect(pImgWnd->m_pImg, &rc);
  1418. CommitImgRect(pImgWnd->m_pImg, &rc);
  1419. }
  1420. if (pmti->pt.x < c_undoRect.left)
  1421. c_undoRect.left = pmti->pt.x;
  1422. else if (pmti->pt.x > c_undoRect.right)
  1423. c_undoRect.right = pmti->pt.x;
  1424. if (pmti->pt.y < c_undoRect.top)
  1425. c_undoRect.top = pmti->pt.y;
  1426. else if (pmti->pt.y > c_undoRect.bottom)
  1427. c_undoRect.bottom = pmti->pt.y;
  1428. SetStatusBarPosition(pmti->pt);
  1429. fDraggingBrush = TRUE;
  1430. pImgWnd->ShowBrush(pmti->pt);
  1431. }
  1432. /***************************************************************************/
  1433. void CEraserTool::OnMove(CImgWnd* pImgWnd, MTI* pmti)
  1434. {
  1435. COLORREF crRealLeftColor;
  1436. COLORREF crRealRightColor;
  1437. crRealLeftColor = crLeft;
  1438. crRealRightColor = crRight;
  1439. crLeft = crRight;
  1440. g_bCustomBrush = FALSE;
  1441. CImgTool::OnMove(pImgWnd, pmti);
  1442. crLeft = crRealLeftColor;
  1443. crRight = crRealRightColor;
  1444. }
  1445. /***************************************************************************/
  1446. void CEraserTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  1447. {
  1448. c_undoRect.left -= m_nStrokeWidth / 2;
  1449. c_undoRect.top -= m_nStrokeWidth / 2;
  1450. c_undoRect.right += (m_nStrokeWidth + 1) / 2;
  1451. c_undoRect.bottom += (m_nStrokeWidth + 1) / 2;
  1452. pImgWnd->FinishUndo(c_undoRect);
  1453. CImgTool::OnEndDrag(pImgWnd, pmti); // Bypass CFreehandTool
  1454. }
  1455. /***************************************************************************/
  1456. void CEraserTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShow)
  1457. {
  1458. if (bShow && g_bBrushVisible)
  1459. {
  1460. CClientDC dc(pImgWnd);
  1461. CRect imageRect;
  1462. pImgWnd->GetImageRect(imageRect);
  1463. dc.IntersectClipRect(&imageRect);
  1464. BOOL bGrid = pImgWnd->IsGridVisible();
  1465. CRect rect = rcDragBrush;
  1466. pImgWnd->ImageToClient(rect);
  1467. dc.PatBlt(rect.left, rect.top,
  1468. rect.Width() + bGrid, 1, BLACKNESS);
  1469. dc.PatBlt(rect.left, rect.top + 1,
  1470. 1, rect.Height() - 2 + bGrid, BLACKNESS);
  1471. dc.PatBlt(rect.right - 1 + bGrid, rect.top + 1,
  1472. 1, rect.Height() - 2 + bGrid, BLACKNESS);
  1473. dc.PatBlt(rect.left, rect.bottom - 1 + bGrid,
  1474. rect.Width() + bGrid, 1, BLACKNESS);
  1475. }
  1476. }
  1477. /***************************************************************************/
  1478. UINT CEraserTool::GetCursorID()
  1479. {
  1480. CPoint point;
  1481. GetCursorPos(&point);
  1482. CRect rc;
  1483. CPBView* pcbView = (CPBView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
  1484. CImgWnd* pImgWnd = pcbView->m_pImgWnd;
  1485. pImgWnd->ScreenToClient(&point);
  1486. pImgWnd->GetClientRect(&rc);
  1487. if (!rc.PtInRect(point))
  1488. {
  1489. // Return crosshair outside the client rect of the image window
  1490. return LOWORD(IDC_CROSSHAIR);
  1491. }
  1492. pImgWnd->ClientToImage(point);
  1493. if (point.x > pImgWnd->m_pImg->cxWidth ||
  1494. point.y > pImgWnd->m_pImg->cyHeight)
  1495. {
  1496. // Return crosshair outside the drawing area
  1497. return LOWORD(IDC_CROSSHAIR);
  1498. }
  1499. return m_nCursorID;
  1500. }
  1501. /***************************************************************************/
  1502. CImageWell CAirBrushTool::c_imageWell(IDB_AIROPT, CSize(24, 24));
  1503. CAirBrushTool::CAirBrushTool()
  1504. {
  1505. m_nCmdID = IDMB_AIRBSHTOOL;
  1506. m_nStrokeWidth = 8;
  1507. m_nCursorID = IDCUR_AIRBRUSH;
  1508. m_bUsesBrush = FALSE;
  1509. m_bFilled = TRUE;
  1510. }
  1511. /***************************************************************************/
  1512. void CAirBrushTool::OnPaintOptions( CDC* pDC, const CRect& paintRect,
  1513. const CRect& optionsRect )
  1514. {
  1515. CPoint pt(optionsRect.left + (optionsRect.Width() / 2 - 24) / 2,
  1516. optionsRect.top + (optionsRect.Height() / 2 - 24) / 2);
  1517. c_imageWell.Open();
  1518. pDC->SetTextColor(GetSysColor(
  1519. m_nStrokeWidth == 8 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  1520. pDC->SetBkColor(GetSysColor(
  1521. m_nStrokeWidth == 8 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));
  1522. c_imageWell.DrawImage(pDC, pt, 0, SRCCOPY);
  1523. pt.x += optionsRect.Width() / 2;
  1524. pDC->SetTextColor(GetSysColor(
  1525. m_nStrokeWidth == 16 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  1526. pDC->SetBkColor(GetSysColor(
  1527. m_nStrokeWidth == 16 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));
  1528. c_imageWell.DrawImage(pDC, pt, 1, SRCCOPY);
  1529. pt.x = optionsRect.left + (optionsRect.Width() - 24) / 2;
  1530. pDC->SetTextColor(GetSysColor(
  1531. m_nStrokeWidth == 24 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  1532. pDC->SetBkColor(GetSysColor(
  1533. m_nStrokeWidth == 24 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));
  1534. pt.y += optionsRect.Height() / 2;
  1535. c_imageWell.DrawImage(pDC, pt, 2, SRCCOPY);
  1536. c_imageWell.Close();
  1537. }
  1538. /***************************************************************************/
  1539. void CAirBrushTool::OnClickOptions(CImgToolWnd* pWnd,
  1540. const CRect& optionsRect, const CPoint& clickPoint)
  1541. {
  1542. UINT nNewStrokeWidth;
  1543. if (clickPoint.y > optionsRect.Height() / 2)
  1544. nNewStrokeWidth = 24;
  1545. else if (clickPoint.x > optionsRect.Width() / 2)
  1546. nNewStrokeWidth = 16;
  1547. else
  1548. nNewStrokeWidth = 8;
  1549. if (nNewStrokeWidth != m_nStrokeWidth)
  1550. SetStrokeWidth(nNewStrokeWidth);
  1551. }
  1552. /***************************************************************************/
  1553. void CAirBrushTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  1554. {
  1555. pImgWnd->SetTimer(1, 0, NULL); // FUTURE: rate should be adjustable
  1556. CFreehandTool::OnStartDrag(pImgWnd, pmti);
  1557. }
  1558. /***************************************************************************/
  1559. void CAirBrushTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  1560. {
  1561. CPoint pt;
  1562. CRect rect;
  1563. fDraggingBrush = FALSE;
  1564. int nDiam = (m_nStrokeWidth + 1) & ~1; // nDiam must be even
  1565. if (nDiam < 4)
  1566. nDiam = 4;
  1567. int nRadius = nDiam / 2;
  1568. int nRadiusSquared = (nDiam / 2) * (nDiam / 2);
  1569. // Start a bounding rect for changes made in the following loop
  1570. rect.left = rect.right = pmti->pt.x;
  1571. rect.top = rect.bottom = pmti->pt.y;
  1572. m_bCtrlDown = pmti->fCtrlDown; // save it for the timer
  1573. SetupPenBrush(pImgWnd->m_pImg->hDC, !pmti->fLeft, TRUE, m_bCtrlDown);
  1574. for (int i = 0; i < 10; i++)
  1575. {
  1576. // Loop here until we randomly pick a point inside a circle
  1577. // centered around the mouse with a diameter of m_nStrokeWidth...
  1578. #ifdef _DEBUG
  1579. int nTrys = 0;
  1580. #endif
  1581. do
  1582. {
  1583. #ifdef _DEBUG
  1584. if (nTrys++ > 10)
  1585. {
  1586. TRACE(TEXT("The airbrush is clogged!\n"));
  1587. break;
  1588. }
  1589. #endif
  1590. pt = pmti->pt;
  1591. pt.x += (rand() % (nDiam + 1)) - nRadius;
  1592. pt.y += (rand() % (nDiam + 1)) - nRadius;
  1593. }
  1594. while (((pt.x - pmti->pt.x) * (pt.x - pmti->pt.x) +
  1595. (pt.y - pmti->pt.y) * (pt.y - pmti->pt.y)) > nRadiusSquared);
  1596. PatBlt(pImgWnd->m_pImg->hDC, pt.x, pt.y, 1, 1, PATCOPY);
  1597. if (pt.x < rect.left)
  1598. rect.left = pt.x;
  1599. else if (pt.x + 1 > rect.right)
  1600. rect.right = pt.x + 1;
  1601. if (pt.y < rect.top)
  1602. rect.top = pt.y;
  1603. else if (pt.y + 1 > rect.bottom)
  1604. rect.bottom = pt.y + 1;
  1605. }
  1606. SetupPenBrush(pImgWnd->m_pImg->hDC, !pmti->fLeft, FALSE, m_bCtrlDown);
  1607. c_undoRect |= rect;
  1608. InvalImgRect(pImgWnd->m_pImg, &rect);
  1609. CommitImgRect(pImgWnd->m_pImg, &rect);
  1610. SetStatusBarPosition(pmti->pt);
  1611. }
  1612. /***************************************************************************/
  1613. void CAirBrushTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  1614. {
  1615. ::KillTimer(pImgWnd->GetSafeHwnd(), 1);
  1616. CFreehandTool::OnEndDrag(pImgWnd, pmti);
  1617. }
  1618. /***************************************************************************/
  1619. void CAirBrushTool::OnTimer(CImgWnd* pImgWnd, MTI* pmti)
  1620. {
  1621. pmti->fCtrlDown = m_bCtrlDown;
  1622. OnDrag(pImgWnd, pmti);
  1623. }
  1624. /***************************************************************************/
  1625. void CAirBrushTool::OnCancel(CImgWnd* pImgWnd)
  1626. {
  1627. ::KillTimer(pImgWnd->GetSafeHwnd(), 1);
  1628. CImgTool::OnCancel(pImgWnd);
  1629. }
  1630. /***************************************************************************/
  1631. CLineTool::CLineTool()
  1632. {
  1633. m_bUsesBrush = FALSE;
  1634. m_nStrokeWidth = 1;
  1635. m_nCmdID = IDMB_LINETOOL;
  1636. }
  1637. /***************************************************************************/
  1638. void CLineTool::Render(CDC* pDC, CRect& rect, BOOL bLeft, BOOL bCommit, BOOL bCtrlDown)
  1639. {
  1640. COLORREF color;
  1641. // use transparent color if defined
  1642. if (bCtrlDown && crTrans != TRANS_COLOR_NONE)
  1643. {
  1644. color = crTrans;
  1645. }
  1646. else
  1647. {
  1648. color = bLeft ? crLeft : crRight;
  1649. }
  1650. int sx = rect.left;
  1651. int sy = rect.top;
  1652. int ex = rect.right;
  1653. int ey = rect.bottom;
  1654. DrawImgLine( pImgCur, rect.TopLeft(), rect.BottomRight(), color,
  1655. m_nStrokeWidth, m_nStrokeShape, FALSE );
  1656. CRect rc;
  1657. if (sx < ex)
  1658. {
  1659. rc.left = sx;
  1660. rc.right = ex + 1;
  1661. }
  1662. else
  1663. {
  1664. rc.left = ex;
  1665. rc.right = sx + 1;
  1666. }
  1667. if (sy < ey)
  1668. {
  1669. rc.top = sy;
  1670. rc.bottom = ey + 1;
  1671. }
  1672. else
  1673. {
  1674. rc.top = ey;
  1675. rc.bottom = sy + 1;
  1676. }
  1677. rc.left -= m_nStrokeWidth;
  1678. rc.top -= m_nStrokeWidth;
  1679. rc.right += m_nStrokeWidth;
  1680. rc.bottom += m_nStrokeWidth;
  1681. rect = rc;
  1682. }
  1683. /******************************************************************************/
  1684. // Given an x and y coordinate, we can calculate the angle from the x axis in
  1685. // the right triangle using the Tan(a) algorithm. Where
  1686. // tan(a) = opposite/adjacent or y/x.
  1687. //
  1688. // In order to constrain the line drawing, we need to determine the angle
  1689. // from the x axis and constrain it to the nearest 45 degree line (0 degree,
  1690. // 45 degree, 90 degree,....).
  1691. //
  1692. // Thus we can use the following rule :
  1693. //
  1694. // 0 Degrees <= Angle < 45/2 Degrees Constrained to 0 Degrees
  1695. // 45/2 Degrees <= Angle < 45+45/2 Degrees Constrained to 45 Degrees
  1696. // 45+45/2 Degrees <= Angle < 90 Degrees Constrained to 90 Degrees
  1697. //
  1698. //
  1699. // We can translate this rule into the below using tan(angle) = y/x and the
  1700. // fact that Tan(0) = 0, Tan(22.5) = .414, tan(67.5) = 2.414, tan(90) = infinity
  1701. //
  1702. // 0 <= y/x < .414 Constrained to 0 Degrees
  1703. // .414 <= y/x < 2.414 Constrained to 45 Degrees
  1704. // 2.414 <= y/x Constrained to 90 Degrees
  1705. //
  1706. // For more precision, we will multiply everything by 1000 to give us finally
  1707. // the following table
  1708. //
  1709. // 0 <= (1000*y)/x < 414 Constrained to 0 Degrees
  1710. // 414 <= (1000*y)/x < 2414 Constrained to 45 Degrees
  1711. // 2414 <= (1000*y)/x Constrained to 90 Degrees
  1712. void CLineTool::AdjustPointsForConstraint(MTI *pmti)
  1713. {
  1714. if (pmti != NULL)
  1715. {
  1716. int iAngle = 0;
  1717. long lcy = abs( (pmti->ptDown).y - (pmti->pt).y );
  1718. long lcx = abs( (pmti->ptDown).x - (pmti->pt).x );
  1719. long lResult;
  1720. if (lcx != 0)
  1721. {
  1722. lResult = (lcy*1000)/lcx;
  1723. }
  1724. else
  1725. {
  1726. lResult = 2414; // default to 90 degrees if x value is 0.
  1727. }
  1728. if (lResult >= 2414)
  1729. {
  1730. iAngle = 90;
  1731. }
  1732. else
  1733. {
  1734. if (lResult >= 414)
  1735. {
  1736. iAngle = 45;
  1737. }
  1738. else
  1739. {
  1740. iAngle = 0;
  1741. }
  1742. }
  1743. // int iWidthHeight = min( abs(pmti->ptDown.x - pmti->pt.x),
  1744. // abs(pmti->ptDown.y - pmti->pt.y));
  1745. int iWidthHeight = ( abs(pmti->ptDown.x - pmti->pt.x) +
  1746. abs(pmti->ptDown.y - pmti->pt.y) ) / 2 ;
  1747. switch (iAngle)
  1748. {
  1749. default: //if for some reason, angle is not valid case, use 0
  1750. case 0:
  1751. pmti->pt.y = pmti->ptDown.y;
  1752. break;
  1753. case 45:
  1754. if (pmti->pt.x < pmti->ptDown.x)
  1755. {
  1756. pmti->pt.x = pmti->ptDown.x - iWidthHeight;
  1757. }
  1758. else
  1759. {
  1760. pmti->pt.x = pmti->ptDown.x + iWidthHeight;
  1761. }
  1762. if (pmti->pt.y < pmti->ptDown.y)
  1763. {
  1764. pmti->pt.y = pmti->ptDown.y - iWidthHeight;
  1765. }
  1766. else
  1767. {
  1768. pmti->pt.y = pmti->ptDown.y + iWidthHeight;
  1769. }
  1770. break;
  1771. case 90:
  1772. pmti->pt.x = pmti->ptDown.x;
  1773. break;
  1774. }
  1775. }
  1776. }
  1777. /***************************************************************************/
  1778. CRectTool::CRectTool()
  1779. {
  1780. m_nCmdID = IDMB_RECTTOOL;
  1781. }
  1782. /***************************************************************************/
  1783. CRoundRectTool::CRoundRectTool()
  1784. {
  1785. m_nCmdID = IDMB_RNDRECTTOOL;
  1786. }
  1787. /***************************************************************************/
  1788. CEllipseTool::CEllipseTool()
  1789. {
  1790. m_nCmdID = IDMB_ELLIPSETOOL;
  1791. }
  1792. /***************************************************************************/
  1793. CPickColorTool::CPickColorTool()
  1794. {
  1795. m_bIsUndoable = FALSE;
  1796. m_bCanBePrevTool = FALSE;
  1797. m_bToggleWithPrev = TRUE;
  1798. m_Color = ::GetSysColor( COLOR_BTNFACE );
  1799. m_nCursorID = IDC_EYEDROP;
  1800. m_nCmdID = IDMY_PICKCOLOR;
  1801. }
  1802. /***************************************************************************/
  1803. void CPickColorTool::OnActivate(BOOL bActivate)
  1804. {
  1805. g_bPickingColor = bActivate;
  1806. m_Color = ::GetSysColor( COLOR_BTNFACE );
  1807. CImgTool::OnActivate(bActivate);
  1808. }
  1809. /***************************************************************************/
  1810. void CPickColorTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  1811. {
  1812. CImgTool::OnStartDrag(pImgWnd, pmti);
  1813. OnDrag(pImgWnd, pmti);
  1814. }
  1815. /***************************************************************************/
  1816. void CPickColorTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  1817. {
  1818. COLORREF cr = GetPixel(pImgWnd->m_pImg->hDC, pmti->pt.x, pmti->pt.y);
  1819. BYTE red = GetRValue( cr );
  1820. BYTE green = GetGValue( cr );
  1821. BYTE blue = GetBValue( cr );
  1822. if (theApp.m_bPaletted)
  1823. m_Color = PALETTERGB( red, green, blue );
  1824. else
  1825. m_Color = RGB( red, green, blue );
  1826. if (g_pImgToolWnd && g_pImgToolWnd->m_hWnd &&
  1827. IsWindow(g_pImgToolWnd->m_hWnd) )
  1828. g_pImgToolWnd->InvalidateOptions();
  1829. }
  1830. /***************************************************************************/
  1831. void CPickColorTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  1832. {
  1833. if (pmti->fCtrlDown) // pick transparent color
  1834. {
  1835. SetTransColor (m_Color);
  1836. }
  1837. else if (pmti->fLeft)
  1838. SetDrawColor ( m_Color );
  1839. else
  1840. SetEraseColor( m_Color );
  1841. m_Color = ::GetSysColor( COLOR_BTNFACE );
  1842. if (g_pImgToolWnd && g_pImgToolWnd->m_hWnd &&
  1843. IsWindow(g_pImgToolWnd->m_hWnd) )
  1844. g_pImgToolWnd->InvalidateOptions();
  1845. SelectPrevious();
  1846. CImgTool::OnEndDrag( pImgWnd, pmti );
  1847. }
  1848. /***************************************************************************/
  1849. void CPickColorTool::OnCancel(CImgWnd* pImgWnd)
  1850. {
  1851. SelectPrevious();
  1852. CImgTool::OnCancel(pImgWnd);
  1853. }
  1854. /***************************************************************************/
  1855. void CPickColorTool::OnPaintOptions( CDC* pDC, const CRect& paintRect,
  1856. const CRect& optionsRect )
  1857. {
  1858. CPalette* pOldPal = NULL;
  1859. if (theApp.m_pPalette)
  1860. {
  1861. pOldPal = pDC->SelectPalette( theApp.m_pPalette, FALSE );
  1862. pDC->RealizePalette();
  1863. }
  1864. CBrush br;
  1865. if (br.CreateSolidBrush( m_Color ))
  1866. {
  1867. pDC->FillRect( &paintRect, &br );
  1868. br.DeleteObject();
  1869. }
  1870. if (pOldPal)
  1871. pDC->SelectPalette( pOldPal, FALSE );
  1872. }
  1873. /***************************************************************************/
  1874. CFloodTool::CFloodTool()
  1875. {
  1876. m_nCursorID = IDC_FLOOD;
  1877. m_nCmdID = IDMB_FILLTOOL;
  1878. m_bFilled = TRUE;
  1879. }
  1880. /***************************************************************************/
  1881. void CFloodTool::OnPaintOptions(CDC* pDC, const CRect& paintRect,
  1882. const CRect& optionsRect)
  1883. {
  1884. // PaintStdPattern(pDC, paintRect, optionsRect);
  1885. }
  1886. /***************************************************************************/
  1887. void CFloodTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect,
  1888. const CPoint& clickPoint)
  1889. {
  1890. CImgTool::OnClickOptions(pWnd, optionsRect, clickPoint);
  1891. }
  1892. /***************************************************************************/
  1893. void CFloodTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  1894. {
  1895. CImgTool::OnStartDrag( pImgWnd, pmti );
  1896. CPalette *pcPaletteOld = NULL;
  1897. IMG* pimg = pImgWnd->m_pImg;
  1898. CDC* pDC = CDC::FromHandle( pimg->hDC );
  1899. CBrush brush;
  1900. CBrush* pOldBrush = NULL;
  1901. COLORREF color;
  1902. if (pmti->fCtrlDown && crTrans != TRANS_COLOR_NONE)
  1903. {
  1904. color = crTrans;
  1905. }
  1906. else
  1907. {
  1908. color = pmti->fLeft ? crLeft : crRight;
  1909. }
  1910. if (theApp.m_pPalette)
  1911. {
  1912. pcPaletteOld = pDC->SelectPalette( theApp.m_pPalette, FALSE );
  1913. pDC->RealizePalette();
  1914. }
  1915. if (brush.CreateSolidBrush( color ))
  1916. {
  1917. pOldBrush = pDC->SelectObject( &brush );
  1918. COLORREF crFillThis = pDC->GetPixel( pmti->pt.x, pmti->pt.y );
  1919. BYTE iRed = GetRValue( crFillThis );
  1920. BYTE iGreen = GetGValue( crFillThis );
  1921. BYTE iBlue = GetBValue( crFillThis );
  1922. if (theApp.m_bPaletted)
  1923. crFillThis = PALETTERGB( iRed, iGreen, iBlue );
  1924. else
  1925. crFillThis = RGB( iRed, iGreen, iBlue );
  1926. pDC->ExtFloodFill( pmti->pt.x,
  1927. pmti->pt.y, crFillThis, FLOODFILLSURFACE );
  1928. pDC->SelectObject( pOldBrush );
  1929. InvalImgRect ( pimg, NULL );
  1930. CommitImgRect( pimg, NULL );
  1931. }
  1932. else
  1933. {
  1934. theApp.SetGdiEmergency();
  1935. }
  1936. if (pcPaletteOld)
  1937. pDC->SelectPalette( pcPaletteOld, FALSE );
  1938. }
  1939. /***************************************************************************/
  1940. void CFloodTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  1941. {
  1942. pImgWnd->FinishUndo(CRect(0, 0,
  1943. pImgWnd->m_pImg->cxWidth, pImgWnd->m_pImg->cyHeight));
  1944. CImgTool::OnEndDrag(pImgWnd, pmti);
  1945. }
  1946. /***************************************************************************/
  1947. CRect CSelectTool::c_selectRect;
  1948. CImageWell CSelectTool::c_imageWell(IDB_SELOPT, CSize(37, 23));
  1949. CSelectTool::CSelectTool()
  1950. {
  1951. m_bIsUndoable = FALSE;
  1952. m_nCmdID = IDMB_PICKTOOL;
  1953. m_bCanBePrevTool = FALSE;
  1954. }
  1955. /***************************************************************************/
  1956. void CSelectTool::OnPaintOptions( CDC* pDC, const CRect& paintRect,
  1957. const CRect& optionsRect )
  1958. {
  1959. CPoint pt(optionsRect.left + (optionsRect.Width() - 37) / 2,
  1960. optionsRect.top + (optionsRect.Height() / 2 - 23) / 2);
  1961. CRect selRect(pt.x - 3, pt.y - 3, pt.x + 37 + 3, pt.y + 23 + 3);
  1962. CBrush* pOldBrush;
  1963. pOldBrush = pDC->SelectObject( GetSysBrush(theImgBrush.m_bOpaque ?
  1964. COLOR_HIGHLIGHT : COLOR_BTNFACE));
  1965. pDC->PatBlt(selRect.left, selRect.top,
  1966. selRect.Width(), selRect.Height(), PATCOPY);
  1967. pDC->SelectObject(pOldBrush);
  1968. selRect.OffsetRect(0, optionsRect.Height() / 2);
  1969. pOldBrush = pDC->SelectObject(GetSysBrush(theImgBrush.m_bOpaque ?
  1970. COLOR_BTNFACE : COLOR_HIGHLIGHT));
  1971. pDC->PatBlt(selRect.left, selRect.top,
  1972. selRect.Width(), selRect.Height(), PATCOPY);
  1973. pDC->SelectObject(pOldBrush);
  1974. c_imageWell.Open();
  1975. c_imageWell.DrawImage(pDC, pt, 0);
  1976. pt.y += optionsRect.Height() / 2;
  1977. c_imageWell.DrawImage(pDC, pt, 1);
  1978. c_imageWell.Close();
  1979. }
  1980. /***************************************************************************/
  1981. void CSelectTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect,
  1982. const CPoint& clickPoint)
  1983. {
  1984. BOOL bNewOpaque = clickPoint.y < optionsRect.Height() / 2;
  1985. if (bNewOpaque != theImgBrush.m_bOpaque)
  1986. {
  1987. HideBrush();
  1988. theImgBrush.m_bOpaque = bNewOpaque;
  1989. theImgBrush.RecalcMask(crRight);
  1990. CImgWnd::GetCurrent()->MoveBrush(theImgBrush.m_rcSelection);
  1991. pWnd->InvalidateOptions();
  1992. }
  1993. }
  1994. /***************************************************************************/
  1995. void CSelectTool::InvertSelectRect(CImgWnd* pImgWnd)
  1996. {
  1997. if (c_selectRect.IsRectEmpty())
  1998. return;
  1999. CClientDC dc( pImgWnd );
  2000. CBrush* pOldBrush = NULL;
  2001. int iLineWidth = pImgWnd->GetZoom();
  2002. if (g_brSelectHorz.m_hObject != NULL)
  2003. pOldBrush = dc.SelectObject( &g_brSelectHorz );
  2004. else
  2005. pOldBrush = (CBrush*)dc.SelectStockObject( BLACK_BRUSH );
  2006. CRect invertRect = c_selectRect;
  2007. pImgWnd->ImageToClient( invertRect );
  2008. int iWidth = invertRect.Width();
  2009. int iHeight = invertRect.Height();
  2010. dc.PatBlt( invertRect.left, invertRect.top, iWidth - iLineWidth, iLineWidth, PATINVERT );
  2011. dc.PatBlt( invertRect.left, invertRect.top + iHeight - iLineWidth, iWidth - iLineWidth, iLineWidth, PATINVERT );
  2012. if (g_brSelectVert.m_hObject != NULL)
  2013. dc.SelectObject( &g_brSelectVert );
  2014. dc.PatBlt( invertRect.left, invertRect.top + iLineWidth * 2, iLineWidth, iHeight - iLineWidth * 3, PATINVERT );
  2015. dc.PatBlt( invertRect.right - iLineWidth, invertRect.top, iLineWidth, iHeight, PATINVERT );
  2016. if (pOldBrush != NULL)
  2017. dc.SelectObject( pOldBrush );
  2018. }
  2019. /***************************************************************************/
  2020. void CSelectTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShow)
  2021. {
  2022. if (!bShow)
  2023. {
  2024. InvertSelectRect(pImgWnd);
  2025. c_selectRect.SetRect(0, 0, 0, 0);
  2026. }
  2027. }
  2028. /***************************************************************************/
  2029. void CSelectTool::OnActivate(BOOL bActivate)
  2030. {
  2031. if (!bActivate)
  2032. {
  2033. if (theImgBrush.m_pImg != NULL)
  2034. {
  2035. if (! theImgBrush.m_bFirstDrag)
  2036. CommitSelection(TRUE);
  2037. InvalImgRect(theImgBrush.m_pImg, NULL); // erase selection tracker
  2038. theImgBrush.m_pImg = NULL;
  2039. }
  2040. }
  2041. CImgTool::OnActivate(bActivate);
  2042. }
  2043. /***************************************************************************/
  2044. void CSelectTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  2045. {
  2046. CImgTool::OnStartDrag(pImgWnd, pmti);
  2047. CommitSelection(TRUE);
  2048. pImgWnd->EraseTracker();
  2049. theImgBrush.m_bMakingSelection = TRUE;
  2050. }
  2051. /***************************************************************************/
  2052. void CSelectTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti)
  2053. {
  2054. CRect newSelectRect(pmti->ptDown.x, pmti->ptDown.y,
  2055. pmti->pt.x, pmti->pt.y);
  2056. FixRect(&newSelectRect);
  2057. newSelectRect.right += 1;
  2058. newSelectRect.bottom += 1;
  2059. if (newSelectRect.left < 0)
  2060. newSelectRect.left = 0;
  2061. if (newSelectRect.top < 0)
  2062. newSelectRect.top = 0;
  2063. if (newSelectRect.right > pImgWnd->GetImg()->cxWidth)
  2064. newSelectRect.right = pImgWnd->GetImg()->cxWidth;
  2065. if (newSelectRect.bottom > pImgWnd->GetImg()->cyHeight)
  2066. newSelectRect.bottom = pImgWnd->GetImg()->cyHeight;
  2067. if (newSelectRect != c_selectRect)
  2068. {
  2069. InvertSelectRect(pImgWnd);
  2070. c_selectRect = newSelectRect;
  2071. InvertSelectRect(pImgWnd);
  2072. }
  2073. SetStatusBarPosition(pmti->ptDown);
  2074. SetStatusBarSize(c_selectRect.Size());
  2075. }
  2076. /***************************************************************************/
  2077. void CSelectTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  2078. {
  2079. InvertSelectRect(pImgWnd);
  2080. c_selectRect.SetRect(0, 0, 0, 0);
  2081. CRect rcPick;
  2082. theImgBrush.m_bMakingSelection = FALSE;
  2083. if (pmti->ptDown.x > pmti->pt.x)
  2084. {
  2085. rcPick.left = pmti->pt.x;
  2086. rcPick.right = pmti->ptDown.x;
  2087. }
  2088. else
  2089. {
  2090. rcPick.left = pmti->ptDown.x;
  2091. rcPick.right = pmti->pt.x;
  2092. }
  2093. if (pmti->ptDown.y > pmti->pt.y)
  2094. {
  2095. rcPick.top = pmti->pt.y;
  2096. rcPick.bottom = pmti->ptDown.y;
  2097. }
  2098. else
  2099. {
  2100. rcPick.top = pmti->ptDown.y;
  2101. rcPick.bottom = pmti->pt.y;
  2102. }
  2103. if (rcPick.left < 0)
  2104. rcPick.left = 0;
  2105. if (rcPick.top < 0)
  2106. rcPick.top = 0;
  2107. if (rcPick.right > pImgWnd->m_pImg->cxWidth - 1)
  2108. rcPick.right = pImgWnd->m_pImg->cxWidth - 1;
  2109. if (rcPick.bottom > pImgWnd->m_pImg->cyHeight - 1)
  2110. rcPick.bottom = pImgWnd->m_pImg->cyHeight - 1;
  2111. if (rcPick.Width() == 0 || rcPick.Height() == 0)
  2112. {
  2113. theImgBrush.TopLeftHandle();
  2114. theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE;
  2115. g_bCustomBrush = FALSE;
  2116. SetCombineMode(combineColor);
  2117. InvalImgRect(pImgWnd->m_pImg, NULL); // redraw selection
  2118. theImgBrush.m_pImg = NULL;
  2119. }
  2120. else
  2121. {
  2122. rcPick.right += 1;
  2123. rcPick.bottom += 1;
  2124. pImgWnd->MakeBrush(pImgWnd->m_pImg->hDC, rcPick );
  2125. }
  2126. ClearStatusBarSize();
  2127. CImgTool::OnEndDrag(pImgWnd, pmti);
  2128. if (pmti->fRight && !pmti->fLeft)
  2129. {
  2130. CPoint pt = pmti->pt;
  2131. pImgWnd->OnRButtonDownInSel(&pt);
  2132. }
  2133. }
  2134. /***************************************************************************/
  2135. void CSelectTool::OnCancel(CImgWnd* pImgWnd)
  2136. {
  2137. if (! theImgBrush.m_bMakingSelection && CWnd::GetCapture() != pImgWnd)
  2138. {
  2139. // We were not selecting or dragging, just cancel the select tool...
  2140. CommitSelection(TRUE);
  2141. theImgBrush.TopLeftHandle();
  2142. theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE;
  2143. g_bCustomBrush = FALSE;
  2144. SetCombineMode(combineColor);
  2145. if (theImgBrush.m_pImg != NULL)
  2146. InvalImgRect(theImgBrush.m_pImg, NULL); // redraw selection
  2147. theImgBrush.m_pImg = NULL;
  2148. CImgTool::OnCancel(pImgWnd);
  2149. return;
  2150. }
  2151. if (!theImgBrush.m_bMakingSelection && CWnd::GetCapture() == pImgWnd)
  2152. {
  2153. HideBrush();
  2154. if (!theImgBrush.m_bMoveSel && !theImgBrush.m_bSmearSel)
  2155. {
  2156. if (g_bCustomBrush)
  2157. {
  2158. theImgBrush.TopLeftHandle();
  2159. g_bCustomBrush = FALSE;
  2160. SetCombineMode(combineColor);
  2161. }
  2162. else
  2163. {
  2164. if (theImgBrush.m_pImg)
  2165. CommitSelection(TRUE);
  2166. InvalImgRect(pImgWnd->m_pImg, NULL); // erase the dragger
  2167. }
  2168. }
  2169. }
  2170. InvertSelectRect(pImgWnd);
  2171. c_selectRect.SetRect(0, 0, 0, 0);
  2172. theImgBrush.TopLeftHandle();
  2173. g_bCustomBrush = FALSE;
  2174. theImgBrush.m_pImg = NULL;
  2175. theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE;
  2176. theImgBrush.m_bMakingSelection = FALSE;
  2177. InvalImgRect(pImgWnd->m_pImg, NULL);
  2178. CImgTool::OnCancel(pImgWnd);
  2179. }
  2180. /***************************************************************************/
  2181. BOOL CSelectTool::IsToolModal(void)
  2182. {
  2183. if (theImgBrush.m_pImg)
  2184. {
  2185. return(TRUE);
  2186. }
  2187. return(CImgTool::IsToolModal());
  2188. }
  2189. /***************************************************************************/
  2190. UINT CSelectTool::GetCursorID()
  2191. {
  2192. CPoint point;
  2193. GetCursorPos(&point);
  2194. CImgWnd* pImgWnd = (CImgWnd*)CWnd::WindowFromPoint(point);
  2195. if (pImgWnd->IsKindOf(RUNTIME_CLASS(CImgWnd))
  2196. && pImgWnd->GetImg() == pImgCur
  2197. && theImgBrush.m_pImg != NULL)
  2198. {
  2199. pImgWnd->ScreenToClient(&point);
  2200. pImgWnd->ClientToImage(point);
  2201. if (theImgBrush.m_rcSelection.PtInRect(point))
  2202. return IDCUR_MOVE;
  2203. }
  2204. return m_nCursorID;
  2205. }
  2206. /***************************************************************************/
  2207. CRect CZoomTool::c_zoomRect;
  2208. CImgWnd* CZoomTool::c_pImgWnd;
  2209. CImageWell CZoomTool::c_imageWell(IDB_ZOOMOPT, CSize(23, 9));
  2210. /***************************************************************************/
  2211. CZoomTool::CZoomTool()
  2212. {
  2213. m_bIsUndoable = FALSE;
  2214. m_bCanBePrevTool = FALSE;
  2215. m_bToggleWithPrev = TRUE;
  2216. m_nCursorID = IDC_ZOOMIN;
  2217. m_nCmdID = IDMB_ZOOMTOOL;
  2218. }
  2219. /***************************************************************************/
  2220. void CZoomTool::OnPaintOptions( CDC* pDC, const CRect& paintRect,
  2221. const CRect& optionsRect )
  2222. {
  2223. int nCurZoom = CImgWnd::GetCurrent()->GetZoom();
  2224. int dy = optionsRect.Height() / 4;
  2225. CPoint pt(optionsRect.left + (optionsRect.Width() - 23) / 2,
  2226. optionsRect.top + optionsRect.Height() / dy);
  2227. c_imageWell.Open();
  2228. if (nCurZoom == 1)
  2229. {
  2230. CBrush* pOldBrush;
  2231. pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT));
  2232. pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4,
  2233. PATCOPY);
  2234. pDC->SelectObject(pOldBrush);
  2235. }
  2236. pDC->SetTextColor(GetSysColor(
  2237. nCurZoom == 1 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  2238. pDC->SetBkColor(GetSysColor(
  2239. nCurZoom == 1 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));
  2240. c_imageWell.DrawImage(pDC, pt, 0, SRCCOPY);
  2241. pt.y += dy;
  2242. if (nCurZoom == 2)
  2243. {
  2244. CBrush* pOldBrush;
  2245. pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT));
  2246. pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4, PATCOPY);
  2247. pDC->SelectObject(pOldBrush);
  2248. }
  2249. pDC->SetTextColor(GetSysColor(
  2250. nCurZoom == 2 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  2251. pDC->SetBkColor(GetSysColor(
  2252. nCurZoom == 2 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));
  2253. c_imageWell.DrawImage(pDC, pt, 1, SRCCOPY);
  2254. pt.y += dy;
  2255. if (nCurZoom == 6)
  2256. {
  2257. CBrush* pOldBrush;
  2258. pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT));
  2259. pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4, PATCOPY);
  2260. pDC->SelectObject(pOldBrush);
  2261. }
  2262. pDC->SetTextColor(GetSysColor(
  2263. nCurZoom == 6 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  2264. pDC->SetBkColor(GetSysColor(
  2265. nCurZoom == 6 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));
  2266. c_imageWell.DrawImage(pDC, pt, 2, SRCCOPY);
  2267. pt.y += dy;
  2268. if (nCurZoom == 8)
  2269. {
  2270. CBrush* pOldBrush;
  2271. pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT));
  2272. pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4, PATCOPY);
  2273. pDC->SelectObject(pOldBrush);
  2274. }
  2275. pDC->SetTextColor(GetSysColor(
  2276. nCurZoom == 8 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT));
  2277. pDC->SetBkColor(GetSysColor(
  2278. nCurZoom == 8 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));;
  2279. c_imageWell.DrawImage(pDC, pt, 3, SRCCOPY);
  2280. c_imageWell.Close();
  2281. }
  2282. /***************************************************************************/
  2283. void CZoomTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect,
  2284. const CPoint& clickPoint)
  2285. {
  2286. int nNewZoom = clickPoint.y / (optionsRect.Height() / 4) + 1;
  2287. if (nNewZoom >= 3)
  2288. nNewZoom *= 2;
  2289. if (nNewZoom != CImgWnd::GetCurrent()->GetZoom())
  2290. {
  2291. CImgWnd::GetCurrent()->SetZoom(nNewZoom);
  2292. CImgWnd::GetCurrent()->CheckScrollBars();
  2293. pWnd->InvalidateOptions();
  2294. }
  2295. SelectPrevious();
  2296. }
  2297. /***************************************************************************/
  2298. void CZoomTool::OnLeave(CImgWnd* pImgWnd, MTI* pmti)
  2299. {
  2300. InvertZoomRect();
  2301. c_zoomRect.SetRect(0, 0, 0, 0);
  2302. }
  2303. /***************************************************************************/
  2304. void CZoomTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShow)
  2305. {
  2306. InvertZoomRect();
  2307. }
  2308. /***************************************************************************/
  2309. void CZoomTool::InvertZoomRect()
  2310. {
  2311. if (c_zoomRect.IsRectEmpty())
  2312. return;
  2313. CClientDC dc(c_pImgWnd);
  2314. CBrush* pOldBrush = (CBrush*)dc.SelectStockObject(NULL_BRUSH);
  2315. dc.SetROP2(R2_NOT);
  2316. CRect invertRect = c_zoomRect;
  2317. c_pImgWnd->ImageToClient(invertRect);
  2318. dc.Rectangle(&invertRect);
  2319. dc.SelectObject(pOldBrush);
  2320. }
  2321. /***************************************************************************/
  2322. void CZoomTool::OnMove(CImgWnd* pImgWnd, MTI* pmti)
  2323. {
  2324. if (pImgWnd->GetZoom() > 1)
  2325. return;
  2326. CRect viewRect;
  2327. pImgWnd->GetClientRect(&viewRect);
  2328. int nPrevZoom = pImgWnd->GetPrevZoom();
  2329. CRect newZoomRect;
  2330. CSize viewSize = viewRect.Size();
  2331. if (viewSize.cx > pImgWnd->m_pImg->cxWidth * nPrevZoom)
  2332. viewSize.cx = pImgWnd->m_pImg->cxWidth * nPrevZoom;
  2333. if (viewSize.cy > pImgWnd->m_pImg->cyHeight * nPrevZoom)
  2334. viewSize.cy = pImgWnd->m_pImg->cyHeight * nPrevZoom;
  2335. newZoomRect.left = pmti->pt.x;
  2336. newZoomRect.top = pmti->pt.y;
  2337. newZoomRect.right = newZoomRect.left + viewSize.cx / nPrevZoom;
  2338. newZoomRect.bottom = newZoomRect.top + viewSize.cy / nPrevZoom;
  2339. newZoomRect.OffsetRect(-newZoomRect.Width() / 2,
  2340. -newZoomRect.Height() / 2);
  2341. int xAdjust = 0;
  2342. int yAdjust = 0;
  2343. if (newZoomRect.left < 0)
  2344. xAdjust = -newZoomRect.left;
  2345. else if ((xAdjust = pImgWnd->m_pImg->cxWidth - newZoomRect.right) > 0)
  2346. xAdjust = 0;
  2347. if (newZoomRect.top < 0)
  2348. yAdjust = -newZoomRect.top;
  2349. else if ((yAdjust = pImgWnd->m_pImg->cyHeight - newZoomRect.bottom) > 0)
  2350. yAdjust = 0;
  2351. newZoomRect.OffsetRect(xAdjust, yAdjust);
  2352. if (newZoomRect != c_zoomRect)
  2353. {
  2354. InvertZoomRect();
  2355. c_pImgWnd = pImgWnd;
  2356. c_zoomRect = newZoomRect;
  2357. InvertZoomRect();
  2358. }
  2359. }
  2360. /***************************************************************************/
  2361. void CZoomTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti)
  2362. {
  2363. CImgTool::OnStartDrag(pImgWnd, pmti);
  2364. c_pImgWnd = pImgWnd;
  2365. InvertZoomRect();
  2366. if (pImgWnd->GetZoom() == 1)
  2367. {
  2368. pImgWnd->SetZoom( pImgWnd->GetPrevZoom() );
  2369. pImgWnd->CheckScrollBars();
  2370. pImgWnd->SetScroll(-c_zoomRect.left - 1, -c_zoomRect.top - 1);
  2371. }
  2372. else
  2373. {
  2374. pImgWnd->SetZoom(1);
  2375. pImgWnd->CheckScrollBars();
  2376. }
  2377. c_zoomRect.SetRect(0, 0, 0, 0);
  2378. }
  2379. /***************************************************************************/
  2380. void CZoomTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti)
  2381. {
  2382. SelectPrevious();
  2383. CImgTool::OnEndDrag(pImgWnd, pmti);
  2384. }
  2385. /***************************************************************************/
  2386. void CZoomTool::OnCancel(CImgWnd* pImgWnd)
  2387. {
  2388. InvertZoomRect();
  2389. c_zoomRect.SetRect(0, 0, 0, 0);
  2390. SelectPrevious();
  2391. CImgTool::OnCancel(pImgWnd);
  2392. }
  2393. /***************************************************************************/