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.

3166 lines
86 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 "imgcolor.h"
  12. #include "imgbrush.h"
  13. #include "imgwell.h"
  14. #include "imgtools.h"
  15. #include "tedit.h"
  16. #include "t_text.h"
  17. #include "t_fhsel.h"
  18. #include "toolbox.h"
  19. #include "undo.h"
  20. #include "props.h"
  21. #include "cmpmsg.h"
  22. #include "imgdlgs.h"
  23. #include "ferr.h"
  24. #include "thumnail.h"
  25. #ifdef _DEBUG
  26. #undef THIS_FILE
  27. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  28. #endif
  29. IMPLEMENT_DYNAMIC(CImgWnd, CWnd)
  30. #include "memtrace.h"
  31. /***************************************************************************/
  32. // helper fns
  33. static CTedit *_GetTextEdit()
  34. {
  35. if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  36. {
  37. CTextTool* pTextTool = (CTextTool*)CImgTool::GetCurrent();
  38. if ((pTextTool != NULL) &&
  39. pTextTool->IsKindOf(RUNTIME_CLASS( CTextTool )))
  40. {
  41. CTedit* pTextEdit = pTextTool->GetTextEditField();
  42. if ((pTextEdit != NULL) &&
  43. pTextEdit->IsKindOf(RUNTIME_CLASS( CTedit )))
  44. {
  45. return pTextEdit;
  46. }
  47. }
  48. }
  49. return NULL;
  50. }
  51. BOOL IsUserEditingText()
  52. {
  53. return (_GetTextEdit() != NULL);
  54. }
  55. BOOL TextToolProcessed( UINT nMessage )
  56. {
  57. CTedit *pTextEdit = _GetTextEdit();
  58. if (pTextEdit)
  59. {
  60. pTextEdit->SendMessage( WM_COMMAND, nMessage );
  61. return TRUE;
  62. }
  63. return FALSE;
  64. }
  65. /***************************************************************************/
  66. BEGIN_MESSAGE_MAP(CImgWnd, CWnd)
  67. ON_WM_CREATE()
  68. #if 0
  69. ON_WM_DESTROY()
  70. #endif
  71. ON_WM_SETFOCUS()
  72. ON_WM_KILLFOCUS()
  73. ON_WM_PAINT()
  74. ON_WM_SIZE()
  75. ON_WM_HSCROLL()
  76. ON_WM_VSCROLL()
  77. ON_WM_LBUTTONDOWN()
  78. ON_WM_LBUTTONDBLCLK()
  79. ON_WM_LBUTTONUP()
  80. ON_WM_RBUTTONDOWN()
  81. ON_WM_RBUTTONDBLCLK()
  82. ON_WM_RBUTTONUP()
  83. ON_WM_MOUSEMOVE()
  84. ON_WM_KEYDOWN()
  85. ON_WM_KEYUP()
  86. ON_WM_TIMER()
  87. ON_WM_CANCELMODE()
  88. ON_WM_WINDOWPOSCHANGING()
  89. ON_WM_DESTROYCLIPBOARD()
  90. ON_WM_PALETTECHANGED()
  91. ON_WM_SETCURSOR()
  92. ON_WM_MOUSEWHEEL ()
  93. END_MESSAGE_MAP()
  94. /***************************************************************************/
  95. CRect rcDragBrush;
  96. CImgBrush theBackupBrush;
  97. CImgWnd* g_pMouseImgWnd = NULL;
  98. CImgWnd* g_pDragBrushWnd = NULL;
  99. // Current Image Viewer
  100. CImgWnd* CImgWnd::c_pImgWndCur = NULL;
  101. CDragger* CImgWnd::c_pResizeDragger = NULL;
  102. CTracker::STATE CImgWnd::c_dragState = CTracker::nil;
  103. // Mouse Tracking Information
  104. MTI mti;
  105. BOOL bIgnoreMouse;
  106. /***************************************************************************/
  107. CImgWnd::CImgWnd(IMG* pImg)
  108. {
  109. m_pNextImgWnd = NULL;
  110. m_nZoom = 1;
  111. m_nZoomPrev = 4;
  112. m_xScroll = 0;
  113. m_yScroll = 0;
  114. m_LineX = 1;
  115. m_LineY = 1;
  116. m_ptDispPos.x = -1;
  117. m_ptDispPos.y = -1;
  118. c_pImgWndCur = this;
  119. m_pwndThumbNailView = NULL;
  120. m_wClipboardFormat = 0;
  121. m_hPoints = NULL;
  122. m_WheelDelta = 0;
  123. ASSERT(pImg != NULL);
  124. m_pImg = pImg;
  125. m_pImg->m_nLastChanged = -1;
  126. }
  127. /***************************************************************************/
  128. CImgWnd::CImgWnd(CImgWnd *pImgWnd)
  129. {
  130. m_pImg = pImgWnd->m_pImg;
  131. m_pNextImgWnd = pImgWnd->m_pNextImgWnd;
  132. m_nZoom = pImgWnd->m_nZoom;
  133. m_nZoomPrev = pImgWnd->m_nZoomPrev;
  134. m_xScroll = pImgWnd->m_xScroll,
  135. m_yScroll = pImgWnd->m_yScroll;
  136. m_ptDispPos = pImgWnd->m_ptDispPos;
  137. m_pwndThumbNailView = NULL;
  138. m_wClipboardFormat = 0;
  139. m_hPoints = NULL;
  140. }
  141. /***************************************************************************/
  142. CImgWnd::~CImgWnd()
  143. {
  144. if (c_pImgWndCur == this)
  145. c_pImgWndCur = NULL;
  146. if (g_pMouseImgWnd == this)
  147. g_pMouseImgWnd = NULL;
  148. HideBrush();
  149. fDraggingBrush = FALSE;
  150. g_bBrushVisible = FALSE;
  151. if (g_pDragBrushWnd == this)
  152. {
  153. g_pDragBrushWnd = NULL;
  154. }
  155. if (m_hPoints)
  156. {
  157. ::GlobalFree( m_hPoints );
  158. m_hPoints = NULL;
  159. }
  160. }
  161. /***************************************************************************/
  162. BOOL CImgWnd::Create( DWORD dwStyle, const RECT& rect,
  163. CWnd* pParentWnd, UINT nID)
  164. {
  165. static CString sImgWndClass;
  166. if (sImgWndClass.IsEmpty())
  167. sImgWndClass = AfxRegisterWndClass( CS_DBLCLKS );
  168. ASSERT( ! sImgWndClass.IsEmpty() );
  169. dwStyle |= WS_CLIPSIBLINGS;
  170. return CWnd::Create( sImgWndClass, NULL, dwStyle, rect, pParentWnd, nID );
  171. }
  172. /***************************************************************************/
  173. int CImgWnd::OnCreate( LPCREATESTRUCT lpCreateStruct )
  174. {
  175. if (m_pImg)
  176. AddImgWnd( m_pImg, this );
  177. return CWnd::OnCreate(lpCreateStruct);
  178. }
  179. /***************************************************************************/
  180. #if 0
  181. void CImgWnd::OnDestroy()
  182. {
  183. if (c_pImgWndCur == this)
  184. c_pImgWndCur = NULL;
  185. HideBrush();
  186. fDraggingBrush = FALSE;
  187. CWnd::OnDestroy();
  188. }
  189. #endif
  190. /***************************************************************************/
  191. void CImgWnd::OnPaletteChanged(CWnd *pPaletteWnd)
  192. {
  193. #if 0
  194. // obviously this never gets hit or somebody would have realized by now...
  195. CImgWnd::OnPaletteChanged(pPaletteWnd);
  196. #endif
  197. Invalidate();
  198. }
  199. /***************************************************************************/
  200. BOOL CImgWnd::OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message)
  201. {
  202. if (nHitTest==HTCLIENT && pWnd->m_hWnd==m_hWnd)
  203. {
  204. // We do our own cursor stuff in our own client area, but not in the
  205. // text box
  206. return(TRUE);
  207. }
  208. return((BOOL)Default());
  209. }
  210. /***************************************************************************/
  211. void CImgWnd::OnWindowPosChanging( WINDOWPOS FAR* lpwndpos )
  212. {
  213. CWnd::OnWindowPosChanging( lpwndpos );
  214. }
  215. /***************************************************************************/
  216. // Image View Painting Functions
  217. //
  218. void CImgWnd::OnPaint()
  219. {
  220. CPaintDC dc(this);
  221. if (dc.m_hDC == NULL)
  222. {
  223. theApp.SetGdiEmergency();
  224. return;
  225. }
  226. if (m_pImg == NULL)
  227. return;
  228. if (g_pMouseImgWnd == this)
  229. CImgTool::HideDragger( this );
  230. CPalette* ppalOld = SetImgPalette( &dc, FALSE );
  231. DrawBackground( &dc, (CRect*)&dc.m_ps.rcPaint );
  232. DrawImage ( &dc, (CRect*)&dc.m_ps.rcPaint );
  233. DrawTracker ( &dc, (CRect*)&dc.m_ps.rcPaint );
  234. if (g_pMouseImgWnd == this)
  235. CImgTool::ShowDragger( this );
  236. if (m_pwndThumbNailView != NULL)
  237. m_pwndThumbNailView->RefreshImage();
  238. if (ppalOld)
  239. dc.SelectPalette( ppalOld, FALSE );
  240. }
  241. /***************************************************************************/
  242. BOOL CImgWnd::OnCmdMsg( UINT nID, int nCode, void* pExtra,
  243. AFX_CMDHANDLERINFO* pHandlerInfo )
  244. {
  245. if (nCode == CN_COMMAND)
  246. {
  247. switch (nID)
  248. {
  249. case IDMX_VS_PAGEUP:
  250. SendMessage( WM_VSCROLL, SB_PAGEUP, 0L );
  251. return TRUE;
  252. case IDMX_VS_PAGEDOWN:
  253. SendMessage( WM_VSCROLL, SB_PAGEDOWN, 0L );
  254. return TRUE;
  255. case IDMX_HS_PAGEUP:
  256. SendMessage( WM_HSCROLL, SB_PAGEUP, 0L );
  257. return TRUE;
  258. case IDMX_HS_PAGEDOWN:
  259. SendMessage( WM_HSCROLL, SB_PAGEDOWN, 0L );
  260. return TRUE;
  261. }
  262. CImgTool* pImgTool = CImgTool::FromID( nID );
  263. if (pImgTool != NULL)
  264. {
  265. pImgTool->Select();
  266. return TRUE;
  267. }
  268. }
  269. return CWnd::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
  270. }
  271. void CImgWnd::GetDrawRects(const CRect* pPaintRect, const CRect* pReqDestRect,
  272. CRect& srcRect, CRect& destRect)
  273. {
  274. // Find the sub-rectangle of srcRect that corresponds to
  275. // the pPaintRect sub-rectangle of destRect.
  276. srcRect = *pPaintRect;
  277. srcRect.right += m_nZoom - 1;
  278. srcRect.bottom += m_nZoom - 1;
  279. ClientToImage( srcRect );
  280. srcRect.left = max(0, srcRect.left);
  281. srcRect.top = max(0, srcRect.top );
  282. srcRect.right = min(m_pImg->cxWidth , srcRect.right );
  283. srcRect.bottom = min(m_pImg->cyHeight, srcRect.bottom);
  284. if (pReqDestRect == NULL)
  285. {
  286. destRect = srcRect;
  287. ImageToClient( destRect );
  288. }
  289. else
  290. {
  291. destRect = *pReqDestRect;
  292. }
  293. }
  294. /***************************************************************************/
  295. // Draw the actual image 'a bitmap'. Drawing is
  296. // optimized to only deal with the pixels inside paintRect. This function
  297. // reduces flashing by drawing the image and optional grid in an off-screen
  298. // bitmap and then transfering that bitmap to the screen.
  299. //
  300. void CImgWnd::DrawImage( CDC* pDC, const CRect* pPaintRect,
  301. CRect* pDestRect, BOOL bDoGrid )
  302. {
  303. ASSERT( pDC != NULL );
  304. ASSERT( m_pImg != NULL );
  305. CRect destRect;
  306. CRect srcRect;
  307. GetDrawRects(pPaintRect, pDestRect, srcRect, destRect);
  308. if (srcRect.Width() <= 0 || srcRect.Height() <= 0)
  309. {
  310. // Nothing to paint...
  311. return;
  312. }
  313. if (! IsGridVisible() && m_nZoom == 1)
  314. {
  315. // Optimize the easy case... (Can't speed up magnified views
  316. // because of the bogus hack we have to do in StretchCopy.)
  317. if (theApp.m_pPalette
  318. && ((m_pImg->cPlanes * m_pImg->cBitCount) == 1))
  319. {
  320. pDC->SetTextColor( PALETTEINDEX( 0 ) );
  321. pDC->SetBkColor ( PALETTEINDEX( 1 ) );
  322. }
  323. BitBlt(pDC->m_hDC, destRect.left , destRect.top,
  324. destRect.Width(), destRect.Height(),
  325. m_pImg->hDC, srcRect.left , srcRect.top, SRCCOPY);
  326. return;
  327. }
  328. CDC tempDC;
  329. CBitmap tempBitmap;
  330. CBitmap* pOldTempBitmap;
  331. if (! tempDC.CreateCompatibleDC(pDC)
  332. || ! tempBitmap.CreateCompatibleBitmap(pDC, destRect.Width() + 1,
  333. destRect.Height() + 1))
  334. {
  335. theApp.SetGdiEmergency(FALSE);
  336. return;
  337. }
  338. pOldTempBitmap = tempDC.SelectObject(&tempBitmap);
  339. ASSERT(pOldTempBitmap != NULL);
  340. CPalette* pOldPalette = SetImgPalette( &tempDC, FALSE ); // Background ??
  341. // If we're zoomed in, use COLORONCOLOR for easy pixel-by-pixel editing
  342. // Otherwise use HALFTONE for nice appearance
  343. if (m_nZoom < 2)
  344. {
  345. tempDC.SetStretchBltMode(HALFTONE);
  346. }
  347. else
  348. {
  349. tempDC.SetStretchBltMode(COLORONCOLOR);
  350. }
  351. if (m_pImg->cPlanes * m_pImg->cBitCount == 1)
  352. {
  353. tempDC.SetTextColor( RGB( 0x00, 0x00, 0x00 ));
  354. tempDC.SetBkColor ( RGB( 0xFF, 0xFF, 0xFF ));
  355. }
  356. // Bitmaps...
  357. StretchCopy(tempDC.m_hDC, 0, 0, destRect.Width(), destRect.Height(),
  358. m_pImg->hDC, srcRect.left, srcRect.top,
  359. srcRect.Width(), srcRect.Height());
  360. // Draw the grid...
  361. if (IsGridVisible() && bDoGrid)
  362. DrawGrid( &tempDC, srcRect, destRect );
  363. // Transfer to the screen...
  364. pDC->BitBlt(destRect.left, destRect.top, destRect.Width(),
  365. destRect.Height(), &tempDC, 0, 0, SRCCOPY);
  366. // Cleanup...
  367. if (pOldPalette)
  368. tempDC.SelectPalette( pOldPalette, FALSE ); // Background ??
  369. tempDC.SelectObject(pOldTempBitmap);
  370. }
  371. /***************************************************************************/
  372. // Draw a border and bevel around the image and fill the rest of
  373. // the window with gray. If pPaintRect is not NULL, painting is
  374. // optimized to only draw with the rectangle.
  375. //
  376. void CImgWnd::DrawBackground(CDC* pDC, const CRect* pPaintRect)
  377. {
  378. ASSERT( pDC != NULL );
  379. CRect clientRect;
  380. if (pPaintRect == NULL)
  381. {
  382. // Draw everything...
  383. GetClientRect( &clientRect );
  384. pPaintRect = &clientRect;
  385. }
  386. CRect srcRect;
  387. CRect imageRect;
  388. GetDrawRects(pPaintRect, NULL, srcRect, imageRect);
  389. // Erase area around image, border, and bevel...
  390. CBrush* pOldBrush = pDC->SelectObject( GetSysBrush( COLOR_APPWORKSPACE ) );
  391. if (imageRect.top > pPaintRect->top)
  392. {
  393. // Top...
  394. pDC->PatBlt(pPaintRect->left, pPaintRect->top, pPaintRect->Width(),
  395. imageRect.top - pPaintRect->top, PATCOPY);
  396. }
  397. if (imageRect.left > pPaintRect->left)
  398. {
  399. // Left...
  400. pDC->PatBlt(pPaintRect->left, imageRect.top,
  401. imageRect.left - pPaintRect->left, imageRect.Height(), PATCOPY);
  402. }
  403. if (imageRect.right < pPaintRect->right)
  404. {
  405. // Right...
  406. pDC->PatBlt(imageRect.right, imageRect.top,
  407. pPaintRect->right - imageRect.right, imageRect.Height(), PATCOPY);
  408. }
  409. if (imageRect.bottom < pPaintRect->bottom)
  410. {
  411. // Bottom...
  412. pDC->PatBlt(pPaintRect->left, imageRect.bottom, pPaintRect->Width(),
  413. pPaintRect->bottom - imageRect.bottom, PATCOPY);
  414. }
  415. pDC->SelectObject(pOldBrush);
  416. }
  417. /***************************************************************************/
  418. void CImgWnd::SetImg(IMG* pImg)
  419. {
  420. m_pNextImgWnd = pImg->m_pFirstImgWnd;
  421. pImg->m_pFirstImgWnd = this;
  422. m_pImg = pImg;
  423. }
  424. /***************************************************************************/
  425. CPalette* CImgWnd::SetImgPalette( CDC* pdc, BOOL bForce )
  426. {
  427. CPalette* ppal = NULL;
  428. // If we do not realize as a background brush when in-place, we can get
  429. // an infinite recursion of the container and us trying to realize the
  430. // palette
  431. if (theApp.m_pwndInPlaceFrame)
  432. {
  433. bForce = TRUE;
  434. }
  435. if (theApp.m_pPalette
  436. && theApp.m_pPalette->m_hObject)
  437. {
  438. ppal = pdc->SelectPalette( theApp.m_pPalette, bForce );
  439. pdc->RealizePalette();
  440. }
  441. return ppal;
  442. }
  443. /***************************************************************************/
  444. HPALETTE CImgWnd::SetImgPalette( HDC hdc, BOOL bForce )
  445. {
  446. HPALETTE hpal = NULL;
  447. // If we do not realize as a background brush when in-place, we can get
  448. // an infinite recursion of the container and us trying to realize the
  449. // palette
  450. if (theApp.m_pwndInPlaceFrame)
  451. {
  452. bForce = TRUE;
  453. }
  454. if (theApp.m_pPalette
  455. && theApp.m_pPalette->m_hObject)
  456. {
  457. hpal = ::SelectPalette( hdc, (HPALETTE)theApp.m_pPalette->m_hObject, bForce );
  458. ::RealizePalette( hdc );
  459. }
  460. return hpal;
  461. }
  462. /***************************************************************************/
  463. void CImgWnd::SetZoom(int nZoom)
  464. {
  465. if (m_nZoom > 1)
  466. m_nZoomPrev = m_nZoom;
  467. CommitSelection(TRUE);
  468. if (nZoom > 1)
  469. {
  470. // deselect the text tool if it's around
  471. CImgTool* pImgTool = CImgTool::GetCurrent();
  472. if (pImgTool != NULL && CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  473. {
  474. CImgTool::Select(IDMB_PENCILTOOL);
  475. }
  476. }
  477. HideBrush();
  478. SetupRubber( m_pImg );
  479. EraseTracker();
  480. theImgBrush.m_pImg = NULL;
  481. DrawTracker();
  482. CPBView* pView = (CPBView*)GetParent();
  483. if (pView != NULL && pView->IsKindOf( RUNTIME_CLASS( CPBView ) ))
  484. if (nZoom == 1)
  485. pView->HideThumbNailView();
  486. else
  487. pView->ShowThumbNailView();
  488. Invalidate(FALSE);
  489. m_nZoom = nZoom;
  490. }
  491. /***************************************************************************/
  492. void CImgWnd::SetScroll(int xPos, int yPos)
  493. {
  494. if (xPos > 0)
  495. xPos = 0;
  496. else
  497. if (xPos < -m_pImg->cxWidth)
  498. xPos = -m_pImg->cxWidth;
  499. if (yPos > 0)
  500. yPos = 0;
  501. else
  502. if (yPos < -m_pImg->cyHeight)
  503. yPos = -m_pImg->cyHeight;
  504. m_xScroll = xPos;
  505. m_yScroll = yPos;
  506. Invalidate( FALSE );
  507. CheckScrollBars();
  508. }
  509. /***************************************************************************/
  510. void CImgWnd::CheckScrollBars()
  511. {
  512. // Tacky recursion blocker is required because this is called from
  513. // the OnSize handler and turning scroll bars on or off changes
  514. // the size of our window...
  515. static BOOL bInHere = FALSE;
  516. if (bInHere)
  517. return;
  518. bInHere = TRUE;
  519. int cxVScrollBar = GetSystemMetrics( SM_CXVSCROLL );
  520. int cyHScrollBar = GetSystemMetrics( SM_CYHSCROLL );
  521. // Figure the client area size if there were no scroll bars...
  522. CRect clientRect;
  523. GetClientRect( &clientRect );
  524. int cxWidth = clientRect.Width();
  525. int cyHeight = clientRect.Height();
  526. BOOL hHasHBar = ((GetStyle() & WS_HSCROLL) != 0);
  527. BOOL bHasVBar = ((GetStyle() & WS_VSCROLL) != 0);
  528. if (hHasHBar)
  529. cyHeight += cyHScrollBar;
  530. if (bHasVBar)
  531. cxWidth += cxVScrollBar;
  532. // Figure the size of the thing we are scrolling (the subject)...
  533. CSize subjectSize;
  534. GetImgSize( m_pImg, subjectSize );
  535. int iTrackerSize = 2 * CTracker::HANDLE_SIZE;
  536. subjectSize.cx = (subjectSize.cx * m_nZoom ) + iTrackerSize;
  537. subjectSize.cy = (subjectSize.cy * m_nZoom ) + iTrackerSize;
  538. m_LineX = (subjectSize.cx + 31) / 32;
  539. m_LineY = (subjectSize.cy + 31) / 32;
  540. // Nasty loop takes care of case where we only need a vertical
  541. // scroll bar because we added a horizontal scroll bar and
  542. // vice versa... (Will only ever loop twice.)
  543. BOOL bNeedHBar = FALSE;
  544. BOOL bNeedVBar = FALSE;
  545. BOOL bChange;
  546. do {
  547. bChange = FALSE;
  548. if (! bNeedVBar && subjectSize.cy > cyHeight)
  549. {
  550. bChange = TRUE;
  551. bNeedVBar = TRUE;
  552. cxWidth -= cxVScrollBar;
  553. }
  554. if (! bNeedHBar && subjectSize.cx > cxWidth)
  555. {
  556. bChange = TRUE;
  557. bNeedHBar = TRUE;
  558. cyHeight -= cyHScrollBar;
  559. }
  560. } while (bChange);
  561. SetRedraw( FALSE );
  562. SCROLLINFO si;
  563. si.cbSize = sizeof( si );
  564. si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
  565. si.nMin = 0;
  566. // We subtract 1 because subjectSize is the size we want, so the range
  567. // should be 0 to subjectSize-1
  568. si.nMax = (subjectSize.cx - 1) / m_nZoom;
  569. si.nPage = cxWidth / m_nZoom;
  570. si.nPos = -m_xScroll;
  571. SetScrollInfo( SB_HORZ, &si, FALSE );
  572. si.nMax = (subjectSize.cy - 1) / m_nZoom;
  573. si.nPage = cyHeight / m_nZoom;
  574. si.nPos = -m_yScroll;
  575. SetScrollInfo( SB_VERT, &si, FALSE );
  576. si.fMask = SIF_POS;
  577. GetScrollInfo( SB_HORZ, &si );
  578. if ( -m_xScroll != si.nPos )
  579. m_xScroll = -si.nPos ;
  580. GetScrollInfo( SB_VERT, &si );
  581. if ( -m_yScroll != si.nPos )
  582. m_yScroll = -si.nPos;
  583. SetRedraw ( TRUE );
  584. Invalidate( FALSE );
  585. bInHere = FALSE;
  586. }
  587. /***************************************************************************/
  588. void CImgWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*)
  589. {
  590. OnScroll(FALSE, nSBCode, nPos);
  591. }
  592. /***************************************************************************/
  593. void CImgWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*)
  594. {
  595. OnScroll(TRUE, nSBCode, nPos);
  596. }
  597. /***************************************************************************/
  598. void CImgWnd::OnScroll(BOOL bVert, UINT nSBCode, UINT nPos)
  599. {
  600. SCROLLINFO ScrollInfo;
  601. ScrollInfo.cbSize = sizeof( ScrollInfo );
  602. ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
  603. GetScrollInfo( (bVert? SB_VERT: SB_HORZ), &ScrollInfo );
  604. int iScroll = ScrollInfo.nPage/4;
  605. int iNewPos = ScrollInfo.nPos;
  606. switch (nSBCode)
  607. {
  608. case SB_TOP:
  609. iNewPos = 0;
  610. break;
  611. case SB_BOTTOM:
  612. iNewPos = ScrollInfo.nMax;
  613. break;
  614. case SB_LINEDOWN:
  615. iNewPos += iScroll;
  616. break;
  617. case SB_LINEUP:
  618. iNewPos -= iScroll;
  619. break;
  620. case SB_PAGEDOWN:
  621. iNewPos += iScroll * 4;
  622. break;
  623. case SB_PAGEUP:
  624. iNewPos -= iScroll * 4;
  625. break;
  626. case SB_THUMBPOSITION:
  627. case SB_THUMBTRACK:
  628. iNewPos = nPos;
  629. break;
  630. }
  631. if (iNewPos < ScrollInfo.nMin)
  632. iNewPos = 0;
  633. else
  634. if (iNewPos > ScrollInfo.nMax-(int)ScrollInfo.nPage+1)
  635. iNewPos = ScrollInfo.nMax-(int)ScrollInfo.nPage+1;
  636. iScroll = -(iNewPos - ScrollInfo.nPos);
  637. Invalidate(FALSE);
  638. if (bVert)
  639. m_yScroll = -iNewPos;
  640. else
  641. m_xScroll = -iNewPos;
  642. ScrollInfo.fMask = SIF_POS;
  643. ScrollInfo.nPos = iNewPos;
  644. SetScrollInfo( (bVert? SB_VERT: SB_HORZ), &ScrollInfo, TRUE );
  645. }
  646. /***************************************************************************/
  647. BOOL CImgWnd::OnMouseWheel (UINT nFlags, short zDelta, CPoint pt)
  648. {
  649. //
  650. // Don't handle zoom and datazoom.
  651. //
  652. if (nFlags & (MK_SHIFT | MK_CONTROL))
  653. {
  654. return FALSE;
  655. }
  656. int nBar;
  657. int *pScroll;
  658. if (GetWindowLong(GetSafeHwnd(), GWL_STYLE) & WS_VSCROLL)
  659. {
  660. nBar = SB_VERT;
  661. pScroll = &m_yScroll;
  662. }
  663. else
  664. {
  665. nBar = SB_HORZ;
  666. pScroll = &m_xScroll;
  667. }
  668. SCROLLINFO ScrollInfo;
  669. ScrollInfo.cbSize = sizeof( ScrollInfo );
  670. ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
  671. GetScrollInfo( nBar, &ScrollInfo );
  672. m_WheelDelta -= zDelta;
  673. if (abs(m_WheelDelta) >= WHEEL_DELTA)
  674. {
  675. int iScroll = ScrollInfo.nPage/4 * (m_WheelDelta/WHEEL_DELTA);
  676. int iNewPos = ScrollInfo.nPos + iScroll;
  677. if (iNewPos < ScrollInfo.nMin)
  678. iNewPos = 0;
  679. else if (iNewPos > ScrollInfo.nMax-(int)ScrollInfo.nPage+1)
  680. iNewPos = ScrollInfo.nMax-(int)ScrollInfo.nPage+1;
  681. Invalidate(FALSE);
  682. *pScroll = -iNewPos;
  683. ScrollInfo.fMask = SIF_POS;
  684. ScrollInfo.nPos = iNewPos;
  685. SetScrollInfo( nBar, &ScrollInfo, TRUE );
  686. m_WheelDelta= m_WheelDelta % WHEEL_DELTA;
  687. CImgTool* pImgTool = CImgTool::GetCurrent();
  688. mti.ptPrev = mti.pt;
  689. mti.pt = pt;
  690. pImgTool->OnMove (this, &mti);
  691. }
  692. return TRUE;
  693. }
  694. /***************************************************************************/
  695. void CImgWnd::PrepareForBrushChange(BOOL bPickup, BOOL bErase)
  696. {
  697. if (theImgBrush.m_pImg != NULL
  698. && theImgBrush.m_bFirstDrag)
  699. {
  700. if (bPickup)
  701. PickupSelection();
  702. SetUndo(m_pImg);
  703. theImgBrush.m_bLastDragWasFirst = TRUE;
  704. theImgBrush.m_bFirstDrag = FALSE;
  705. theImgBrush.m_rcDraggedFrom = rcDragBrush;
  706. if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  707. {
  708. HideBrush();
  709. bErase = FALSE;
  710. }
  711. if (bErase)
  712. {
  713. // Clear the background...
  714. HideBrush();
  715. FillImgRect( m_pImg->hDC, &theImgBrush.m_rcDraggedFrom, crRight );
  716. CommitImgRect(m_pImg, &theImgBrush.m_rcDraggedFrom);
  717. InvalImgRect (m_pImg, &theImgBrush.m_rcDraggedFrom);
  718. FinishUndo(theImgBrush.m_rcDraggedFrom);
  719. MoveBrush(theImgBrush.m_rcSelection);
  720. }
  721. }
  722. }
  723. /***************************************************************************/
  724. void CImgWnd::OnCancelMode()
  725. {
  726. CmdCancel();
  727. }
  728. /***************************************************************************/
  729. void CImgWnd::CmdCancel()
  730. {
  731. // This will:
  732. // Erase the size indicator on the status bar.
  733. // Reset the mouse cursor to an arrow.
  734. // Release the capture.
  735. // Cancel (and undo) any drawing operation in progress.
  736. // Cancel the Pick Color command if it's active.
  737. // If there's a selection, will set to whole image and select prev tool
  738. ClearStatusBarSize();
  739. mti.fLeft = mti.fRight = FALSE;
  740. if (c_pResizeDragger != NULL)
  741. {
  742. EndResizeOperation();
  743. bIgnoreMouse = TRUE;
  744. return;
  745. }
  746. CImgTool* pImgTool = CImgTool::GetCurrent();
  747. if (GetCapture() == this || pImgTool->IsMultPtOpInProgress())
  748. {
  749. // Cancel dragging or multi-point operation in progress
  750. BOOL bWasMakingSelection = theImgBrush.m_bMakingSelection;
  751. ZoomedInDP(WM_CANCEL, 0, CPoint(0, 0));
  752. SetCursor(LoadCursor(NULL, IDC_ARROW + 11));
  753. if (! bWasMakingSelection)
  754. CancelPainting();
  755. bIgnoreMouse = TRUE;
  756. }
  757. else
  758. if (pImgTool->IsToggle()
  759. || CImgTool::GetCurrentID() == IDMB_PICKTOOL
  760. || CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL
  761. || CImgTool::GetCurrentID() == IDMZ_BRUSHTOOL
  762. || CImgTool::GetCurrentID() == IDMB_POLYGONTOOL
  763. || CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  764. {
  765. pImgTool->OnCancel( this );
  766. }
  767. if (GetKeyState( VK_LBUTTON ) < 0 || GetKeyState( VK_RBUTTON) < 0 )
  768. bIgnoreMouse = TRUE;
  769. SetToolCursor();
  770. }
  771. /***************************************************************************/
  772. void CImgWnd::CmdSel2Bsh()
  773. {
  774. if (! g_bCustomBrush)
  775. {
  776. if (theImgBrush.m_pImg == NULL)
  777. {
  778. // No selection, turn the whole image into a brush!
  779. MakeBrush( m_pImg->hDC, CRect( 0, 0, m_pImg->cxWidth,
  780. m_pImg->cyHeight ) );
  781. }
  782. if (theImgBrush.m_bFirstDrag)
  783. {
  784. // Time to pick up the bits!
  785. ASSERT(theImgBrush.m_pImg == m_pImg);
  786. PickupSelection();
  787. }
  788. InvalImgRect(theImgBrush.m_pImg, NULL); // erase the selection tracker
  789. CImgTool::Select(IDMZ_BRUSHTOOL);
  790. SetCombineMode(combineMatte);
  791. g_bCustomBrush = TRUE;
  792. theImgBrush.m_pImg = NULL;
  793. theImgBrush.CenterHandle();
  794. }
  795. else
  796. if (CImgTool::GetCurrentID() == IDMZ_BRUSHTOOL)
  797. {
  798. CImgTool::GetCurrent()->OnCancel(this);
  799. }
  800. }
  801. /***************************************************************************/
  802. // Coordinate Translation and Calculation Functions
  803. //
  804. //
  805. // Convert a point or rect in image view client coordinates to image
  806. // coordinates taking magnification and scrolling into account.
  807. //
  808. void CImgWnd::ClientToImage(CPoint& point)
  809. {
  810. int iHandleSize = CTracker::HANDLE_SIZE;
  811. point.x = (point.x - iHandleSize) / m_nZoom - m_xScroll;
  812. point.y = (point.y - iHandleSize) / m_nZoom - m_yScroll;
  813. }
  814. /***************************************************************************/
  815. void CImgWnd::ClientToImage(CRect& rect)
  816. {
  817. ClientToImage(rect.TopLeft());
  818. ClientToImage(rect.BottomRight());
  819. }
  820. /***************************************************************************/
  821. // Convert a point or rect in image coordinates to image view client
  822. // coordinates taking magnification and scrolling into account.
  823. //
  824. void CImgWnd::ImageToClient(CPoint& point)
  825. {
  826. int iHandleSize = CTracker::HANDLE_SIZE;
  827. point.x = (point.x + m_xScroll) * m_nZoom + iHandleSize;
  828. point.y = (point.y + m_yScroll) * m_nZoom + iHandleSize;
  829. }
  830. /***************************************************************************/
  831. void CImgWnd::ImageToClient(CRect& rect)
  832. {
  833. ImageToClient(rect.TopLeft());
  834. ImageToClient(rect.BottomRight());
  835. }
  836. /***************************************************************************/
  837. // Return a rectangle in image view coordinates surrounding the image
  838. // taking magnification, scrolling, and the grid into account.
  839. void CImgWnd::GetImageRect( CRect& imageRect )
  840. {
  841. imageRect.SetRect( 0, 0, m_pImg->cxWidth, m_pImg->cyHeight );
  842. ImageToClient( imageRect );
  843. if (IsGridVisible())
  844. {
  845. imageRect.right += 1;
  846. imageRect.bottom += 1;
  847. }
  848. }
  849. /***************************************************************************/
  850. CRect CImgWnd::GetDrawingRect( void )
  851. {
  852. CRect rectImage;
  853. CRect rectClient;
  854. GetImageRect ( rectImage );
  855. GetClientRect( &rectClient );
  856. rectImage &= rectClient;
  857. rectImage.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
  858. return ( rectImage );
  859. }
  860. /***************************************************************************/
  861. void CImgWnd::OnSetFocus(CWnd* pOldWnd)
  862. {
  863. if (m_pImg == NULL)
  864. {
  865. // Time to die... (Our img was deleted, so we'll be disappearing
  866. // soon. Don't bother to do any of the rest of this function...
  867. return;
  868. }
  869. Invalidate();
  870. BringWindowToTop(); // so updates happen here first
  871. if (c_pImgWndCur != this
  872. && c_pImgWndCur != NULL)
  873. c_pImgWndCur->EraseTracker();
  874. c_pImgWndCur = this;
  875. SelectImg( m_pImg );
  876. UpdateWindow();
  877. CWnd::OnSetFocus( pOldWnd );
  878. DrawTracker();
  879. }
  880. /***************************************************************************/
  881. void CImgWnd::OnKillFocus(CWnd* pNewWnd)
  882. {
  883. Invalidate();
  884. if (theImgBrush.m_pImg == NULL)
  885. HideBrush();
  886. if (GetCapture() == this)
  887. CmdCancel();
  888. CWnd::OnKillFocus(pNewWnd);
  889. }
  890. /***************************************************************************/
  891. void CImgWnd::OnSize(UINT nType, int cx, int cy)
  892. {
  893. CheckScrollBars();
  894. CWnd::OnSize(nType, cx, cy);
  895. }
  896. /***************************************************************************/
  897. BOOL CImgWnd::OnMouseDown(UINT nFlags)
  898. {
  899. if (GetFocus() != this)
  900. {
  901. SetFocus();
  902. SetActiveWindow();
  903. }
  904. if ((nFlags & (MK_LBUTTON | MK_RBUTTON)) == (MK_LBUTTON | MK_RBUTTON))
  905. {
  906. ClearStatusBarSize();
  907. BOOL bWasMakingSelection = theImgBrush.m_bMakingSelection;
  908. ZoomedInDP(WM_CANCEL, 0, CPoint(0, 0));
  909. SetCursor(LoadCursor(NULL, IDC_ARROW + 11));
  910. if (! bWasMakingSelection)
  911. CancelPainting();
  912. bIgnoreMouse = TRUE;
  913. return FALSE;
  914. }
  915. return TRUE;
  916. }
  917. /***************************************************************************/
  918. BOOL CImgWnd::OnMouseMessage( UINT nFlags )
  919. {
  920. if (bIgnoreMouse /*|| GetFocus() != this*/)
  921. {
  922. if ((nFlags & (MK_LBUTTON | MK_RBUTTON)) == 0)
  923. {
  924. bIgnoreMouse = FALSE;
  925. SetToolCursor();
  926. }
  927. else
  928. {
  929. SetCursor( LoadCursor( NULL, IDC_ARROW ) );
  930. }
  931. return FALSE;
  932. }
  933. if ((CImgTool::GetCurrentID() != IDMB_PICKTOOL)
  934. && (CImgTool::GetCurrentID() != IDMB_PICKRGNTOOL))
  935. SetupRubber(m_pImg);
  936. const MSG* pMsg = GetCurrentMessage();
  937. mti.fCtrlDown = (nFlags & MK_CONTROL);
  938. ZoomedInDP( pMsg->message, (DWORD)pMsg->wParam, CPoint( (DWORD)pMsg->lParam ) );
  939. return TRUE;
  940. }
  941. /***************************************************************************/
  942. void CImgWnd::OnLButtonDown( UINT nFlags, CPoint point )
  943. {
  944. CWnd::OnLButtonDown( nFlags, point );
  945. if (OnMouseDown( nFlags ))
  946. {
  947. OnMouseMessage( nFlags );
  948. }
  949. }
  950. /***************************************************************************/
  951. void CImgWnd::OnLButtonDblClk(UINT nFlags, CPoint point)
  952. {
  953. CRect rect;
  954. GetImageRect(rect);
  955. // When inside the image, a double click is the same as a single click
  956. OnLButtonDown(nFlags, point);
  957. }
  958. /***************************************************************************/
  959. void CImgWnd::OnLButtonUp(UINT nFlags, CPoint point)
  960. {
  961. CWnd::OnLButtonUp(nFlags, point);
  962. OnMouseMessage(nFlags);
  963. }
  964. /***************************************************************************/
  965. void CImgWnd::OnRButtonDown(UINT nFlags, CPoint point)
  966. {
  967. CWnd::OnRButtonDown(nFlags, point);
  968. if (OnMouseDown(nFlags))
  969. {
  970. OnMouseMessage(nFlags);
  971. }
  972. }
  973. /***************************************************************************/
  974. void CImgWnd::OnRButtonDblClk(UINT nFlags, CPoint point)
  975. {
  976. // A right button double click is the same as a right button single click
  977. OnRButtonDown(nFlags, point);
  978. }
  979. /***************************************************************************/
  980. void CImgWnd::OnRButtonUp(UINT nFlags, CPoint point)
  981. {
  982. CWnd::OnRButtonUp(nFlags, point);
  983. OnMouseMessage(nFlags);
  984. }
  985. /***************************************************************************/
  986. void CImgWnd::OnMouseMove(UINT nFlags, CPoint point)
  987. {
  988. CWnd::OnMouseMove(nFlags, point);
  989. if (g_pMouseImgWnd != this
  990. && g_pMouseImgWnd != NULL)
  991. {
  992. CImgTool::GetCurrent()->OnLeave( g_pMouseImgWnd, &mti );
  993. g_pMouseImgWnd = NULL;
  994. }
  995. ClientToImage( point );
  996. m_ptDispPos = point;
  997. if (g_pMouseImgWnd == NULL)
  998. {
  999. MTI mtiEnter;
  1000. mtiEnter.pt = point;
  1001. mtiEnter.ptDown = point;
  1002. mtiEnter.ptPrev = point;
  1003. mtiEnter.fLeft = FALSE;
  1004. mtiEnter.fRight = FALSE;
  1005. mtiEnter.fCtrlDown = FALSE;
  1006. CImgTool::GetCurrent()->OnEnter( g_pMouseImgWnd, &mtiEnter );
  1007. g_pMouseImgWnd = this;
  1008. }
  1009. OnMouseMessage( nFlags );
  1010. }
  1011. /***************************************************************************/
  1012. void CImgWnd::OnTimer(UINT nIDEvent)
  1013. {
  1014. OnMouseMessage( 0 );
  1015. }
  1016. /***************************************************************************/
  1017. void CImgWnd::SetToolCursor()
  1018. {
  1019. UINT nCursorID = CImgTool::GetCurrent()->GetCursorID();
  1020. HCURSOR hCursor = NULL;
  1021. if (nCursorID != 0)
  1022. {
  1023. hCursor = LoadCursor(nCursorID < 32512 ?
  1024. AfxGetResourceHandle() : NULL, MAKEINTRESOURCE( nCursorID ));
  1025. }
  1026. SetCursor(hCursor);
  1027. }
  1028. /***************************************************************************/
  1029. void CImgWnd::EndResizeOperation()
  1030. {
  1031. ReleaseCapture();
  1032. delete c_pResizeDragger;
  1033. c_pResizeDragger = NULL;
  1034. c_dragState = CTracker::nil;
  1035. ClearStatusBarSize();
  1036. }
  1037. /***************************************************************************/
  1038. void CImgWnd::ResizeMouseHandler(unsigned code, CPoint imagePt)
  1039. {
  1040. CRect imageRect = c_pResizeDragger->m_rect;
  1041. ClientToImage(imageRect);
  1042. switch (code)
  1043. {
  1044. case WM_CANCEL:
  1045. EndResizeOperation();
  1046. return;
  1047. case WM_LBUTTONUP:
  1048. // resizing whole bitmap
  1049. if (m_pImg != theImgBrush.m_pImg
  1050. && m_pwndThumbNailView)
  1051. {
  1052. m_pwndThumbNailView->Invalidate();
  1053. }
  1054. EndResizeOperation();
  1055. if (theImgBrush.m_pImg == NULL)
  1056. {
  1057. // User was resizing the whole image...
  1058. CPBView* pView = (CPBView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
  1059. CPBDoc* pDoc = (pView == NULL)? NULL: pView->GetDocument();
  1060. if (pDoc != NULL)
  1061. {
  1062. theUndo.BeginUndo( TEXT("Property Edit") );
  1063. if (GetKeyState( VK_SHIFT ) < 0)
  1064. pDoc->m_pBitmapObj->SetIntProp( P_Shrink, 1 );
  1065. theApp.m_sizeBitmap = imageRect.Size();
  1066. pDoc->m_pBitmapObj->SetSizeProp( P_Size, theApp.m_sizeBitmap );
  1067. pDoc->m_pBitmapObj->SetIntProp ( P_Shrink, 0 );
  1068. theUndo.EndUndo();
  1069. }
  1070. }
  1071. else
  1072. {
  1073. // User was resizing the selection...
  1074. HideBrush();
  1075. theImgBrush.SetSize( imageRect.Size(), TRUE );
  1076. MoveBrush( imageRect );
  1077. }
  1078. return;
  1079. case WM_MOUSEMOVE:
  1080. switch (c_dragState)
  1081. {
  1082. default:
  1083. ASSERT(FALSE);
  1084. case CTracker::resizingTop:
  1085. imageRect.top = imagePt.y;
  1086. if (imageRect.top >= imageRect.bottom)
  1087. imageRect.top = imageRect.bottom - 1;
  1088. break;
  1089. case CTracker::resizingLeft:
  1090. imageRect.left = imagePt.x;
  1091. if (imageRect.left >= imageRect.right)
  1092. imageRect.left = imageRect.right - 1;
  1093. break;
  1094. case CTracker::resizingRight:
  1095. imageRect.right = imagePt.x;
  1096. if (imageRect.right <= imageRect.left)
  1097. imageRect.right = imageRect.left + 1;
  1098. break;
  1099. case CTracker::resizingBottom:
  1100. imageRect.bottom = imagePt.y;
  1101. if (imageRect.bottom <= imageRect.top)
  1102. imageRect.bottom = imageRect.top + 1;
  1103. break;
  1104. case CTracker::resizingTopLeft:
  1105. imageRect.left = imagePt.x;
  1106. imageRect.top = imagePt.y;
  1107. if (imageRect.top >= imageRect.bottom)
  1108. imageRect.top = imageRect.bottom - 1;
  1109. if (imageRect.left >= imageRect.right)
  1110. imageRect.left = imageRect.right - 1;
  1111. break;
  1112. case CTracker::resizingTopRight:
  1113. imageRect.top = imagePt.y;
  1114. imageRect.right = imagePt.x;
  1115. if (imageRect.top >= imageRect.bottom)
  1116. imageRect.top = imageRect.bottom - 1;
  1117. if (imageRect.right <= imageRect.left)
  1118. imageRect.right = imageRect.left + 1;
  1119. break;
  1120. case CTracker::resizingBottomLeft:
  1121. imageRect.left = imagePt.x;
  1122. imageRect.bottom = imagePt.y;
  1123. if (imageRect.left >= imageRect.right)
  1124. imageRect.left = imageRect.right - 1;
  1125. if (imageRect.bottom <= imageRect.top)
  1126. imageRect.bottom = imageRect.top + 1;
  1127. break;
  1128. case CTracker::resizingBottomRight:
  1129. imageRect.right = imagePt.x;
  1130. imageRect.bottom = imagePt.y;
  1131. if (imageRect.right <= imageRect.left)
  1132. imageRect.right = imageRect.left + 1;
  1133. if (imageRect.bottom <= imageRect.top)
  1134. imageRect.bottom = imageRect.top + 1;
  1135. break;
  1136. }
  1137. if (theImgBrush.m_pImg == NULL && m_pImg->m_bTileGrid)
  1138. {
  1139. // Snap to tile grid...
  1140. int cxTile = m_pImg->m_cxTile;
  1141. if (cxTile != 1 && cxTile <= m_pImg->cxWidth)
  1142. {
  1143. imageRect.right = ((imageRect.right + cxTile / 2) /
  1144. cxTile) * cxTile;
  1145. }
  1146. int cyTile = m_pImg->m_cyTile;
  1147. if (cyTile != 1 && cyTile <= m_pImg->cyHeight)
  1148. {
  1149. imageRect.bottom = ((imageRect.bottom + cyTile / 2) /
  1150. cyTile) * cyTile;
  1151. }
  1152. }
  1153. SetStatusBarSize(imageRect.Size());
  1154. ImageToClient(imageRect);
  1155. c_pResizeDragger->Move(imageRect, TRUE);
  1156. break;
  1157. }
  1158. }
  1159. /***************************************************************************/
  1160. void CImgWnd::StartSelectionDrag(unsigned code, CPoint newPt)
  1161. {
  1162. theImgBrush.CopyTo(theBackupBrush);
  1163. newPt.x /= m_nZoom;
  1164. newPt.y /= m_nZoom;
  1165. mti.pt = mti.ptDown = mti.ptPrev = newPt;
  1166. SetCapture();
  1167. SetCombineMode(theImgBrush.m_bOpaque ? combineReplace : combineMatte);
  1168. if (theImgBrush.m_bFirstDrag)
  1169. {
  1170. ASSERT(theImgBrush.m_pImg == m_pImg);
  1171. PickupSelection();
  1172. }
  1173. else
  1174. if (! theImgBrush.m_bOpaque)
  1175. theImgBrush.RecalcMask( crRight );
  1176. theImgBrush.TopLeftHandle();
  1177. theImgBrush.m_dragOffset = mti.pt - theImgBrush.m_rcSelection.TopLeft();
  1178. EraseTracker();
  1179. if (GetKeyState(VK_CONTROL) < 0)
  1180. {
  1181. // Copy the selection and start moving...
  1182. if (theImgBrush.m_bFirstDrag)
  1183. {
  1184. // The first time, the bits are already in
  1185. // the bitmap, so just copy them to the
  1186. // selection (which has already been done).
  1187. theImgBrush.m_bFirstDrag = FALSE;
  1188. theImgBrush.m_bLastDragWasFirst = TRUE;
  1189. }
  1190. else
  1191. {
  1192. CommitSelection(TRUE);
  1193. }
  1194. theImgBrush.m_bMoveSel = TRUE;
  1195. }
  1196. else
  1197. if (GetKeyState(VK_SHIFT) < 0)
  1198. {
  1199. // Start a smear operation...
  1200. HideBrush();
  1201. if (theImgBrush.m_bLastDragWasFirst)
  1202. CommitSelection(TRUE);
  1203. SetUndo(m_pImg);
  1204. theImgBrush.m_bSmearSel = TRUE;
  1205. theImgBrush.m_bFirstDrag = FALSE;
  1206. theImgBrush.m_bLastDragWasFirst = TRUE;
  1207. }
  1208. else
  1209. {
  1210. // Start a move operation...
  1211. theImgBrush.m_bMoveSel = TRUE;
  1212. }
  1213. g_bCustomBrush = TRUE;
  1214. }
  1215. /***************************************************************************/
  1216. void CImgWnd::CancelSelectionDrag()
  1217. {
  1218. if (!theImgBrush.m_bSmearSel && !theImgBrush.m_bMoveSel)
  1219. {
  1220. TRACE(TEXT("Extraneous CancelSelectionDrag!\n"));
  1221. return;
  1222. }
  1223. ReleaseCapture();
  1224. theImgBrush.m_rcSelection = theImgBrush.m_rcDraggedFrom;
  1225. theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE;
  1226. g_bCustomBrush = FALSE;
  1227. SetCombineMode(combineColor);
  1228. theBackupBrush.CopyTo(theImgBrush);
  1229. rcDragBrush = theImgBrush.m_rcSelection;
  1230. rcDragBrush.right += 1;
  1231. rcDragBrush.bottom += 1;
  1232. CancelPainting();
  1233. InvalImgRect(theImgBrush.m_pImg, NULL); // draw selection tracker
  1234. // "Opaque" mode may have changed...
  1235. if ((CImgTool::GetCurrentID() == IDMB_PICKTOOL)
  1236. || (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL))
  1237. g_pImgToolWnd->InvalidateOptions(FALSE);
  1238. // Cancel all the way now...
  1239. theImgBrush.m_pImg = NULL;
  1240. }
  1241. /***************************************************************************/
  1242. void CImgWnd::SelectionDragHandler(unsigned code, CPoint newPt)
  1243. {
  1244. switch (code)
  1245. {
  1246. case WM_CANCEL:
  1247. CancelSelectionDrag();
  1248. break;
  1249. case WM_MOUSEMOVE:
  1250. if (theImgBrush.m_bMoveSel)
  1251. PrepareForBrushChange(FALSE);
  1252. mti.ptPrev = mti.pt;
  1253. mti.pt = newPt;
  1254. theImgBrush.m_rcSelection.OffsetRect(
  1255. -theImgBrush.m_rcSelection.TopLeft()
  1256. + (CSize)mti.pt - theImgBrush.m_dragOffset);
  1257. // Make sure the selection stays at least along the edge
  1258. // of the actual image so we don't lose the tracker...
  1259. if (theImgBrush.m_rcSelection.left > m_pImg->cxWidth)
  1260. theImgBrush.m_rcSelection.OffsetRect(-theImgBrush.m_rcSelection.left + m_pImg->cxWidth, 0);
  1261. if (theImgBrush.m_rcSelection.top > m_pImg->cyHeight)
  1262. theImgBrush.m_rcSelection.OffsetRect(0, -theImgBrush.m_rcSelection.top + m_pImg->cyHeight);
  1263. if (theImgBrush.m_rcSelection.right < 0)
  1264. theImgBrush.m_rcSelection.OffsetRect(-theImgBrush.m_rcSelection.right, 0);
  1265. if (theImgBrush.m_rcSelection.bottom < 0)
  1266. theImgBrush.m_rcSelection.OffsetRect(0, -theImgBrush.m_rcSelection.bottom);
  1267. if (theImgBrush.m_bSmearSel)
  1268. DrawBrush(m_pImg, theImgBrush.m_rcSelection.TopLeft(), TRUE);
  1269. else
  1270. ShowBrush(theImgBrush.m_rcSelection.TopLeft());
  1271. break;
  1272. case WM_LBUTTONUP:
  1273. theImgBrush.m_bLastDragWasASmear = theImgBrush.m_bSmearSel;
  1274. if (theImgBrush.m_bSmearSel)
  1275. {
  1276. IMG* pImg = m_pImg;
  1277. CommitSelection(FALSE);
  1278. FinishUndo(CRect(0, 0, pImg->cxWidth, pImg->cyHeight));
  1279. }
  1280. ReleaseCapture();
  1281. theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE;
  1282. g_bCustomBrush = FALSE;
  1283. SetCombineMode(combineColor);
  1284. InvalImgRect(theImgBrush.m_pImg, NULL); // draw selection tracker
  1285. break;
  1286. }
  1287. }
  1288. /******************************************************************************/
  1289. BOOL CImgWnd::PtInTracker( CPoint cptLocation )
  1290. {
  1291. CRect selRect = theImgBrush.m_rcSelection;
  1292. BOOL bPtInTracker = FALSE;
  1293. selRect.left *= m_nZoom;
  1294. selRect.top *= m_nZoom;
  1295. selRect.right *= m_nZoom;
  1296. selRect.bottom *= m_nZoom;
  1297. selRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
  1298. bPtInTracker = selRect.PtInRect( cptLocation );
  1299. return bPtInTracker;
  1300. }
  1301. /******************************************************************************/
  1302. void CImgWnd::OnRButtonDownInSel(CPoint *pcPointDown)
  1303. {
  1304. CMenu cMenuPopup;
  1305. BOOL bRC = cMenuPopup.LoadMenu(IDR_SELECTION_POPUP);
  1306. ASSERT(bRC);
  1307. if (bRC)
  1308. {
  1309. CMenu *pcContextMenu = cMenuPopup.GetSubMenu(0);
  1310. ASSERT(pcContextMenu != NULL);
  1311. if (pcContextMenu != NULL)
  1312. {
  1313. CPoint cPointDown = *pcPointDown;
  1314. ImageToClient(cPointDown);
  1315. ClientToScreen(&cPointDown);
  1316. CRect cRectClient;
  1317. GetClientRect(&cRectClient);
  1318. ClientToScreen(&cRectClient);
  1319. // the frame actually has a clue about what items to enable...
  1320. CWnd *notify = GetParentFrame();
  1321. if (!notify)
  1322. notify = GetParent(); // oh well...
  1323. pcContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  1324. cPointDown.x, cPointDown.y, notify, &cRectClient);
  1325. }
  1326. }
  1327. }
  1328. /***************************************************************************/
  1329. void CImgWnd::ZoomedInDP(unsigned code, unsigned mouseKeys, CPoint newPt)
  1330. {
  1331. CPoint clientPt = newPt;
  1332. CPoint imagePt = clientPt;
  1333. ClientToImage( imagePt );
  1334. if (c_pResizeDragger != NULL)
  1335. {
  1336. ResizeMouseHandler( code, imagePt );
  1337. return;
  1338. }
  1339. int iHandleSize = CTracker::HANDLE_SIZE;
  1340. newPt.x -= iHandleSize + m_xScroll * m_nZoom;
  1341. newPt.y -= iHandleSize + m_yScroll * m_nZoom;
  1342. // AdjustPointForGrid(&newPt);
  1343. IMG* pImg = m_pImg;
  1344. int cxImage = pImg->cxWidth;
  1345. int cyImage = pImg->cyHeight;
  1346. CRect imageRect;
  1347. GetImageRect( imageRect );
  1348. // Check for selection manipulations...
  1349. if (GetCapture() != this
  1350. && c_pImgWndCur == this
  1351. && theImgBrush.m_pImg == m_pImg)
  1352. {
  1353. CRect selRect = theImgBrush.m_rcSelection;
  1354. BOOL bPtInTracker = FALSE;
  1355. selRect.left *= m_nZoom;
  1356. selRect.top *= m_nZoom;
  1357. selRect.right *= m_nZoom;
  1358. selRect.bottom *= m_nZoom;
  1359. selRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
  1360. bPtInTracker = PtInTracker(newPt);
  1361. if (bPtInTracker)
  1362. {
  1363. // Mouse is within the outer border of the tracker...
  1364. // We don't set the rubber for every mouse message when the
  1365. // selection tool is active, but we'd better set it up now!
  1366. if (pRubberImg != m_pImg)
  1367. SetupRubber(m_pImg);
  1368. ClearStatusBarPosition();
  1369. CTracker::STATE state;
  1370. selRect.InflateRect( -CTracker::HANDLE_SIZE,
  1371. -CTracker::HANDLE_SIZE );
  1372. state = CTracker::HitTest(selRect, newPt, CTracker::nil);
  1373. if (bPtInTracker && state == CTracker::nil)
  1374. {
  1375. // Actually inside the selection...
  1376. SetCursor(theApp.LoadCursor(IDCUR_MOVE));
  1377. if (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK)
  1378. {
  1379. StartSelectionDrag(code, newPt);
  1380. }
  1381. else
  1382. {
  1383. if (code == WM_RBUTTONDOWN || code == WM_RBUTTONDBLCLK)
  1384. // some of the menu commands don't work for free form selections
  1385. OnRButtonDownInSel( &imagePt );
  1386. }
  1387. }
  1388. else
  1389. {
  1390. // In the tracker frame...
  1391. SetCursor(HCursorFromTrackerState(state));
  1392. if (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK)
  1393. {
  1394. // Start a resize operation...
  1395. SetCapture();
  1396. PrepareForBrushChange();
  1397. ASSERT(c_pResizeDragger == NULL);
  1398. CRect rect = theImgBrush.m_rcSelection;
  1399. ImageToClient(rect);
  1400. c_pResizeDragger = new CDragger(this, &rect);
  1401. ASSERT(c_pResizeDragger != NULL);
  1402. c_dragState = state;
  1403. }
  1404. }
  1405. return;
  1406. }
  1407. }
  1408. if (! imageRect.PtInRect( clientPt )
  1409. && code != WM_CANCEL
  1410. && GetCapture() == NULL)
  1411. {
  1412. // The mouse is not inside the image and we're not in any
  1413. // special mode, so hide the brush...
  1414. if (g_pDragBrushWnd == this
  1415. && theImgBrush.m_pImg == NULL)
  1416. HideBrush();
  1417. CRect selRect = imageRect;
  1418. selRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
  1419. if (theImgBrush.m_pImg != NULL || ! selRect.PtInRect( clientPt ))
  1420. {
  1421. // The mouse is not in the whole image tracker
  1422. if (WM_LBUTTONDOWN == code)
  1423. {
  1424. if (CImgTool::GetCurrentID() != IDMX_TEXTTOOL)
  1425. {
  1426. CmdCancel ();
  1427. }
  1428. }
  1429. else
  1430. {
  1431. SetCursor( LoadCursor(NULL, IDC_ARROW ));
  1432. }
  1433. return;
  1434. }
  1435. // The mouse is in the whole image tracker, so set the cursor
  1436. // as appropriate
  1437. CTracker::STATE state = CTracker::nil;
  1438. if (c_pImgWndCur == this)
  1439. state = CTracker::HitTest(imageRect, clientPt, CTracker::nil);
  1440. switch (state)
  1441. {
  1442. case CTracker::resizingTop:
  1443. case CTracker::resizingLeft:
  1444. case CTracker::resizingTopLeft:
  1445. case CTracker::resizingTopRight:
  1446. case CTracker::resizingBottomLeft:
  1447. state = CTracker::nil;
  1448. break;
  1449. }
  1450. SetCursor( HCursorFromTrackerState( state ) );
  1451. // Handle mouse messages for tracker...
  1452. if (state != CTracker::nil
  1453. && (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK))
  1454. {
  1455. SetCapture();
  1456. ASSERT( c_pResizeDragger == NULL );
  1457. c_pResizeDragger = new CDragger( this, &imageRect );
  1458. ASSERT( c_pResizeDragger != NULL );
  1459. c_dragState = state;
  1460. }
  1461. return;
  1462. }
  1463. newPt.x /= m_nZoom;
  1464. newPt.y /= m_nZoom;
  1465. if (! CImgTool::IsDragging())
  1466. SetStatusBarPosition( m_ptDispPos );
  1467. // Moving the selection??
  1468. if (theImgBrush.m_bMoveSel
  1469. || theImgBrush.m_bSmearSel)
  1470. {
  1471. SelectionDragHandler( code, newPt );
  1472. return;
  1473. }
  1474. AdjustPointForGrid( &newPt );
  1475. // Dispatch the event off to the current tool...
  1476. CImgTool* pImgTool = CImgTool::GetCurrent();
  1477. switch (code)
  1478. {
  1479. case WM_CANCEL:
  1480. ReleaseCapture();
  1481. pImgTool->OnCancel(this);
  1482. mti.fLeft = mti.fRight = FALSE;
  1483. break;
  1484. case WM_LBUTTONDOWN:
  1485. case WM_LBUTTONDBLCLK:
  1486. case WM_RBUTTONDOWN:
  1487. case WM_RBUTTONDBLCLK:
  1488. // We don't set the rubber for every mouse message when the
  1489. // selection tool is active, but we'd better set it up now!
  1490. if (pRubberImg != m_pImg)
  1491. SetupRubber( m_pImg );
  1492. mti.fLeft = (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK);
  1493. mti.fRight = (code == WM_RBUTTONDOWN || code == WM_RBUTTONDBLCLK);
  1494. mti.pt = mti.ptDown = mti.ptPrev = newPt;
  1495. // if in the polygon tool, double clicks will end operation
  1496. if (CImgTool::GetCurrentID() == IDMB_POLYGONTOOL
  1497. && ((code == WM_LBUTTONDBLCLK) || (code == WM_RBUTTONDBLCLK)))
  1498. {
  1499. mti.ptPrev = mti.pt;
  1500. mti.pt = newPt;
  1501. pImgTool->EndMultiptOperation(); // end the multipt operation
  1502. pImgTool->OnEndDrag( this, &mti );
  1503. mti.fLeft = FALSE;
  1504. mti.fRight = FALSE;
  1505. break;
  1506. }
  1507. SetCapture();
  1508. if (CImgTool::GetCurrentID() != IDMB_PICKRGNTOOL)
  1509. HideBrush();
  1510. if (pImgTool->IsUndoable())
  1511. SetUndo(m_pImg);
  1512. pImgTool->OnStartDrag( this, &mti );
  1513. break;
  1514. case WM_LBUTTONUP:
  1515. case WM_RBUTTONUP:
  1516. mti.ptPrev = mti.pt;
  1517. mti.pt = newPt;
  1518. if (GetCapture() != this)
  1519. break;
  1520. ReleaseCapture();
  1521. pImgTool->CanEndMultiptOperation( &mti );
  1522. pImgTool->OnEndDrag( this, &mti );
  1523. if (code == WM_LBUTTONUP)
  1524. {
  1525. mti.fLeft = FALSE;
  1526. }
  1527. if (code == WM_RBUTTONUP)
  1528. {
  1529. mti.fRight = FALSE;
  1530. }
  1531. break;
  1532. case WM_MOUSEMOVE:
  1533. mti.ptPrev = mti.pt;
  1534. mti.pt = newPt;
  1535. if (mti.fLeft || mti.fRight)
  1536. pImgTool->OnDrag(this, &mti);
  1537. else
  1538. pImgTool->OnMove(this, &mti);
  1539. break;
  1540. case WM_TIMER:
  1541. pImgTool->OnTimer( this, &mti );
  1542. break;
  1543. }
  1544. UpdateWindow(); // For immediate feedback in active window
  1545. SetToolCursor();
  1546. }
  1547. /***************************************************************************/
  1548. void CImgWnd::FinishUndo(const CRect& rectUndo)
  1549. {
  1550. if ( EnsureUndoSize(m_pImg) )
  1551. m_pImg->m_pBitmapObj->FinishUndo(&rectUndo);
  1552. else
  1553. {
  1554. TRACE(TEXT("Problem: Can NOT ensure undo capability!\n"));
  1555. MessageBeep(0);
  1556. }
  1557. }
  1558. /***************************************************************************/
  1559. void CImgWnd::CancelPainting()
  1560. {
  1561. if (g_hUndoImgBitmap == NULL)
  1562. return; // nothing to cancel!
  1563. IMG* pimg;
  1564. HDC hTempDC;
  1565. HBITMAP hOldBM;
  1566. HPALETTE hOldPalette = NULL;
  1567. pimg = m_pImg;
  1568. if ((hTempDC = CreateCompatibleDC( pimg->hDC )) == NULL)
  1569. {
  1570. TRACE(TEXT("Not enough memory to undo!\n"));
  1571. MessageBeep(0);
  1572. return;
  1573. }
  1574. HideBrush();
  1575. if (g_hUndoPalette)
  1576. {
  1577. if (pimg->m_hPalOld)
  1578. {
  1579. ::SelectPalette( pimg->hDC, pimg->m_hPalOld, FALSE );
  1580. pimg->m_hPalOld = NULL;
  1581. }
  1582. if (pimg->m_pPalette)
  1583. pimg->m_pPalette->DeleteObject();
  1584. pimg->m_pPalette->Attach( g_hUndoPalette );
  1585. g_hUndoPalette = NULL;
  1586. pimg->m_hPalOld = ::SelectPalette( pimg->hDC,
  1587. (HPALETTE)pimg->m_pPalette->GetSafeHandle(), FALSE );
  1588. ::RealizePalette( pimg->hDC );
  1589. }
  1590. hOldBM = (HBITMAP)SelectObject( hTempDC, g_hUndoImgBitmap );
  1591. if (pimg->m_pPalette)
  1592. {
  1593. hOldPalette = ::SelectPalette( hTempDC,
  1594. (HPALETTE)pimg->m_pPalette->GetSafeHandle(), FALSE );
  1595. ::RealizePalette( hTempDC );
  1596. }
  1597. ASSERT( hOldBM != NULL );
  1598. BitBlt( pimg->hDC, 0, 0, pimg->cxWidth, pimg->cyHeight, hTempDC, 0, 0, SRCCOPY );
  1599. if (hOldPalette != NULL)
  1600. ::SelectPalette( hTempDC, hOldPalette, FALSE );
  1601. SelectObject( hTempDC, hOldBM );
  1602. DeleteDC ( hTempDC );
  1603. InvalImgRect ( m_pImg, NULL );
  1604. CommitImgRect( m_pImg, NULL );
  1605. }
  1606. #ifdef GRIDOPTIONS
  1607. /***************************************************************************/
  1608. void CImgWnd::CmdGridOptions()
  1609. {
  1610. CImgGridDlg dlg;
  1611. dlg.m_bPixelGrid = theApp.m_bShowGrid;
  1612. dlg.m_bTileGrid = m_pImg->m_bTileGrid;
  1613. dlg.m_nWidth = m_pImg->m_cxTile;
  1614. dlg.m_nHeight = m_pImg->m_cyTile;
  1615. if (dlg.DoModal() != IDOK)
  1616. return;
  1617. // Hide the current is dependant on the state of the grid...
  1618. BOOL bOldShowGrid = theApp.m_bShowGrid;
  1619. theApp.m_bShowGrid = dlg.m_bPixelGrid;
  1620. m_pImg->m_bTileGrid = dlg.m_bTileGrid;
  1621. m_pImg->m_cxTile = dlg.m_nWidth;
  1622. m_pImg->m_cyTile = dlg.m_nHeight;
  1623. InvalImgRect(m_pImg, NULL);
  1624. if (bOldShowGrid != theApp.m_bShowGrid)
  1625. {
  1626. if (c_pImgWndCur != NULL)
  1627. c_pImgWndCur->Invalidate(FALSE); // Redraw tracker
  1628. }
  1629. }
  1630. #endif // GRIDOPTIONS
  1631. /***************************************************************************/
  1632. void CImgWnd::CmdShowGrid()
  1633. {
  1634. // Hide the current cross hair since the width of the lines
  1635. // is dependant on the state of the grid...
  1636. theApp.m_bShowGrid = ! theApp.m_bShowGrid;
  1637. InvalImgRect(m_pImg, NULL);
  1638. if (c_pImgWndCur != NULL)
  1639. c_pImgWndCur->Invalidate(FALSE); // Redraw tracker
  1640. }
  1641. /***************************************************************************/
  1642. // Draw a grid over the image already in the bitmap in pDC. Drawing
  1643. // is optimized by restricting it to destRect.
  1644. //
  1645. void CImgWnd::DrawGrid(CDC* pDC, const CRect& srcRect, CRect& destRect)
  1646. {
  1647. ASSERT(pDC != NULL);
  1648. ASSERT(m_pImg != NULL);
  1649. pDC->SetTextColor(RGB(192, 192, 192));
  1650. pDC->SetBkColor(RGB(128, 128, 128));
  1651. CBrush* pOldBrush = pDC->SelectObject(GetHalftoneBrush());
  1652. CRect gridRect(0, 0, m_pImg->cxWidth * m_nZoom + 1,
  1653. m_pImg->cyHeight * m_nZoom + 1);
  1654. for (int x = gridRect.left; x <= gridRect.right; x += m_nZoom)
  1655. pDC->PatBlt(x, gridRect.top, 1, gridRect.Height(), PATCOPY);
  1656. for (int y = gridRect.top; y <= gridRect.bottom; y += m_nZoom)
  1657. pDC->PatBlt(gridRect.left, y, gridRect.Width(), 1, PATCOPY);
  1658. if (m_pImg->m_bTileGrid)
  1659. {
  1660. pDC->SetTextColor(RGB(0, 0, 255));
  1661. pDC->SetBkColor(RGB(0, 0, 128));
  1662. int nWidth = destRect.Width();
  1663. int nHeight = destRect.Height();
  1664. int nStep;
  1665. if (m_pImg->m_cxTile > 1 && m_pImg->m_cxTile <= m_pImg->cxWidth)
  1666. {
  1667. nStep = m_nZoom * m_pImg->m_cxTile;
  1668. for (x = (m_pImg->m_cxTile - srcRect.left % m_pImg->m_cxTile -
  1669. m_pImg->m_cxTile) * m_nZoom; x <= nWidth; x += nStep)
  1670. {
  1671. pDC->PatBlt(x, 0, 1, nHeight, PATCOPY);
  1672. }
  1673. }
  1674. if (m_pImg->m_cyTile > 1 && m_pImg->m_cyTile <= m_pImg->cyHeight)
  1675. {
  1676. nStep = m_nZoom * m_pImg->m_cyTile;
  1677. for (y = (m_pImg->m_cyTile - srcRect.top % m_pImg->m_cyTile -
  1678. m_pImg->m_cyTile) * m_nZoom; y <= nHeight; y += nStep)
  1679. {
  1680. pDC->PatBlt(0, y, nWidth, 1, PATCOPY);
  1681. }
  1682. }
  1683. }
  1684. pDC->SelectObject(pOldBrush);
  1685. destRect.right += 1;
  1686. destRect.bottom += 1;
  1687. }
  1688. #ifdef GRIDOPTIONS
  1689. /***************************************************************************/
  1690. void CImgWnd::CmdShowTileGrid()
  1691. {
  1692. extern BOOL g_bDefaultTileGrid;
  1693. // If neither grid is visible, show both. Otherwise leave the pixel
  1694. // grid alone and toggle the tile grid.
  1695. if (! theApp.m_bShowGrid)
  1696. {
  1697. m_pImg->m_bTileGrid = TRUE;
  1698. theApp.m_bShowGrid = TRUE;
  1699. }
  1700. else
  1701. {
  1702. m_pImg->m_bTileGrid = !m_pImg->m_bTileGrid;
  1703. }
  1704. g_bDefaultTileGrid = m_pImg->m_bTileGrid;
  1705. InvalImgRect(m_pImg, NULL);
  1706. if (c_pImgWndCur != NULL)
  1707. c_pImgWndCur->Invalidate(FALSE); // Redraw tracker
  1708. }
  1709. #endif // GRIDOPTIONS
  1710. /***************************************************************************/
  1711. void CImgWnd::MoveBrush( const CRect& newSelRect )
  1712. {
  1713. if (! theImgBrush.m_pImg)
  1714. return;
  1715. theImgBrush.m_rcSelection = newSelRect;
  1716. InvalImgRect( theImgBrush.m_pImg, NULL );
  1717. theImgBrush.m_handle.cx = theImgBrush.m_handle.cy = 0;
  1718. BOOL bOldCustomBrush = g_bCustomBrush;
  1719. g_bCustomBrush = TRUE;
  1720. int wOldCombineMode = wCombineMode;
  1721. SetCombineMode( theImgBrush.m_bOpaque ? combineReplace : combineMatte );
  1722. ShowBrush( theImgBrush.m_rcSelection.TopLeft() );
  1723. g_bCustomBrush = bOldCustomBrush;
  1724. SetCombineMode( wOldCombineMode );
  1725. }
  1726. /***************************************************************************/
  1727. BOOL CImgWnd::MakeBrush( HDC hSourceDC, CRect rcSource )
  1728. {
  1729. int cxWidth;
  1730. int cyHeight;
  1731. int iToolID = CImgTool::GetCurrentID();
  1732. if (rcSource.IsRectEmpty())
  1733. {
  1734. ASSERT( FALSE );
  1735. return FALSE;
  1736. }
  1737. theImgBrush.m_size = rcSource.Size();
  1738. cxWidth = theImgBrush.m_size.cx;
  1739. cyHeight = theImgBrush.m_size.cy;
  1740. if (theImgBrush.m_hbmOld)
  1741. ::SelectObject( theImgBrush.m_dc.m_hDC, theImgBrush.m_hbmOld );
  1742. if (theImgBrush.m_hbmMaskOld)
  1743. ::SelectObject( theImgBrush.m_dc.m_hDC, theImgBrush.m_hbmMaskOld );
  1744. theImgBrush.m_hbmOld = NULL;
  1745. theImgBrush.m_hbmMaskOld = NULL;
  1746. theImgBrush.m_dc.DeleteDC();
  1747. theImgBrush.m_bitmap.DeleteObject();
  1748. theImgBrush.m_maskDC.DeleteDC();
  1749. theImgBrush.m_maskBitmap.DeleteObject();
  1750. CDC* pdcSource = CDC::FromHandle( hSourceDC );
  1751. CDC* pdcBitmap = CDC::FromHandle( m_pImg->hDC );
  1752. if (! theImgBrush.m_bitmap.CreateCompatibleBitmap( pdcBitmap, cxWidth, cyHeight )
  1753. || ! theImgBrush.m_dc.CreateCompatibleDC ( pdcBitmap )
  1754. || ! theImgBrush.m_maskBitmap.CreateBitmap ( cxWidth, cyHeight, 1, 1, NULL)
  1755. || ! theImgBrush.m_maskDC.CreateCompatibleDC ( pdcBitmap ))
  1756. {
  1757. theApp.SetGdiEmergency();
  1758. return FALSE;
  1759. }
  1760. theImgBrush.m_pImg = m_pImg;
  1761. theImgBrush.m_hbmOld = (HBITMAP)((theImgBrush.m_dc.SelectObject(
  1762. &theImgBrush.m_bitmap ))->GetSafeHandle());
  1763. theImgBrush.m_hbmMaskOld = (HBITMAP)((theImgBrush.m_maskDC.SelectObject(
  1764. &theImgBrush.m_maskBitmap ))->GetSafeHandle());
  1765. CPalette* pcOldPalette = SetImgPalette( &theImgBrush.m_dc, FALSE );
  1766. if (iToolID == IDMB_PICKRGNTOOL)
  1767. {
  1768. // Using StretchBlt to ensure palette mapping occurs
  1769. TRY {
  1770. CBrush cBrushWhite( PALETTERGB( 0xff, 0xff, 0xff ) );
  1771. CRect cRectTmp( 0, 0, cxWidth, cyHeight );
  1772. theImgBrush.m_dc.FillRect( &cRectTmp, &cBrushWhite );
  1773. }
  1774. CATCH(CResourceException, e)
  1775. {
  1776. theApp.SetGdiEmergency();
  1777. return FALSE;
  1778. }
  1779. END_CATCH
  1780. if (theImgBrush.m_cRgnPolyFreeHandSel.GetSafeHandle())
  1781. theImgBrush.m_dc.FillRgn( &theImgBrush.m_cRgnPolyFreeHandSel,
  1782. CBrush::FromHandle( (HBRUSH)::GetStockObject( BLACK_BRUSH ) ) );
  1783. theImgBrush.m_dc.StretchBlt( 0, 0, cxWidth, cyHeight,
  1784. pdcSource,
  1785. rcSource.left, rcSource.top,
  1786. cxWidth, cyHeight, SRCERASE);
  1787. }
  1788. else
  1789. {
  1790. // Using StretchBlt to ensure palette mapping occurs
  1791. theImgBrush.m_dc.StretchBlt( 0, 0, cxWidth, cyHeight,
  1792. pdcSource,
  1793. rcSource.left, rcSource.top,
  1794. cxWidth, cyHeight, SRCCOPY );
  1795. }
  1796. theImgBrush.RecalcMask( crRight );
  1797. if (pcOldPalette)
  1798. theImgBrush.m_dc.SelectPalette( pcOldPalette, FALSE );
  1799. theImgBrush.m_rcSelection = rcSource;
  1800. rcSource.right += 1;
  1801. rcSource.bottom += 1;
  1802. InvalImgRect( m_pImg, NULL ); // Redraw selection tracker
  1803. rcDragBrush = rcSource;
  1804. g_bBrushVisible = TRUE;
  1805. g_pDragBrushWnd = this;
  1806. theImgBrush.m_bFirstDrag = TRUE;
  1807. theImgBrush.m_bLastDragWasFirst = FALSE;
  1808. return TRUE;
  1809. }
  1810. /***************************************************************************/
  1811. void CImgWnd::CmdClear()
  1812. {
  1813. if (TextToolProcessed( ID_EDIT_CLEAR ))
  1814. return;
  1815. HPALETTE hOldPalette = NULL;
  1816. HBRUSH hNewBrush, hOldBrush;
  1817. IMG* pImg = m_pImg;
  1818. if ((hNewBrush = CreateSolidBrush( crRight )) == NULL)
  1819. {
  1820. theApp.SetGdiEmergency();
  1821. return;
  1822. }
  1823. HideBrush();
  1824. CRect clearRect;
  1825. if (theImgBrush.m_pImg == NULL)
  1826. clearRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight);
  1827. else
  1828. {
  1829. clearRect = rcDragBrush;
  1830. clearRect.right -= 1;
  1831. clearRect.bottom -= 1;
  1832. }
  1833. BOOL bUndo = FALSE;
  1834. if (!theImgBrush.m_pImg || theImgBrush.m_bFirstDrag
  1835. || theImgBrush.m_bCuttingFromImage)
  1836. {
  1837. bUndo = TRUE;
  1838. SetUndo(m_pImg);
  1839. if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
  1840. {
  1841. int iPoints;
  1842. CPoint* pptArray;
  1843. BOOL bData = ((CFreehandSelectTool*)CImgTool::GetCurrent())->CopyPointsToMemArray( &pptArray, &iPoints );
  1844. if (bData && iPoints)
  1845. {
  1846. HRGN hrgn = ::CreatePolygonRgn( pptArray, iPoints, ALTERNATE );
  1847. if (hrgn)
  1848. ::FillRgn( pImg->hDC, hrgn, hNewBrush );
  1849. delete [] pptArray;
  1850. }
  1851. else
  1852. {
  1853. DeleteObject ( hNewBrush );
  1854. theApp.SetMemoryEmergency();
  1855. return;
  1856. }
  1857. }
  1858. else
  1859. {
  1860. hOldBrush = (HBRUSH)SelectObject(pImg->hDC, hNewBrush);
  1861. PatBlt( pImg->hDC, clearRect.left,
  1862. clearRect.top,
  1863. clearRect.Width(),
  1864. clearRect.Height(), PATCOPY );
  1865. SelectObject( pImg->hDC, hOldBrush );
  1866. }
  1867. }
  1868. InvalImgRect ( m_pImg, &clearRect );
  1869. CommitImgRect( m_pImg, &clearRect );
  1870. if (bUndo)
  1871. FinishUndo(clearRect);
  1872. DirtyImg ( m_pImg );
  1873. DeleteObject ( hNewBrush );
  1874. // If we have a selection, nuke it since it's useless now...
  1875. if (theImgBrush.m_pImg != NULL)
  1876. {
  1877. if (theImgBrush.m_bLastDragWasFirst)
  1878. {
  1879. theImgBrush.m_bLastDragWasFirst = FALSE;
  1880. FinishUndo(theImgBrush.m_rcDraggedFrom);
  1881. }
  1882. theImgBrush.m_handle.cx = 0;
  1883. theImgBrush.m_handle.cy = 0;
  1884. theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE;
  1885. g_bCustomBrush = FALSE;
  1886. SetCombineMode(combineColor);
  1887. InvalImgRect(theImgBrush.m_pImg, NULL); // redraw selection
  1888. theImgBrush.m_pImg = NULL;
  1889. }
  1890. }
  1891. /***************************************************************************/
  1892. void CImgWnd::CmdFlipBshH()
  1893. {
  1894. IMG* pImg = m_pImg;
  1895. HideBrush();
  1896. CRect flipRect;
  1897. if (theImgBrush.m_pImg == NULL && !g_bCustomBrush)
  1898. {
  1899. flipRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight);
  1900. }
  1901. else
  1902. {
  1903. flipRect = rcDragBrush;
  1904. flipRect.right -= 1;
  1905. flipRect.bottom -= 1;
  1906. }
  1907. if ( theImgBrush.m_pImg != NULL
  1908. && ! theImgBrush.m_bFirstDrag || g_bCustomBrush)
  1909. {
  1910. CPalette* ppal = SetImgPalette( &theImgBrush.m_dc, FALSE );
  1911. //
  1912. // Don't do halftone blts when just moving bits around
  1913. //
  1914. theImgBrush.m_dc.SetStretchBltMode (COLORONCOLOR);
  1915. StretchCopy(theImgBrush.m_dc.m_hDC, 0, 0,
  1916. theImgBrush.m_size.cx,
  1917. theImgBrush.m_size.cy,
  1918. theImgBrush.m_dc.m_hDC,
  1919. theImgBrush.m_size.cx - 1, 0,
  1920. -theImgBrush.m_size.cx,
  1921. theImgBrush.m_size.cy);
  1922. StretchCopy(theImgBrush.m_maskDC.m_hDC, 0, 0,
  1923. theImgBrush.m_size.cx,
  1924. theImgBrush.m_size.cy,
  1925. theImgBrush.m_maskDC.m_hDC,
  1926. theImgBrush.m_size.cx - 1, 0,
  1927. -theImgBrush.m_size.cx,
  1928. theImgBrush.m_size.cy);
  1929. if (ppal)
  1930. theImgBrush.m_dc.SelectPalette( ppal, FALSE ); // Background ??
  1931. MoveBrush(theImgBrush.m_rcSelection);
  1932. }
  1933. else
  1934. {
  1935. SetUndo(m_pImg);
  1936. SetStretchBltMode (pImg->hDC, COLORONCOLOR);
  1937. StretchCopy(pImg->hDC, flipRect.left,
  1938. flipRect.top,
  1939. flipRect.Width(),
  1940. flipRect.Height(),
  1941. pImg->hDC, flipRect.left + flipRect.Width() - 1,
  1942. flipRect.top,
  1943. -flipRect.Width(),
  1944. flipRect.Height());
  1945. InvalImgRect (m_pImg, &flipRect);
  1946. CommitImgRect(m_pImg, &flipRect);
  1947. FinishUndo (flipRect);
  1948. DirtyImg (m_pImg);
  1949. }
  1950. }
  1951. /***************************************************************************/
  1952. void CImgWnd::CmdFlipBshV()
  1953. {
  1954. IMG* pImg = m_pImg;
  1955. HideBrush();
  1956. CRect flipRect;
  1957. if (theImgBrush.m_pImg == NULL && !g_bCustomBrush)
  1958. {
  1959. flipRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight);
  1960. }
  1961. else
  1962. {
  1963. flipRect = rcDragBrush;
  1964. flipRect.right -= 1;
  1965. flipRect.bottom -= 1;
  1966. }
  1967. if ( theImgBrush.m_pImg != NULL
  1968. && ! theImgBrush.m_bFirstDrag || g_bCustomBrush)
  1969. {
  1970. CPalette* ppal = SetImgPalette( &theImgBrush.m_dc, FALSE ); // Background ??
  1971. theImgBrush.m_dc.SetStretchBltMode (COLORONCOLOR);
  1972. StretchCopy(theImgBrush.m_dc.m_hDC, 0, 0,
  1973. theImgBrush.m_size.cx,
  1974. theImgBrush.m_size.cy,
  1975. theImgBrush.m_dc.m_hDC, 0,
  1976. theImgBrush.m_size.cy - 1,
  1977. theImgBrush.m_size.cx,
  1978. -theImgBrush.m_size.cy);
  1979. StretchCopy(theImgBrush.m_maskDC.m_hDC, 0, 0,
  1980. theImgBrush.m_size.cx,
  1981. theImgBrush.m_size.cy,
  1982. theImgBrush.m_maskDC.m_hDC, 0,
  1983. theImgBrush.m_size.cy - 1,
  1984. theImgBrush.m_size.cx,
  1985. -theImgBrush.m_size.cy);
  1986. if (ppal)
  1987. theImgBrush.m_dc.SelectPalette( ppal, FALSE ); // Background ??
  1988. MoveBrush(theImgBrush.m_rcSelection);
  1989. }
  1990. else
  1991. {
  1992. SetUndo(m_pImg);
  1993. SetStretchBltMode (pImg->hDC, COLORONCOLOR);
  1994. StretchCopy(pImg->hDC, flipRect.left, flipRect.top,
  1995. flipRect.Width(), flipRect.Height(),
  1996. pImg->hDC, flipRect.left, flipRect.top + flipRect.Height() - 1,
  1997. flipRect.Width(), -flipRect.Height());
  1998. InvalImgRect (m_pImg, &flipRect);
  1999. CommitImgRect(m_pImg, &flipRect);
  2000. FinishUndo (flipRect);
  2001. DirtyImg (m_pImg);
  2002. }
  2003. }
  2004. /***************************************************************************/
  2005. void CImgWnd::CmdDoubleBsh()
  2006. {
  2007. if (!g_bCustomBrush && theImgBrush.m_pImg == NULL)
  2008. {
  2009. MessageBeep(0);
  2010. return;
  2011. }
  2012. PrepareForBrushChange(TRUE, FALSE);
  2013. CRect rc = theImgBrush.m_rcSelection;
  2014. rc.left -= theImgBrush.m_size.cx / 2;
  2015. rc.right = rc.left + theImgBrush.m_size.cx * 2;
  2016. rc.top -= theImgBrush.m_size.cy / 2;
  2017. rc.bottom = rc.top + theImgBrush.m_size.cy * 2;
  2018. HideBrush();
  2019. theImgBrush.SetSize( CSize( theImgBrush.m_size.cx * 2,
  2020. theImgBrush.m_size.cy * 2 ) );
  2021. MoveBrush(rc);
  2022. if (g_bCustomBrush)
  2023. theImgBrush.CenterHandle();
  2024. }
  2025. /***************************************************************************/
  2026. void CImgWnd::CmdHalfBsh()
  2027. {
  2028. if (! g_bCustomBrush
  2029. && ! theImgBrush.m_pImg)
  2030. {
  2031. MessageBeep(0);
  2032. return;
  2033. }
  2034. PrepareForBrushChange( TRUE, FALSE );
  2035. CRect rc = theImgBrush.m_rcSelection;
  2036. rc.left += theImgBrush.m_size.cx / 4;
  2037. rc.right = rc.left + (theImgBrush.m_size.cx + 1) / 2;
  2038. rc.top += theImgBrush.m_size.cy / 4;
  2039. rc.bottom = rc.top + (theImgBrush.m_size.cy + 1) / 2;
  2040. HideBrush();
  2041. theImgBrush.SetSize( CSize( (theImgBrush.m_size.cx + 1) / 2,
  2042. (theImgBrush.m_size.cy + 1) / 2 ) );
  2043. MoveBrush( rc );
  2044. if (g_bCustomBrush)
  2045. theImgBrush.CenterHandle();
  2046. }
  2047. /***************************************************************************/
  2048. CPalette* CImgWnd::FixupDibPalette( LPSTR lpDib, CPalette* ppalDib )
  2049. {
  2050. CPBView* pView = (CPBView*)GetParent();
  2051. CPBDoc* pDoc = pView->GetDocument();
  2052. if (pDoc == NULL || lpDib == NULL || ppalDib == NULL || pDoc->m_pBitmapObj->m_pImg == NULL)
  2053. return ppalDib;
  2054. IMG* pImg = pDoc->m_pBitmapObj->m_pImg;
  2055. int iColorBits = pImg->cBitCount * pImg->cPlanes;
  2056. BOOL bFixupDib = TRUE;
  2057. BOOL bSwapPalette = TRUE;
  2058. // only if dealing with palettes
  2059. if (iColorBits != 8)
  2060. return ppalDib;
  2061. CPalette* ppalPic = theApp.m_pPalette;
  2062. CPalette* ppalNew = NULL;
  2063. BOOL bMergedPalette = FALSE;
  2064. if (ppalPic)
  2065. {
  2066. int iAdds;
  2067. if ( ppalNew = MergePalettes( ppalPic, ppalDib, iAdds ) )
  2068. bMergedPalette = TRUE;
  2069. if (ppalNew)
  2070. {
  2071. if (! iAdds)
  2072. {
  2073. bSwapPalette = FALSE;
  2074. if ( bMergedPalette )
  2075. {
  2076. delete ppalNew;
  2077. ppalNew = FALSE;
  2078. bMergedPalette = FALSE;
  2079. }
  2080. ppalNew = ppalPic;
  2081. }
  2082. }
  2083. else
  2084. {
  2085. bSwapPalette = FALSE;
  2086. if ( bMergedPalette )
  2087. {
  2088. delete ppalNew;
  2089. ppalNew = FALSE;
  2090. bMergedPalette = FALSE;
  2091. }
  2092. ppalNew = ppalPic;
  2093. }
  2094. }
  2095. else
  2096. {
  2097. if ( bMergedPalette )
  2098. {
  2099. delete ppalNew;
  2100. ppalNew = FALSE;
  2101. bMergedPalette = FALSE;
  2102. }
  2103. ppalNew = ppalDib;
  2104. bFixupDib = FALSE;
  2105. }
  2106. if (bFixupDib)
  2107. {
  2108. LOGPALETTE256 palette;
  2109. COLORREF crCurColor;
  2110. UINT uColorIndex;
  2111. int iDibColors = DIBNumColors( lpDib );
  2112. BOOL bWinStyleDIB = IS_WIN30_DIB( lpDib );
  2113. LPBITMAPINFO lpDibInfo = (LPBITMAPINFO)lpDib;
  2114. LPBITMAPCOREINFO lpCoreInfo = (LPBITMAPCOREINFO)lpDib;
  2115. palette.palVersion = 0x300;
  2116. palette.palNumEntries = (WORD)ppalNew->GetPaletteEntries( 0, 256,
  2117. &palette.palPalEntry[0] );
  2118. ppalNew->GetPaletteEntries( 0, palette.palNumEntries,
  2119. &palette.palPalEntry[0] );
  2120. for (int iLoop = 0; iLoop < iDibColors; iLoop++)
  2121. {
  2122. if (bWinStyleDIB)
  2123. {
  2124. crCurColor = PALETTERGB( lpDibInfo->bmiColors[iLoop].rgbRed,
  2125. lpDibInfo->bmiColors[iLoop].rgbGreen,
  2126. lpDibInfo->bmiColors[iLoop].rgbBlue );
  2127. }
  2128. else
  2129. {
  2130. crCurColor = PALETTERGB( lpCoreInfo->bmciColors[iLoop].rgbtRed,
  2131. lpCoreInfo->bmciColors[iLoop].rgbtGreen,
  2132. lpCoreInfo->bmciColors[iLoop].rgbtBlue );
  2133. }
  2134. uColorIndex = ppalNew->GetNearestPaletteIndex( crCurColor );
  2135. if (bWinStyleDIB)
  2136. {
  2137. lpDibInfo->bmiColors[iLoop].rgbRed = palette.palPalEntry[uColorIndex].peRed;
  2138. lpDibInfo->bmiColors[iLoop].rgbGreen = palette.palPalEntry[uColorIndex].peGreen;
  2139. lpDibInfo->bmiColors[iLoop].rgbBlue = palette.palPalEntry[uColorIndex].peBlue;
  2140. }
  2141. else
  2142. {
  2143. lpCoreInfo->bmciColors[iLoop].rgbtRed = palette.palPalEntry[uColorIndex].peRed;
  2144. lpCoreInfo->bmciColors[iLoop].rgbtGreen = palette.palPalEntry[uColorIndex].peGreen;
  2145. lpCoreInfo->bmciColors[iLoop].rgbtBlue = palette.palPalEntry[uColorIndex].peBlue;
  2146. }
  2147. }
  2148. if (! bSwapPalette)
  2149. {
  2150. if ( bMergedPalette )
  2151. {
  2152. delete ppalNew;
  2153. bMergedPalette = FALSE;
  2154. }
  2155. ppalNew = NULL;
  2156. }
  2157. }
  2158. if (bSwapPalette)
  2159. {
  2160. if (pImg->m_hPalOld)
  2161. {
  2162. ::SelectPalette( pImg->hDC, pImg->m_hPalOld, FALSE );
  2163. pImg->m_hPalOld = NULL;
  2164. }
  2165. if (pImg->m_pPalette)
  2166. delete pImg->m_pPalette;
  2167. pImg->m_pPalette = ppalNew;
  2168. pImg->m_hPalOld = ::SelectPalette( pImg->hDC,
  2169. (HPALETTE)ppalNew->GetSafeHandle(), FALSE );
  2170. ::RealizePalette( pImg->hDC );
  2171. InvalImgRect( pImg, NULL );
  2172. // Return NULL since we swapped the new palette into the pImg!
  2173. ppalNew = NULL;
  2174. theApp.m_pPalette = pImg->m_pPalette;
  2175. //
  2176. // now that we changed the app palette update the DIB Section
  2177. // color table too.
  2178. //
  2179. DWORD rgb[256];
  2180. int i,n;
  2181. n = theApp.m_pPalette->GetPaletteEntries(0, 256, (LPPALETTEENTRY)rgb);
  2182. for (i=0; i<n; i++)
  2183. rgb[i] = RGB(GetBValue(rgb[i]),GetGValue(rgb[i]),GetRValue(rgb[i]));
  2184. SetDIBColorTable(pImg->hDC, 0, n, (LPRGBQUAD)rgb);
  2185. }
  2186. // Delete any orphaned ppalDib pointers.
  2187. if ( ppalDib && ppalDib != ppalNew )
  2188. delete ppalDib;
  2189. return ppalNew;
  2190. }
  2191. /***************************************************************************/
  2192. void CImgWnd::ShowBrush(CPoint ptHandle)
  2193. {
  2194. IMG * pimg = m_pImg;
  2195. HideBrush();
  2196. COLORREF crRealLeftColor;
  2197. COLORREF crRealRightColor;
  2198. int nStrokeWidth = CImgTool::GetCurrent()->GetStrokeWidth();
  2199. int nStrokeShape = CImgTool::GetCurrent()->GetStrokeShape();
  2200. if (CImgTool::GetCurrentID() == IDMB_ERASERTOOL)
  2201. {
  2202. crRealRightColor = crRight;
  2203. crRealLeftColor = crLeft;
  2204. crLeft = crRight;
  2205. }
  2206. g_pDragBrushWnd = this;
  2207. if (g_bCustomBrush)
  2208. {
  2209. int nCombineMode = (theImgBrush.m_bOpaque) ? combineReplace : combineMatte;
  2210. rcDragBrush.SetRect(ptHandle.x, ptHandle.y,
  2211. ptHandle.x + theImgBrush.m_size.cx,
  2212. ptHandle.y + theImgBrush.m_size.cy);
  2213. rcDragBrush -= (CPoint)theImgBrush.m_handle;
  2214. theImgBrush.m_rcSelection = rcDragBrush;
  2215. rcDragBrush.right += 1;
  2216. rcDragBrush.bottom += 1;
  2217. if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  2218. {
  2219. // extern CTextTool g_textTool;
  2220. // g_textTool.Render(CDC::FromHandle(pimg->hDC),
  2221. // rcDragBrush, TRUE, FALSE);
  2222. }
  2223. else
  2224. {
  2225. switch (nCombineMode)
  2226. {
  2227. case combineColor:
  2228. theImgBrush.BltColor(pimg, rcDragBrush.TopLeft(), crLeft);
  2229. break;
  2230. case combineMatte:
  2231. theImgBrush.BltMatte(pimg, rcDragBrush.TopLeft());
  2232. break;
  2233. case combineReplace:
  2234. theImgBrush.BltReplace(pimg, rcDragBrush.TopLeft());
  2235. break;
  2236. }
  2237. }
  2238. InvalImgRect(m_pImg, &rcDragBrush);
  2239. }
  2240. else
  2241. {
  2242. DrawImgLine(m_pImg, ptHandle, ptHandle, crLeft,
  2243. nStrokeWidth, nStrokeShape, FALSE);
  2244. rcDragBrush.left = ptHandle.x - nStrokeWidth / 2;
  2245. rcDragBrush.top = ptHandle.y - nStrokeWidth / 2;
  2246. rcDragBrush.right = rcDragBrush.left + nStrokeWidth;
  2247. rcDragBrush.bottom = rcDragBrush.top + nStrokeWidth;
  2248. }
  2249. if (CImgTool::GetCurrentID() == IDMB_ERASERTOOL)
  2250. {
  2251. crLeft = crRealLeftColor;
  2252. crRight = crRealRightColor;
  2253. }
  2254. g_bBrushVisible = TRUE;
  2255. }
  2256. /***************************************************************************/
  2257. void CImgWnd::CmdSmallBrush()
  2258. {
  2259. if (CImgTool::GetCurrent()->GetStrokeWidth() != 0)
  2260. CImgTool::GetCurrent()->SetStrokeWidth(1);
  2261. }
  2262. /***************************************************************************/
  2263. void CImgWnd::CmdSmallerBrush()
  2264. {
  2265. if (theImgBrush.m_pImg != NULL || g_bCustomBrush)
  2266. {
  2267. CmdHalfBsh();
  2268. return;
  2269. }
  2270. UINT nStrokeWidth = CImgTool::GetCurrent()->GetStrokeWidth();
  2271. if (nStrokeWidth > 1)
  2272. CImgTool::GetCurrent()->SetStrokeWidth(nStrokeWidth - 1);
  2273. }
  2274. /***************************************************************************/
  2275. void CImgWnd::CmdLargerBrush()
  2276. {
  2277. if (theImgBrush.m_pImg != NULL || g_bCustomBrush)
  2278. {
  2279. CmdDoubleBsh();
  2280. return;
  2281. }
  2282. UINT nStrokeWidth = CImgTool::GetCurrent()->GetStrokeWidth();
  2283. CImgTool::GetCurrent()->SetStrokeWidth(nStrokeWidth + 1);
  2284. }
  2285. /***************************************************************************/
  2286. void CImgWnd::CmdOK()
  2287. {
  2288. if (GetCapture() != NULL)
  2289. {
  2290. MessageBeep(0);
  2291. return;
  2292. }
  2293. }
  2294. /***************************************************************************/
  2295. // Draw the tracker for this view (if it's the active one) into pDC.
  2296. // If pDC is NULL, one will be provided. Optimize drawing by limiting
  2297. // it to pPaintRect. If pPaintRect is NULL, draw the whole tracker.
  2298. //
  2299. void CImgWnd::DrawTracker( CDC* pDC, const CRect* pPaintRect )
  2300. {
  2301. BOOL bDrawTrackerRgn = FALSE;
  2302. if (c_pImgWndCur != this
  2303. || theImgBrush.m_bMoveSel
  2304. || theImgBrush.m_bSmearSel
  2305. || theImgBrush.m_bMakingSelection)
  2306. {
  2307. // This is not the active view, or the user is doing something
  2308. // to prevent the tracker from appearing.
  2309. return;
  2310. }
  2311. BOOL bReleaseDC = FALSE;
  2312. CRect clientRect;
  2313. if (pDC == NULL)
  2314. {
  2315. pDC = GetDC();
  2316. if (pDC == NULL)
  2317. {
  2318. theApp.SetGdiEmergency(FALSE);
  2319. return;
  2320. }
  2321. bReleaseDC = TRUE;
  2322. }
  2323. if (pPaintRect == NULL)
  2324. {
  2325. GetClientRect(&clientRect);
  2326. pPaintRect = &clientRect;
  2327. }
  2328. CRect trackerRect;
  2329. GetImageRect( trackerRect );
  2330. trackerRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
  2331. CTracker::EDGES edges = (CTracker::EDGES)(CTracker::right | CTracker::bottom);
  2332. if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
  2333. {
  2334. bDrawTrackerRgn = TRUE;
  2335. }
  2336. if (m_pImg == theImgBrush.m_pImg)
  2337. {
  2338. edges = CTracker::all;
  2339. trackerRect = theImgBrush.m_rcSelection;
  2340. trackerRect.left *= m_nZoom;
  2341. trackerRect.top *= m_nZoom;
  2342. trackerRect.right *= m_nZoom;
  2343. trackerRect.bottom *= m_nZoom;
  2344. trackerRect.InflateRect( CTracker::HANDLE_SIZE,
  2345. CTracker::HANDLE_SIZE);
  2346. trackerRect.OffsetRect( CTracker::HANDLE_SIZE + m_xScroll * m_nZoom,
  2347. CTracker::HANDLE_SIZE + m_yScroll * m_nZoom);
  2348. if (IsGridVisible())
  2349. {
  2350. trackerRect.right += 1;
  2351. trackerRect.bottom += 1;
  2352. }
  2353. }
  2354. CTracker::DrawBorder (pDC, trackerRect, edges );
  2355. CTracker::DrawHandles(pDC, trackerRect, edges );
  2356. if (bReleaseDC)
  2357. ReleaseDC(pDC);
  2358. }
  2359. /***************************************************************************/
  2360. // Erase the tracker from this window. Handles whole image as well
  2361. // as selection trackers.
  2362. //
  2363. void CImgWnd::EraseTracker()
  2364. {
  2365. if (m_pImg == NULL)
  2366. return;
  2367. CClientDC dc(this);
  2368. if (dc.m_hDC == NULL)
  2369. {
  2370. theApp.SetGdiEmergency(FALSE);
  2371. return;
  2372. }
  2373. CRect trackerRect;
  2374. if (m_pImg == theImgBrush.m_pImg)
  2375. {
  2376. // Tracker is a selection within the image
  2377. trackerRect = theImgBrush.m_rcSelection;
  2378. ImageToClient(trackerRect);
  2379. trackerRect.InflateRect(CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE);
  2380. if (IsGridVisible())
  2381. {
  2382. trackerRect.right += 1;
  2383. trackerRect.bottom += 1;
  2384. }
  2385. InvalidateRect( &trackerRect, FALSE );
  2386. }
  2387. else
  2388. {
  2389. // Tracker is around entire image
  2390. GetImageRect(trackerRect);
  2391. trackerRect.InflateRect(CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE);
  2392. DrawBackground(&dc, &trackerRect);
  2393. }
  2394. }
  2395. /***************************************************************************/
  2396. void CImgWnd::CmdTglOpaque()
  2397. {
  2398. HideBrush();
  2399. theImgBrush.m_bOpaque = !theImgBrush.m_bOpaque;
  2400. theImgBrush.RecalcMask( crRight );
  2401. MoveBrush( theImgBrush.m_rcSelection );
  2402. if ((CImgTool::GetCurrentID() == IDMB_PICKTOOL)
  2403. || (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL))
  2404. g_pImgToolWnd->InvalidateOptions( FALSE );
  2405. }
  2406. /***************************************************************************/
  2407. void CImgWnd::CmdInvertColors()
  2408. {
  2409. IMG* pImg = m_pImg;
  2410. HideBrush();
  2411. CRect invertRect;
  2412. if (theImgBrush.m_pImg == NULL && !g_bCustomBrush)
  2413. {
  2414. invertRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight);
  2415. }
  2416. else
  2417. {
  2418. invertRect = rcDragBrush;
  2419. invertRect.right -= 1;
  2420. invertRect.bottom -= 1;
  2421. }
  2422. if (theImgBrush.m_pImg != NULL && ! theImgBrush.m_bFirstDrag || g_bCustomBrush)
  2423. {
  2424. CPalette* ppal = SetImgPalette( &theImgBrush.m_dc, FALSE );
  2425. theImgBrush.m_dc.PatBlt(0, 0, theImgBrush.m_size.cx,
  2426. theImgBrush.m_size.cy, DSTINVERT);
  2427. if (ppal)
  2428. theImgBrush.m_dc.SelectPalette( ppal, FALSE ); // Background ??
  2429. theImgBrush.RecalcMask( crRight );
  2430. MoveBrush( theImgBrush.m_rcSelection );
  2431. }
  2432. else
  2433. {
  2434. SetUndo( m_pImg );
  2435. PatBlt( pImg->hDC, invertRect.left, invertRect.top,
  2436. invertRect.Width(), invertRect.Height(), DSTINVERT );
  2437. InvalImgRect ( m_pImg, &invertRect );
  2438. CommitImgRect( m_pImg, &invertRect );
  2439. FinishUndo( invertRect );
  2440. DirtyImg( m_pImg );
  2441. }
  2442. }
  2443. /***************************************************************************/
  2444. void CImgWnd::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
  2445. {
  2446. CWnd::OnKeyDown( nChar, nRepCnt, nFlags );
  2447. }
  2448. /***************************************************************************/
  2449. void CImgWnd::OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags )
  2450. {
  2451. CWnd::OnKeyUp( nChar, nRepCnt, nFlags );
  2452. }
  2453. /***************************************************************************/