|
|
#include "stdafx.h"
#include "global.h"
#include "pbrush.h"
#include "pbrusdoc.h"
#include "pbrusfrm.h"
#include "pbrusvw.h"
#include "minifwnd.h"
#include "bmobject.h"
#include "imgsuprt.h"
#include "imgwnd.h"
#include "imgbrush.h"
#include "imgwell.h"
#include "imgtools.h"
#include "t_text.h"
#include "toolbox.h"
#include "imgcolor.h"
#include "undo.h"
#include "props.h"
#include "colorsrc.h"
#ifdef _DEBUG
#undef THIS_FILE
static CHAR BASED_CODE THIS_FILE[] = __FILE__; #endif
IMPLEMENT_DYNAMIC(CImgTool, CObject) IMPLEMENT_DYNAMIC(CRubberTool, CImgTool) IMPLEMENT_DYNAMIC(CClosedFormTool, CRubberTool) IMPLEMENT_DYNAMIC(CFreehandTool, CImgTool) IMPLEMENT_DYNAMIC(CSketchTool, CFreehandTool) IMPLEMENT_DYNAMIC(CBrushTool, CFreehandTool) IMPLEMENT_DYNAMIC(CPencilTool, CFreehandTool) IMPLEMENT_DYNAMIC(CEraserTool, CFreehandTool) IMPLEMENT_DYNAMIC(CAirBrushTool, CFreehandTool) IMPLEMENT_DYNAMIC(CLineTool, CRubberTool) IMPLEMENT_DYNAMIC(CRectTool, CClosedFormTool) IMPLEMENT_DYNAMIC(CRoundRectTool, CClosedFormTool) IMPLEMENT_DYNAMIC(CEllipseTool, CClosedFormTool) IMPLEMENT_DYNAMIC(CPickColorTool, CImgTool) IMPLEMENT_DYNAMIC(CFloodTool, CImgTool) IMPLEMENT_DYNAMIC(CSelectTool, CImgTool) IMPLEMENT_DYNAMIC(CZoomTool, CImgTool)
#include "memtrace.h"
extern CRect rcDragBrush;
extern HDC hRubberDC;
BOOL g_bBrushVisible; BOOL g_bPickingColor; UINT g_nStrokeWidth = 1;
/***************************************************************************/ //
// Drawing Tool Classes
//
CRectTool g_rectTool; CRoundRectTool g_roundRectTool; CEllipseTool g_ellipseTool; CLineTool g_lineTool; CSelectTool g_selectTool; CBrushTool g_brushTool; CSketchTool g_sketchTool; CPencilTool g_pencilTool; CEraserTool g_eraserTool; CAirBrushTool g_airBrushTool; CFloodTool g_floodTool; CPickColorTool g_pickColorTool; CZoomTool g_zoomTool;
/***************************************************************************/
CImgTool* CImgTool::c_pHeadImgTool = NULL; CImgTool* CImgTool::c_pCurrentImgTool = &g_pencilTool; CImgTool* CImgTool::c_pPreviousImgTool = &g_pencilTool; BOOL CImgTool::c_bDragging = FALSE; int CImgTool::c_nHideCount = 0;
/***************************************************************************/
CImgTool::CImgTool() { m_bUsesBrush = FALSE; m_bIsUndoable = TRUE; m_bCanBePrevTool = TRUE; m_bToggleWithPrev = FALSE; m_bFilled = FALSE; m_bBorder = TRUE; m_bMultPtOpInProgress = FALSE; m_eDrawDirection = eFREEHAND;
m_nStrokeWidth = 0; m_nStrokeShape = roundBrush;
m_nCursorID = LOWORD(IDC_CROSSHAIR); m_nCmdID = NULL;
// Link into the list of tools...
m_pNextImgTool = c_pHeadImgTool; c_pHeadImgTool = this; }
/******************************************************************************/
eDRAWCONSTRAINTDIRECTION CImgTool::DetermineDrawDirection(MTI *pmti) { eDRAWCONSTRAINTDIRECTION eDrawDirection;
// 45 is dominant, test first
if ( (pmti->pt.x > pmti->ptPrev.x) && (pmti->pt.y > pmti->ptPrev.y) ) { eDrawDirection = eSOUTH_EAST; } else { if ( (pmti->pt.x > pmti->ptPrev.x) && (pmti->pt.y < pmti->ptPrev.y) ) { eDrawDirection = eNORTH_EAST; } else { if ( (pmti->pt.x < pmti->ptPrev.x) && (pmti->pt.y > pmti->ptPrev.y) ) { eDrawDirection = eSOUTH_WEST; } else { if ( (pmti->pt.x < pmti->ptPrev.x) && (pmti->pt.y < pmti->ptPrev.y) ) { eDrawDirection = eNORTH_WEST; } else { // Horizontal is the next dominant, test before vertical
if (pmti->ptPrev.x != pmti->pt.x) { eDrawDirection = eEAST_WEST; pmti->pt.y = pmti->ptPrev.y; } else { if (pmti->ptPrev.y != pmti->pt.y) { eDrawDirection = eNORTH_SOUTH; pmti->pt.x = pmti->ptPrev.x; } else { // we should never fall into here, but in any case...
eDrawDirection = eFREEHAND; } } } } } } return eDrawDirection; }
/******************************************************************************/
void CImgTool::AdjustPointsForConstraint(MTI *pmti) { }
/******************************************************************************/
void CImgTool::PreProcessPoints(MTI *pmti) { if (pmti != NULL) { if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) //still in constrain mode
{ switch (m_eDrawDirection) { case eEAST_WEST: case eNORTH_SOUTH: case eNORTH_WEST: case eSOUTH_EAST: case eNORTH_EAST: case eSOUTH_WEST: AdjustPointsForConstraint(pmti); break; default: // not in constraint mode yet If shift down, check for
// mode and save mode else nothing. Default is freehand
m_eDrawDirection = DetermineDrawDirection(pmti); AdjustPointsForConstraint(pmti); break; } } else { // shift not down
m_eDrawDirection = eFREEHAND; } } }
/***************************************************************************/
void CImgTool::HideDragger(CImgWnd* pImgWnd) { ASSERT(c_pCurrentImgTool != NULL);
if (c_nHideCount == 0) c_pCurrentImgTool->OnShowDragger(pImgWnd, FALSE); c_nHideCount++; }
/***************************************************************************/
void CImgTool::ShowDragger(CImgWnd* pImgWnd) { ASSERT(c_pCurrentImgTool != NULL);
if (--c_nHideCount == 0) c_pCurrentImgTool->OnShowDragger(pImgWnd, TRUE); }
/***************************************************************************/
void CImgTool::Select(UINT nCmdID) { CImgTool* p = FromID(nCmdID); if (p) { p->Select(); } }
/***************************************************************************/
void CImgTool::Select() { ASSERT(this != NULL);
if (this == c_pCurrentImgTool && m_bToggleWithPrev) { SelectPrevious(); return; }
if (g_bCustomBrush) { g_bCustomBrush = FALSE; SetCombineMode(combineColor); }
HideBrush();
if (c_pCurrentImgTool->m_bCanBePrevTool && c_pCurrentImgTool != this) c_pPreviousImgTool = c_pCurrentImgTool;
// Make sure to Deactivate the old one BEFORE activating the new one, so
// globals (like g_nStrokeWidth) get set correctly
if (c_pCurrentImgTool != NULL) c_pCurrentImgTool->OnActivate(FALSE);
c_pCurrentImgTool = this;
OnActivate(TRUE);
if (c_pCurrentImgTool != this) { // Some tools may give up activation...
ASSERT(!m_bCanBePrevTool); return; }
SetCombineMode(combineColor);
if (g_pImgToolWnd) { g_pImgToolWnd->SelectTool( (WORD)m_nCmdID );
if (g_pImgToolWnd->m_hWnd) g_pImgToolWnd->InvalidateOptions(); }
CImgWnd::SetToolCursor(); }
/***************************************************************************/
CImgTool* CImgTool::FromID(UINT nCmdID) { CImgTool* pImgTool = c_pHeadImgTool; while (pImgTool != NULL && pImgTool->m_nCmdID != nCmdID) pImgTool = pImgTool->m_pNextImgTool; return pImgTool; }
/***************************************************************************/
void CImgTool::SetStrokeWidth(UINT nNewStrokeWidth) { if (nNewStrokeWidth == m_nStrokeWidth) return;
HideBrush(); g_bCustomBrush = FALSE; m_nStrokeWidth = nNewStrokeWidth; g_pImgToolWnd->InvalidateOptions();
extern MTI mti;
if (mti.fLeft || mti.fRight) OnDrag(CImgWnd::GetCurrent(), &mti); }
/***************************************************************************/
void CImgTool::SetStrokeShape(UINT nNewStrokeShape) { if (m_nStrokeShape == nNewStrokeShape) return;
HideBrush(); g_bCustomBrush = FALSE; m_nStrokeShape = nNewStrokeShape; g_pImgToolWnd->InvalidateOptions(FALSE); }
/***************************************************************************/
void CImgTool::OnActivate(BOOL bActivate) { if (bActivate) OnShowDragger(CImgWnd::GetCurrent(), TRUE); }
/***************************************************************************/
void CImgTool::OnEnter(CImgWnd* pImgWnd, MTI* pmti) { // No default action
}
/***************************************************************************/
void CImgTool::OnLeave(CImgWnd* pImgWnd, MTI* pmti) { // No default action
}
/***************************************************************************/
void CImgTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShowDragger) { // No default action
}
/***************************************************************************/
void CImgTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { c_bDragging = TRUE; }
/***************************************************************************/
void CImgTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { c_bDragging = FALSE;
if (m_bIsUndoable) DirtyImg(pImgWnd->m_pImg); }
/***************************************************************************/
void CImgTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { ASSERT(c_bDragging); }
/***************************************************************************/
void CImgTool::OnMove(CImgWnd* pImgWnd, MTI* pmti) { // ASSERT(!c_bDragging);
if (UsesBrush()) { fDraggingBrush = TRUE; pImgWnd->ShowBrush(pmti->pt); }
SetStatusBarPosition(pmti->pt); }
/***************************************************************************/
void CImgTool::OnTimer(CImgWnd* pImgWnd, MTI* pmti) { // Tools should not have started a timer unless it overrides this!
ASSERT(FALSE); }
/***************************************************************************/
void CImgTool::OnCancel(CImgWnd* pImgWnd) { c_bDragging = FALSE; }
/***************************************************************************/
void CImgTool::OnPaintOptions(CDC* pDC, const CRect& paintRect, const CRect& optionsRect) { }
/***************************************************************************/
void CImgTool::PaintStdPattern(CDC* pDC, const CRect& paintRect, const CRect& optionsRect) { CBrush brush; CPalette *pcPaletteOld = NULL; CPalette *pcPaletteOld2 = NULL;
CDC dc; if (!dc.CreateCompatibleDC(pDC)) return;
CBitmap bitmap, * pOldBitmap; if (!bitmap.CreateCompatibleBitmap(pDC, 8, 8)) return;
pOldBitmap = dc.SelectObject(&bitmap);
if (theApp.m_pPalette) { pcPaletteOld = pDC->SelectPalette( theApp.m_pPalette, FALSE ); pDC->RealizePalette();
pcPaletteOld2 = dc.SelectPalette( theApp.m_pPalette, FALSE ); dc.RealizePalette(); }
CBrush* pOldBrush = NULL;
COLORREF rgb = crLeft;
if (pImgCur->m_pBitmapObj->m_nColors == 0) { BOOL MonoRect(CDC* pDC, const CRect& rect, COLORREF rgb, BOOL bFrame); MonoRect(&dc, CRect(0, 0, 9, 9), rgb, FALSE); } else { brush.CreateSolidBrush(rgb); pOldBrush = dc.SelectObject(&brush); dc.PatBlt(0, 0, 8, 8, PATCOPY); dc.SelectObject(pOldBrush); brush.DeleteObject(); }
// Draw a black grid...
for (int i = 0; i < 9; i++) { pDC->PatBlt(optionsRect.left + 2 + i * 7, optionsRect.top + 3, 1, 8 * 7 + 1, BLACKNESS); pDC->PatBlt(optionsRect.left + 2, optionsRect.top + 3 + i * 7, 8 * 7 + 1, 1, BLACKNESS); }
// Fill in the boxes...
COLORREF curColor = (COLORREF)0xffffffff;
for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { COLORREF color = dc.GetPixel(x, y) | 0x02000000L;
if (color != curColor) { if (pOldBrush != NULL) pDC->SelectObject(pOldBrush);
brush.DeleteObject(); brush.CreateSolidBrush(color);
pOldBrush = pDC->SelectObject(&brush); curColor = color; }
pDC->PatBlt(optionsRect.left + 2 + 1 + x * 7, optionsRect.top + 3 + 1 + y * 7, 6, 6, PATCOPY); } }
ASSERT(pOldBrush != NULL); pDC->SelectObject(pOldBrush);
dc.SelectObject(pOldBitmap);
if (pcPaletteOld) pDC->SelectPalette(pcPaletteOld, FALSE);
if (pcPaletteOld2) dc.SelectPalette(pcPaletteOld2, FALSE); }
/***************************************************************************/
void CImgTool::ClickStdPattern(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { CImgTool::OnClickOptions(pWnd, optionsRect, clickPoint); }
/***************************************************************************/
void CImgTool::PaintStdBrushes(CDC* pDC, const CRect& paintRect, const CRect& optionsRect) { int cxBrush = optionsRect.Width() / 3; int cyBrush = optionsRect.Height() / 4;
for (UINT nBrushShape = 0; nBrushShape < 4; nBrushShape++) { int x = 0; for (UINT nStrokeWidth = 8 - (nBrushShape == 0); (int)nStrokeWidth > 0; nStrokeWidth -= 3, x += cxBrush) { CRect rect; rect.left = optionsRect.left + x; rect.top = optionsRect.top + cyBrush * nBrushShape; rect.right = rect.left + cxBrush; rect.bottom = rect.top + cyBrush; rect.InflateRect(-3, -3);
if ((paintRect & rect).IsRectEmpty()) continue;
BOOL bCur = (nStrokeWidth == m_nStrokeWidth && nBrushShape == m_nStrokeShape);
CBrush* pOldBrush = pDC->SelectObject(GetSysBrush(bCur ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); if ((nStrokeWidth & 1) != 0) { // Adjust hilight rect so brush will be centered
rect.right -= 1; rect.bottom -= 1; } pDC->PatBlt(rect.left + 1, rect.top - 1, rect.Width() - 2, rect.Height() + 2, PATCOPY); pDC->SelectObject(pOldBrush);
CPoint pt(optionsRect.left + (cxBrush - nStrokeWidth) / 2 + x, optionsRect.top + (cyBrush - nStrokeWidth) / 2 + nBrushShape * cyBrush);
pOldBrush = pDC->SelectObject(GetSysBrush(bCur ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); BrushLine(pDC, pt, pt, nStrokeWidth, nBrushShape); pDC->SelectObject(pOldBrush); } } }
/***************************************************************************/
void CImgTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { MessageBeep(0); }
/******************************************************************************/
void CImgTool::OnUpdateColors (CImgWnd* pImgWnd) { }
/******************************************************************************/
BOOL CImgTool::CanEndMultiptOperation(MTI* pmti ) { return (! m_bMultPtOpInProgress); // if not in progress (FALSE) => can end (TRUE)
}
/******************************************************************************/
void CImgTool::EndMultiptOperation(BOOL bAbort) { m_bMultPtOpInProgress = FALSE; }
/******************************************************************************/
BOOL CImgTool::IsToolModal(void) { return(IsDragging() || m_bMultPtOpInProgress || m_bToggleWithPrev); }
/******************************************************************************/
BOOL CImgTool::IsUndoable() { if (m_bMultPtOpInProgress) { return FALSE; // cannot undo in the middle of a multi-point operation.
} else { return m_bIsUndoable; } }
/******************************************************************************/
void CImgTool::ClickStdBrushes(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { HideBrush();
g_bCustomBrush = FALSE; m_nStrokeWidth = 2 + 3 * (2 - (clickPoint.x / (optionsRect.Width() / 3))); m_nStrokeShape = clickPoint.y / (optionsRect.Height() / 4);
if (m_nStrokeShape == 0) m_nStrokeWidth -= 1;
pWnd->InvalidateOptions(FALSE); }
/******************************************************************************/
UINT CImgTool::GetCursorID() { return m_nCursorID; }
/******************************************************************************/
CRect CRubberTool::rcPrev; // UINT CRubberTool::m_nStrokeWidth;
CRubberTool::CRubberTool() { }
/******************************************************************************/
void CRubberTool::OnPaintOptions(CDC* pDC, const CRect& paintRect, const CRect& optionsRect) { if (m_bFilled) { PaintStdPattern(pDC, paintRect, optionsRect); return; }
#define nLineWidths 5
int cyEach = (optionsRect.Height() - 4) / nLineWidths;
for (int i = 0; i < nLineWidths; i++) { UINT cyHeight = i + 1;
CBrush* pOldBrush; BOOL bCur = (cyHeight == GetStrokeWidth());
pOldBrush = pDC->SelectObject( GetSysBrush(bCur ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); pDC->PatBlt(optionsRect.left + 2, optionsRect.top + 3 + i * cyEach, optionsRect.Width() - 4, cyEach - 2, PATCOPY); pDC->SelectObject(pOldBrush);
pOldBrush = pDC->SelectObject(GetSysBrush(bCur ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->PatBlt(optionsRect.left + 6, optionsRect.top + 2 + cyEach * i + (cyEach - cyHeight) / 2, optionsRect.Width() - 12, cyHeight, PATCOPY);
pDC->SelectObject(pOldBrush); } }
/******************************************************************************/
void CRubberTool::OnClickOptions( CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint ) { if (m_bFilled) { CImgTool::OnClickOptions( pWnd, optionsRect, clickPoint ); return; }
m_nStrokeWidth = 1 + clickPoint.y / ((optionsRect.Height() - 4) / nLineWidths);
// fix for rounding errors
if (m_nStrokeWidth > nLineWidths) { m_nStrokeWidth = nLineWidths; }
pWnd->InvalidateOptions(FALSE); }
/******************************************************************************/
void CClosedFormTool::OnPaintOptions( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) {
// Option 0 is Outlined Shape (border and no fill)
// Option 1 is Filled Shape with border
// Option 2 is Filled Shape NO border
#define NUM_CLOSED_FORM_OPTIONS 3 //number of options high
//*DK* Select Palette into DC
CBrush* pOldBrush; CRect cRectOptionSel; // selection rectangle
CRect cRectOption; //rectangle
int cyEach = (optionsRect.Height() - 4) / NUM_CLOSED_FORM_OPTIONS; // max height of each option
int cyHeight = cyEach - cyEach/2; //rectangle is 1/2 max height
int bCurrSelected = FALSE; BOOL bFilled = CImgTool::GetCurrent()->IsFilled(); BOOL bBorder = CImgTool::GetCurrent()->HasBorder(); int i;
for (i = 0; i < NUM_CLOSED_FORM_OPTIONS; i++) { // Setup the Rectangles for painting and for selection
//Selection Rectangle
cRectOptionSel.SetRect(optionsRect.left + 2, optionsRect.top + 3 + (i * cyEach), (optionsRect.left + 2) + optionsRect.Width() - 4, (optionsRect.top + 3 + (i* cyEach)) + cyEach - 2);
//Option Rectangle
cRectOption.SetRect(optionsRect.left + 6, optionsRect.top + 2 + i * cyEach + (cyEach - cyHeight) / 2, (optionsRect.left + 6) + optionsRect.Width() - 12, (optionsRect.top + 2 + i * cyEach + (cyEach - cyHeight) / 2) + cyHeight);
// Determine the Selection state for the current item.
bCurrSelected = FALSE;
switch (i) { case 0: //Outlined Shape (border, no fill)
if (! bFilled && bBorder) { bCurrSelected = TRUE; } break;
case 1: // Filled Shape (border and fill)
if ( (bFilled) && (bBorder) ) { bCurrSelected = TRUE; } break; case 2: // Filled Shape No Border (no border, fill)
if (bFilled && ! bBorder) { bCurrSelected = TRUE; } break; default: bCurrSelected = FALSE; break; } // Draw the selection State
// If selected, use COLOR_HIGHLIGHT else use CMP_COLOR_LTGRAY
pOldBrush = pDC->SelectObject( GetSysBrush( bCurrSelected ? COLOR_HIGHLIGHT : COLOR_BTNFACE ) ); pDC->PatBlt( cRectOptionSel.left, cRectOptionSel.top, cRectOptionSel.Width(),cRectOptionSel.Height(), PATCOPY ); pDC->SelectObject(pOldBrush);
CBrush* pborderBrush; CBrush* pfillBrush;
pborderBrush = GetSysBrush(bCurrSelected ? COLOR_BTNHIGHLIGHT : COLOR_BTNTEXT); pfillBrush = GetSysBrush(COLOR_BTNSHADOW);
// Draw the Option
switch (i) { case 0: //Outlined Shape (no border, no fill)
pDC->FrameRect(&cRectOption, pborderBrush); break;
case 1: // Filled Shape (border and fill)
// using fillrect then frame rect instead of rectangle, since
// don't have getsyspen facility in this program.
pDC->FillRect(&cRectOption, pfillBrush); pDC->FrameRect(&cRectOption, pborderBrush); break;
case 2: // Filled Shape No Border (no border, fill)
pDC->FillRect(&cRectOption, pfillBrush); break;
default: break; } } }
/******************************************************************************/ // clickpoint is from top of optionsrect (i.e. clickpoint if from 0 to optionsrect.height()
// and thus clickpoint is always less than optionsrec.top
void CClosedFormTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { int cyEach = (optionsRect.Height() - 4) / NUM_CLOSED_FORM_OPTIONS; // max height of each option
// BOOL bCurrSelected = FALSE;
int i;
for (i = 0; i < NUM_CLOSED_FORM_OPTIONS; i++) { if ( clickPoint.y < 3 + ((i+1) * cyEach) ) { // bCurrSelected = TRUE;
switch (i) { default: // default is same as initial
case 0: //Outlined Shape (border, no fill)
m_bFilled = FALSE; m_bBorder = TRUE; break;
case 1: // Filled Shape (border and fill)
m_bFilled = TRUE; m_bBorder = TRUE; break;
case 2: // Filled Shape No Border (no border, fill)
m_bFilled = TRUE; m_bBorder = FALSE; break; }
break; // point found, break out of loop test
} }
pWnd->InvalidateOptions(FALSE); }
/******************************************************************************/
void CRubberTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { CImgTool::OnStartDrag(pImgWnd, pmti);
SetupRubber(pImgWnd->m_pImg); OnDrag(pImgWnd, pmti); }
/******************************************************************************/
void CRubberTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { OnDrag(pImgWnd, pmti);
CRect rc(pmti->ptDown.x, pmti->ptDown.y, pmti->pt.x, pmti->pt.y);
Render(CDC::FromHandle(pImgWnd->m_pImg->hDC), rc, pmti->fLeft, TRUE, pmti->fCtrlDown); InvalImgRect(pImgWnd->m_pImg, &rc); CommitImgRect(pImgWnd->m_pImg, &rc); pImgWnd->FinishUndo(rc);
ClearStatusBarSize();
CImgTool::OnEndDrag(pImgWnd, pmti); }
/******************************************************************************/
void CRubberTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { HPALETTE hpalOld = NULL;
if (theApp.m_pPalette && theApp.m_pPalette->m_hObject) { hpalOld = SelectPalette( hRubberDC, (HPALETTE)theApp.m_pPalette->m_hObject, FALSE ); // Background ??
RealizePalette( hRubberDC ); }
BitBlt(pImgWnd->m_pImg->hDC, rcPrev.left , rcPrev.top, rcPrev.Width(), rcPrev.Height(), hRubberDC, rcPrev.left , rcPrev.top, SRCCOPY);
if (hpalOld != NULL) SelectPalette( hRubberDC, hpalOld, FALSE ); // Background ??
InvalImgRect(pImgWnd->m_pImg, &rcPrev);
PreProcessPoints(pmti);
CRect rc(pmti->ptDown.x, pmti->ptDown.y, pmti->pt.x, pmti->pt.y);
Render(CDC::FromHandle(pImgWnd->m_pImg->hDC), rc, pmti->fLeft, FALSE, pmti->fCtrlDown); InvalImgRect(pImgWnd->m_pImg, &rc); rcPrev = rc;
if (m_nCmdID != IDMB_POLYGONTOOL) { CSize size( pmti->pt - pmti->ptDown );
if (size.cx < 0) size.cx -= 1; else size.cx += 1; if (size.cy < 0) size.cy -= 1; else size.cy += 1;
SetStatusBarPosition( pmti->ptDown ); SetStatusBarSize ( size ); } }
/******************************************************************************/
void CRubberTool::AdjustPointsForConstraint(MTI *pmti) { if (pmti != NULL) { int iWidthHeight = min( abs(pmti->ptDown.x - pmti->pt.x), abs(pmti->ptDown.y - pmti->pt.y)); // Set the x value
if (pmti->pt.x < pmti->ptDown.x) { pmti->pt.x = pmti->ptDown.x - iWidthHeight; } else { pmti->pt.x = pmti->ptDown.x + iWidthHeight; }
// Set the y value
if (pmti->pt.y < pmti->ptDown.y) { pmti->pt.y = pmti->ptDown.y - iWidthHeight; } else { pmti->pt.y = pmti->ptDown.y + iWidthHeight; }
} }
/******************************************************************************/
void CRubberTool::Render( CDC* pDC, CRect& rect, BOOL bLeft, BOOL bCommit, BOOL bCtrlDown ) { int sx; int sy; int ex; int ey; HBRUSH hBr = NULL; HPEN hPen = NULL; HPEN hOldPen = NULL; HBRUSH hOldBr = NULL; CPoint pt1; CPoint pt2; HDC hDC = pDC->m_hDC;
enum SHAPE { rectangle, roundRect, ellipse } shape;
switch (m_nCmdID) { default: ASSERT(FALSE);
case IDMB_RECTTOOL: shape = rectangle; break;
case IDMB_FRECTTOOL: shape = rectangle; break;
case IDMB_RNDRECTTOOL: shape = roundRect; break;
case IDMB_FRNDRECTTOOL: shape = roundRect; break;
case IDMB_ELLIPSETOOL: shape = ellipse; break;
case IDMB_FELLIPSETOOL: shape = ellipse; break; }
FixRect(&rect);
pt1.x = rect.left; pt1.y = rect.top; pt2.x = rect.right; pt2.y = rect.bottom;
StandardiseCoords(&pt1, &pt2);
sx = pt1.x; sy = pt1.y; ex = pt2.x; ey = pt2.y;
SetupPenBrush(hDC, bLeft, TRUE, bCtrlDown);
CRect rc(sx, sy, ex, ey);
switch (shape) { case rectangle: Rectangle(hDC, sx, sy, ex, ey); break;
case roundRect: RoundRect(hDC, sx, sy, ex, ey, 16, 16); // The below draws an RoundRect with a mask first then bitblt
// MyRoundRect(hDC, sx, sy, ex, ey, 16, 16, m_bFilled);
// // if border and fill, draw border after fill
// if ( (m_bBorder) && (m_bFilled) )
// {
// MyRoundRect(hDC, sx, sy, ex, ey, 16, 16, !m_bFilled);
// }
break;
case ellipse: Ellipse(hDC, sx, sy, ex, ey); // The below draws an Elipse with a mask first then bitblt
// Mylipse(hDC, sx, sy, ex, ey, m_bFilled);
// // if border and fill, draw border after fill
// if ( (m_bBorder) && (m_bFilled) )
// {
// Mylipse(hDC, sx, sy, ex, ey, !m_bFilled);
// }
break; }
SetupPenBrush(hDC, bLeft, FALSE, bCtrlDown); }
void CRubberTool::OnActivate( BOOL bActivate ) { if (bActivate) { m_nStrokeWidth = g_nStrokeWidth; } else { g_nStrokeWidth = m_nStrokeWidth; }
CImgTool::OnActivate( bActivate ); }
/******************************************************************************/ /*bSetup is true to setup, False to Cleanup */
BOOL CImgTool::SetupPenBrush(HDC hDC, BOOL bLeft, BOOL bSetup, BOOL bCtrlDown) {
COLORREF colorBorder; COLORREF colorFill;
if (bCtrlDown && crTrans != TRANS_COLOR_NONE) { if (HasBorder ()) { colorBorder = bLeft ? crTrans : crRight; colorFill = bLeft ? crRight : crTrans; } else { colorBorder = bLeft ? crRight : crTrans; colorFill = bLeft ? crTrans : crRight; }
} else { if (HasBorder()) { colorBorder = bLeft ? crLeft : crRight; colorFill = bLeft ? crRight: crLeft; } else { colorBorder = bLeft ? crRight : crLeft; colorFill = bLeft ? crLeft: crRight; }
}
static HBRUSH hBr = NULL; static HPEN hPen = NULL; static HPEN hOldPen = NULL; static HBRUSH hOldBr = NULL; static BOOL bCurrentlySetup = FALSE; BOOL bRC = TRUE;
if (bSetup) { if (! bCurrentlySetup) { bCurrentlySetup = TRUE; // select null objects into DC. Depending on drawing mode,
// either or both will be re-selected in to override
hPen = NULL; hBr = NULL; hOldPen = (HPEN)SelectObject( hDC, GetStockObject( NULL_PEN ) ); hOldBr = (HBRUSH)SelectObject( hDC, GetStockObject( NULL_BRUSH ) );
if (m_bFilled) { hBr = CreateSolidBrush( colorFill ); SelectObject( hDC, hBr ); }
if (m_bBorder) { hPen = CreatePen( PS_INSIDEFRAME, m_nStrokeWidth, colorBorder ); SelectObject(hDC, hPen); } else { //simulate no border by drawing the border the same as the fill.
// since GDI does not draw small elipses, roundrects correctly
// with NULL brush for no border.
// Note the width is 2 so we will dither correctly
hPen = CreatePen(PS_INSIDEFRAME, 2, colorFill); SelectObject(hDC, hPen); } } else { // Error: Will lose allocated Brush/Pen
bRC = FALSE; } } else { if (bCurrentlySetup) { bCurrentlySetup = FALSE;
SelectObject(hDC, hOldPen);
if (hPen != NULL) { DeleteObject(hPen); }
SelectObject(hDC, hOldBr);
if (hBr != NULL) { DeleteObject( hBr ); } } else { // Error: Cannot Free/cleanup Brush/Pen -- Never allocated.
bRC = FALSE; } }
return bRC; }
#if 0 // unused code
/******************************************************************************/ /*bSetup is true to setup, False to Cleanup */
BOOL CRubberTool::SetupMaskPenBrush(HDC hDC, BOOL bLeft, BOOL bSetup) { BOOL bRC = TRUE;
static HBRUSH hBr = NULL; static HPEN hPen = NULL; static HPEN hOldPen = NULL; static HBRUSH hOldBr = NULL; static BOOL bCurrentlySetup = FALSE;
if (bSetup) { if (bCurrentlySetup) { // Error: Will lose allocated Brush/Pen
bRC = FALSE; } else { bCurrentlySetup = TRUE; // draw the shape on the mask:
// select null objects into DC. Depending on drawing mode,
// either or both will be re-selected in to override
hPen = NULL; hBr = NULL; hOldPen = (HPEN)SelectObject(hDC, GetStockObject(NULL_PEN)); hOldBr = (HBRUSH)SelectObject(hDC, GetStockObject(NULL_BRUSH));
if (m_bFilled) { SelectObject(hDC, GetStockObject( BLACK_BRUSH )); } if (m_bBorder) { hPen = CreatePen(PS_INSIDEFRAME, m_nStrokeWidth, (COLORREF)0L ); SelectObject(hDC, hPen); } } } else { if (bCurrentlySetup) { bCurrentlySetup = FALSE;
SelectObject(hDC, hOldPen); if (hPen != NULL) { DeleteObject(hPen); }
SelectObject(hDC, hOldBr); if (hBr != NULL) { DeleteObject(hBr); } } else { // Error: Cannot Free/cleanup Brush/Pen -- Never allocated.
bRC = FALSE; } }
return bRC; } #endif // unused code
/******************************************************************************/
CRect CFreehandTool::c_undoRect;
/***************************************************************************/
CFreehandTool::CFreehandTool() { m_bUsesBrush = TRUE; }
/******************************************************************************/
void CFreehandTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { CImgTool::OnStartDrag(pImgWnd, pmti);
c_undoRect.TopLeft() = c_undoRect.BottomRight() = pmti->pt; OnDrag(pImgWnd, pmti); }
/******************************************************************************/
void CFreehandTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { if (g_bCustomBrush) { c_undoRect.left -= theImgBrush.m_size.cx + theImgBrush.m_handle.cx; c_undoRect.top -= theImgBrush.m_size.cy + theImgBrush.m_handle.cy; c_undoRect.right += theImgBrush.m_size.cx - theImgBrush.m_handle.cx; c_undoRect.bottom += theImgBrush.m_size.cy - theImgBrush.m_handle.cy; } else { // HACK: +1s are to cover bug in slanted line brushes
c_undoRect.left -= m_nStrokeWidth / 2 + 1; c_undoRect.top -= m_nStrokeWidth / 2 + 1; c_undoRect.right += (m_nStrokeWidth + 1) / 2 + 1; c_undoRect.bottom += (m_nStrokeWidth + 1) / 2 + 1; }
pImgWnd->FinishUndo(c_undoRect);
CImgTool::OnEndDrag(pImgWnd, pmti); }
/******************************************************************************/
CSketchTool::CSketchTool() { m_nCursorID = IDC_BRUSH; m_nCmdID = IDMZ_BRUSHTOOL; m_bCanBePrevTool = FALSE; }
/******************************************************************************/
void CSketchTool::OnDrag( CImgWnd* pImgWnd, MTI* pmti ) { fDraggingBrush = FALSE;
DrawBrush( pImgWnd->m_pImg, pmti->pt, pmti->fLeft );
if (pmti->pt.x < c_undoRect.left) c_undoRect.left = pmti->pt.x; else if (pmti->pt.x > c_undoRect.right) c_undoRect.right = pmti->pt.x;
if (pmti->pt.y < c_undoRect.top) c_undoRect.top = pmti->pt.y; else if (pmti->pt.y > c_undoRect.bottom) c_undoRect.bottom = pmti->pt.y;
SetStatusBarPosition( pmti->pt ); }
/******************************************************************************/
void CSketchTool::OnCancel(CImgWnd* pImgWnd) { HideBrush(); g_bCustomBrush = FALSE; SelectPrevious(); CImgTool::OnCancel( pImgWnd ); }
/******************************************************************************/
CBrushTool::CBrushTool() { m_nCursorID = IDC_BRUSH; m_nCmdID = IDMB_CBRUSHTOOL; m_nStrokeWidth = 4; }
/***************************************************************************/
void CBrushTool::OnPaintOptions( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) { PaintStdBrushes(pDC, paintRect, optionsRect); }
/***************************************************************************/
void CBrushTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { ClickStdBrushes(pWnd, optionsRect, clickPoint); }
/***************************************************************************/
void CBrushTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { g_bCustomBrush = FALSE;
CPoint pt1, pt2;
fDraggingBrush = FALSE;
pt1 = pmti->ptPrev; pt2 = pmti->pt;
// use transparent color if defined
if (pmti->fCtrlDown && crTrans != TRANS_COLOR_NONE) { DrawImgLine( pImgWnd->m_pImg, pt1, pt2, crTrans, m_nStrokeWidth, m_nStrokeShape, TRUE); } else { DrawImgLine( pImgWnd->m_pImg, pt1, pt2, pmti->fLeft ? crLeft : crRight, m_nStrokeWidth, m_nStrokeShape, TRUE);
}
if (pmti->pt.x < c_undoRect.left) c_undoRect.left = pmti->pt.x; else if (pmti->pt.x > c_undoRect.right) c_undoRect.right = pmti->pt.x; if (pmti->pt.y < c_undoRect.top) c_undoRect.top = pmti->pt.y; else if (pmti->pt.y > c_undoRect.bottom) c_undoRect.bottom = pmti->pt.y;
SetStatusBarPosition(pmti->pt); }
/***************************************************************************/
void CBrushTool::OnMove(CImgWnd* pImgWnd, MTI* pmti) { g_bCustomBrush = FALSE; CImgTool::OnMove(pImgWnd, pmti); }
/***************************************************************************/
CPencilTool::CPencilTool() { m_nCursorID = IDC_PENCIL; m_nCmdID = IDMB_PENCILTOOL; m_bUsesBrush = FALSE; m_nStrokeWidth = 1; }
/***************************************************************************/
void CPencilTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { CFreehandTool::OnStartDrag(pImgWnd, pmti); m_eDrawDirection = eFREEHAND; // initialize to not have a direction
}
/***************************************************************************/
void CPencilTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { g_bCustomBrush = FALSE; fDraggingBrush = FALSE;
PreProcessPoints(pmti);
// use transparent color if defined
if (pmti->fCtrlDown && crTrans != TRANS_COLOR_NONE) { DrawImgLine (pImgWnd->m_pImg, pmti->ptPrev, pmti->pt, crTrans, m_nStrokeWidth, m_nStrokeShape, TRUE); } else { DrawImgLine(pImgWnd->m_pImg, pmti->ptPrev, pmti->pt, pmti->fLeft ? crLeft : crRight, m_nStrokeWidth, m_nStrokeShape, TRUE); }
if (pmti->pt.x < c_undoRect.left) c_undoRect.left = pmti->pt.x; else if (pmti->pt.x > c_undoRect.right) c_undoRect.right = pmti->pt.x; if (pmti->pt.y < c_undoRect.top) c_undoRect.top = pmti->pt.y; else if (pmti->pt.y > c_undoRect.bottom) c_undoRect.bottom = pmti->pt.y;
SetStatusBarPosition(pmti->pt); }
/***************************************************************************/
void CPencilTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { c_undoRect.right += 1; c_undoRect.bottom += 1; pImgWnd->FinishUndo(c_undoRect);
CImgTool::OnEndDrag(pImgWnd, pmti); // Bypass CFreehandTool
}
/******************************************************************************/
void CPencilTool::AdjustPointsForConstraint(MTI *pmti) { eDRAWCONSTRAINTDIRECTION eDrawDirection = DetermineDrawDirection(pmti); int iWidthHeight = min( abs(pmti->ptPrev.x - pmti->pt.x), abs(pmti->ptPrev.y - pmti->pt.y));
switch (m_eDrawDirection) { case eEAST_WEST: pmti->pt.y = pmti->ptPrev.y; break; case eNORTH_SOUTH: pmti->pt.x = pmti->ptPrev.x; break;
case eNORTH_WEST: case eSOUTH_EAST: // Set the SE movement
if ( (pmti->pt.x > pmti->ptPrev.x) || (pmti->pt.y > pmti->ptPrev.y) ) { pmti->pt.x = pmti->ptPrev.x + iWidthHeight; pmti->pt.y = pmti->ptPrev.y + iWidthHeight; } else { // Set the NW movement
if ( (pmti->pt.x < pmti->ptPrev.x) || (pmti->pt.y < pmti->ptPrev.y) ) { pmti->pt.x = pmti->ptPrev.x - iWidthHeight; pmti->pt.y = pmti->ptPrev.y - iWidthHeight; } else { //invalid movement, set to last known position
pmti->pt.x = pmti->ptPrev.x; pmti->pt.y = pmti->ptPrev.y; } } break;
case eNORTH_EAST: case eSOUTH_WEST: // Set the NE movement
if ( (pmti->pt.x > pmti->ptPrev.x) || (pmti->pt.y < pmti->ptPrev.y) ) { pmti->pt.x = pmti->ptPrev.x + iWidthHeight; pmti->pt.y = pmti->ptPrev.y - iWidthHeight; } else { // Set the SW movement
if ( (pmti->pt.x < pmti->ptPrev.x) || (pmti->pt.y > pmti->ptPrev.y) ) { pmti->pt.x = pmti->ptPrev.x - iWidthHeight; pmti->pt.y = pmti->ptPrev.y + iWidthHeight; } else { //invalid movement, set to last known position
pmti->pt.x = pmti->ptPrev.x; pmti->pt.y = pmti->ptPrev.y; } } break;
default: // not in constraint mode yet => do nothing.
// Default is freehand
break; } }
/***************************************************************************/
CEraserTool::CEraserTool() { m_nCmdID = IDMB_ERASERTOOL; m_nStrokeWidth = 8; m_nStrokeShape = squareBrush; m_nCursorID = NULL; }
/***************************************************************************/
void CEraserTool::OnPaintOptions( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) { CRect rect; int cxOctant = (optionsRect.Width() + 1); int cyOctant = (optionsRect.Height() + 1) / 4;
rect.left = optionsRect.left; rect.top = optionsRect.top; rect.right = rect.left + cxOctant; rect.bottom = rect.top + cyOctant;
for (UINT nSize = 4; nSize <= 10; nSize += 2) { CBrush* pOldBrush;
if (nSize == m_nStrokeWidth) { pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT)); pDC->PatBlt(rect.left + (cxOctant - 14) / 2, rect.top + (cyOctant - 14) / 2, 14, 14, PATCOPY); pDC->SelectObject(pOldBrush); }
pOldBrush = pDC->SelectObject(GetSysBrush(nSize == m_nStrokeWidth ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->PatBlt(rect.left + (cxOctant - nSize) / 2, rect.top + (cyOctant - nSize) / 2, nSize, nSize, PATCOPY); pDC->SelectObject(pOldBrush);
rect.top += cyOctant; rect.bottom += cyOctant; } }
/***************************************************************************/
void CEraserTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { int iOptionNumber; int cyOctant = (optionsRect.Height() + 1) / 4; iOptionNumber = (clickPoint.y / cyOctant); if (iOptionNumber > 3) // there are 4 options, numbered 0,1,2,3
{ iOptionNumber = 3; }
m_nStrokeWidth = 4 + 2 * iOptionNumber;
// int cyOctant = (optionsRect.Height() + 1) / 4;
// m_nStrokeWidth = 4 + 2 * (clickPoint.y / cyOctant);
pWnd->InvalidateOptions(); }
void CEraserTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { if (pmti->fLeft) { COLORREF crRealLeftColor = crLeft; COLORREF crRealRightColor = crRight;
crLeft = crRight;
g_bCustomBrush = FALSE; fDraggingBrush = FALSE;
DrawImgLine(pImgWnd->m_pImg, pmti->ptPrev, pmti->pt, crRight, m_nStrokeWidth, squareBrush, TRUE);
crLeft = crRealLeftColor; crRight = crRealRightColor; } else { // Just erase pixels that match the drawing color...
g_bCustomBrush = FALSE; fDraggingBrush = FALSE;
HideBrush();
CDC* pImageDC = CDC::FromHandle(pImgWnd->m_pImg->hDC);
CRect rc;
// Call with NULL DC to get the CRect to use
DrawDCLine(NULL, pmti->ptPrev, pmti->pt, RGB(255, 255, 255), m_nStrokeWidth, squareBrush, rc);
CTempBitmap monoBitmap; CDC monoDc;
// Create the mono DC and bitmap
if (!monoDc.CreateCompatibleDC(NULL) || !monoBitmap.CreateBitmap(rc.Width(), rc.Height(), 1, 1, NULL)) { theApp.SetGdiEmergency(); return; }
// Select the bitmap and change the window origin so the mono DC has
// the same coordinate system as the image
CBitmap* pOldMonoBitmap = monoDc.SelectObject(&monoBitmap); monoDc.SetWindowOrg(rc.left, rc.top);
// Clear the mono DC and then draw the area that will be changed
monoDc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), BLACKNESS); DrawDCLine(monoDc.m_hDC, pmti->ptPrev, pmti->pt, RGB(255, 255, 255), m_nStrokeWidth, squareBrush, rc); DebugShowBitmap(monoDc.m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
// Select the proper palette, and make sure the brush origin is set
// correctly for pattern brushes
CPalette* pcPaletteOld = theImgBrush.SetBrushPalette(pImageDC, FALSE); pImageDC->SetBrushOrg(0, 0);
CBrush rightBrush; rightBrush.CreateSolidBrush(crRight);
if (!QuickColorToMono(&monoDc, rc.left, rc.top, rc.Width(), rc.Height(), pImageDC, rc.left, rc.top, SRCAND, crLeft)) { // We will get her for DDB's (in which case we could be using a
// dithered brush) or for high color images (so no palette problems)
// Create the brush to erase
CBrush leftBrush; leftBrush.CreateSolidBrush(crLeft); leftBrush.UnrealizeObject();
//#define DPSxna 0x00820c49L
// #define PSDPxax 0x00B8074AL
// XOR with the pattern so black is where the pattern was
CBrush* pOldBrush = pImageDC->SelectObject(&leftBrush); pImageDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT); DebugShowBitmap(pImageDC->m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
// Color to mono bitblt to get the final mask
// The ROP will take all pixels in the source that match the pattern
// and and them with the white pixels in the dest
theImgBrush.ColorToMonoBitBlt(&monoDc, rc.left, rc.top, rc.Width(), rc.Height(), pImageDC, rc.left, rc.top, SRCAND, RGB(0, 0, 0)); DebugShowBitmap(monoDc.m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
// XOR again to put the original back
pImageDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT); DebugShowBitmap(pImageDC->m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
pImageDC->SelectObject(pOldBrush); }
// Copy the pattern back into the image where the bitmap has white
CBrush *pOldBrush = pImageDC->SelectObject(&rightBrush);
COLORREF crNewBk, crNewText; GetMonoBltColors(pImageDC->m_hDC, NULL, crNewBk, crNewText); COLORREF crOldBk = pImageDC->SetBkColor(crNewBk); COLORREF crOldText = pImageDC->SetTextColor(crNewText); pImageDC->BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &monoDc, rc.left, rc.top, DSPDxax); pImageDC->SetBkColor(crOldBk); pImageDC->SetTextColor(crOldText); DebugShowBitmap(pImageDC->m_hDC, rc.left, rc.top, rc.Width(), rc.Height());
// Clean up stuff we have selected
pImageDC->SelectObject(pOldBrush);
monoDc.SelectObject(pOldMonoBitmap);
if (pcPaletteOld) pImageDC->SelectPalette(pcPaletteOld, FALSE);
InvalImgRect(pImgWnd->m_pImg, &rc); CommitImgRect(pImgWnd->m_pImg, &rc); }
if (pmti->pt.x < c_undoRect.left) c_undoRect.left = pmti->pt.x; else if (pmti->pt.x > c_undoRect.right) c_undoRect.right = pmti->pt.x; if (pmti->pt.y < c_undoRect.top) c_undoRect.top = pmti->pt.y; else if (pmti->pt.y > c_undoRect.bottom) c_undoRect.bottom = pmti->pt.y;
SetStatusBarPosition(pmti->pt);
fDraggingBrush = TRUE;
pImgWnd->ShowBrush(pmti->pt); }
/***************************************************************************/
void CEraserTool::OnMove(CImgWnd* pImgWnd, MTI* pmti) { COLORREF crRealLeftColor; COLORREF crRealRightColor;
crRealLeftColor = crLeft; crRealRightColor = crRight;
crLeft = crRight;
g_bCustomBrush = FALSE;
CImgTool::OnMove(pImgWnd, pmti);
crLeft = crRealLeftColor; crRight = crRealRightColor; }
/***************************************************************************/
void CEraserTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { c_undoRect.left -= m_nStrokeWidth / 2; c_undoRect.top -= m_nStrokeWidth / 2; c_undoRect.right += (m_nStrokeWidth + 1) / 2; c_undoRect.bottom += (m_nStrokeWidth + 1) / 2; pImgWnd->FinishUndo(c_undoRect);
CImgTool::OnEndDrag(pImgWnd, pmti); // Bypass CFreehandTool
}
/***************************************************************************/
void CEraserTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShow) { if (bShow && g_bBrushVisible) { CClientDC dc(pImgWnd);
CRect imageRect; pImgWnd->GetImageRect(imageRect); dc.IntersectClipRect(&imageRect);
BOOL bGrid = pImgWnd->IsGridVisible();
CRect rect = rcDragBrush; pImgWnd->ImageToClient(rect); dc.PatBlt(rect.left, rect.top, rect.Width() + bGrid, 1, BLACKNESS); dc.PatBlt(rect.left, rect.top + 1, 1, rect.Height() - 2 + bGrid, BLACKNESS); dc.PatBlt(rect.right - 1 + bGrid, rect.top + 1, 1, rect.Height() - 2 + bGrid, BLACKNESS); dc.PatBlt(rect.left, rect.bottom - 1 + bGrid, rect.Width() + bGrid, 1, BLACKNESS); } }
/***************************************************************************/
UINT CEraserTool::GetCursorID() { CPoint point; GetCursorPos(&point);
CRect rc;
CPBView* pcbView = (CPBView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView(); CImgWnd* pImgWnd = pcbView->m_pImgWnd;
pImgWnd->ScreenToClient(&point); pImgWnd->GetClientRect(&rc); if (!rc.PtInRect(point)) { // Return crosshair outside the client rect of the image window
return LOWORD(IDC_CROSSHAIR); }
pImgWnd->ClientToImage(point); if (point.x > pImgWnd->m_pImg->cxWidth || point.y > pImgWnd->m_pImg->cyHeight) { // Return crosshair outside the drawing area
return LOWORD(IDC_CROSSHAIR); }
return m_nCursorID; }
/***************************************************************************/
CImageWell CAirBrushTool::c_imageWell(IDB_AIROPT, CSize(24, 24));
CAirBrushTool::CAirBrushTool() { m_nCmdID = IDMB_AIRBSHTOOL; m_nStrokeWidth = 8; m_nCursorID = IDCUR_AIRBRUSH; m_bUsesBrush = FALSE; m_bFilled = TRUE; }
/***************************************************************************/
void CAirBrushTool::OnPaintOptions( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) { CPoint pt(optionsRect.left + (optionsRect.Width() / 2 - 24) / 2, optionsRect.top + (optionsRect.Height() / 2 - 24) / 2);
c_imageWell.Open();
pDC->SetTextColor(GetSysColor( m_nStrokeWidth == 8 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->SetBkColor(GetSysColor( m_nStrokeWidth == 8 ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); c_imageWell.DrawImage(pDC, pt, 0, SRCCOPY); pt.x += optionsRect.Width() / 2;
pDC->SetTextColor(GetSysColor( m_nStrokeWidth == 16 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->SetBkColor(GetSysColor( m_nStrokeWidth == 16 ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); c_imageWell.DrawImage(pDC, pt, 1, SRCCOPY); pt.x = optionsRect.left + (optionsRect.Width() - 24) / 2;
pDC->SetTextColor(GetSysColor( m_nStrokeWidth == 24 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->SetBkColor(GetSysColor( m_nStrokeWidth == 24 ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); pt.y += optionsRect.Height() / 2; c_imageWell.DrawImage(pDC, pt, 2, SRCCOPY);
c_imageWell.Close(); }
/***************************************************************************/
void CAirBrushTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { UINT nNewStrokeWidth;
if (clickPoint.y > optionsRect.Height() / 2) nNewStrokeWidth = 24; else if (clickPoint.x > optionsRect.Width() / 2) nNewStrokeWidth = 16; else nNewStrokeWidth = 8;
if (nNewStrokeWidth != m_nStrokeWidth) SetStrokeWidth(nNewStrokeWidth); }
/***************************************************************************/
void CAirBrushTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { pImgWnd->SetTimer(1, 0, NULL); // FUTURE: rate should be adjustable
CFreehandTool::OnStartDrag(pImgWnd, pmti); }
/***************************************************************************/
void CAirBrushTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { CPoint pt; CRect rect;
fDraggingBrush = FALSE;
int nDiam = (m_nStrokeWidth + 1) & ~1; // nDiam must be even
if (nDiam < 4) nDiam = 4; int nRadius = nDiam / 2; int nRadiusSquared = (nDiam / 2) * (nDiam / 2);
// Start a bounding rect for changes made in the following loop
rect.left = rect.right = pmti->pt.x; rect.top = rect.bottom = pmti->pt.y;
m_bCtrlDown = pmti->fCtrlDown; // save it for the timer
SetupPenBrush(pImgWnd->m_pImg->hDC, !pmti->fLeft, TRUE, m_bCtrlDown);
for (int i = 0; i < 10; i++) { // Loop here until we randomly pick a point inside a circle
// centered around the mouse with a diameter of m_nStrokeWidth...
#ifdef _DEBUG
int nTrys = 0; #endif
do { #ifdef _DEBUG
if (nTrys++ > 10) { TRACE(TEXT("The airbrush is clogged!\n")); break; } #endif
pt = pmti->pt; pt.x += (rand() % (nDiam + 1)) - nRadius; pt.y += (rand() % (nDiam + 1)) - nRadius; } while (((pt.x - pmti->pt.x) * (pt.x - pmti->pt.x) + (pt.y - pmti->pt.y) * (pt.y - pmti->pt.y)) > nRadiusSquared);
PatBlt(pImgWnd->m_pImg->hDC, pt.x, pt.y, 1, 1, PATCOPY);
if (pt.x < rect.left) rect.left = pt.x; else if (pt.x + 1 > rect.right) rect.right = pt.x + 1; if (pt.y < rect.top) rect.top = pt.y; else if (pt.y + 1 > rect.bottom) rect.bottom = pt.y + 1; }
SetupPenBrush(pImgWnd->m_pImg->hDC, !pmti->fLeft, FALSE, m_bCtrlDown);
c_undoRect |= rect;
InvalImgRect(pImgWnd->m_pImg, &rect); CommitImgRect(pImgWnd->m_pImg, &rect);
SetStatusBarPosition(pmti->pt); }
/***************************************************************************/
void CAirBrushTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { ::KillTimer(pImgWnd->GetSafeHwnd(), 1); CFreehandTool::OnEndDrag(pImgWnd, pmti); }
/***************************************************************************/
void CAirBrushTool::OnTimer(CImgWnd* pImgWnd, MTI* pmti) { pmti->fCtrlDown = m_bCtrlDown; OnDrag(pImgWnd, pmti); }
/***************************************************************************/
void CAirBrushTool::OnCancel(CImgWnd* pImgWnd) { ::KillTimer(pImgWnd->GetSafeHwnd(), 1); CImgTool::OnCancel(pImgWnd); }
/***************************************************************************/
CLineTool::CLineTool() { m_bUsesBrush = FALSE; m_nStrokeWidth = 1; m_nCmdID = IDMB_LINETOOL; }
/***************************************************************************/
void CLineTool::Render(CDC* pDC, CRect& rect, BOOL bLeft, BOOL bCommit, BOOL bCtrlDown) {
COLORREF color;
// use transparent color if defined
if (bCtrlDown && crTrans != TRANS_COLOR_NONE) { color = crTrans; } else { color = bLeft ? crLeft : crRight; }
int sx = rect.left; int sy = rect.top; int ex = rect.right; int ey = rect.bottom;
DrawImgLine( pImgCur, rect.TopLeft(), rect.BottomRight(), color, m_nStrokeWidth, m_nStrokeShape, FALSE ); CRect rc; if (sx < ex) { rc.left = sx; rc.right = ex + 1; } else { rc.left = ex; rc.right = sx + 1; }
if (sy < ey) { rc.top = sy; rc.bottom = ey + 1; } else { rc.top = ey; rc.bottom = sy + 1; }
rc.left -= m_nStrokeWidth; rc.top -= m_nStrokeWidth; rc.right += m_nStrokeWidth; rc.bottom += m_nStrokeWidth;
rect = rc; }
/******************************************************************************/ // Given an x and y coordinate, we can calculate the angle from the x axis in
// the right triangle using the Tan(a) algorithm. Where
// tan(a) = opposite/adjacent or y/x.
//
// In order to constrain the line drawing, we need to determine the angle
// from the x axis and constrain it to the nearest 45 degree line (0 degree,
// 45 degree, 90 degree,....).
//
// Thus we can use the following rule :
//
// 0 Degrees <= Angle < 45/2 Degrees Constrained to 0 Degrees
// 45/2 Degrees <= Angle < 45+45/2 Degrees Constrained to 45 Degrees
// 45+45/2 Degrees <= Angle < 90 Degrees Constrained to 90 Degrees
//
//
// We can translate this rule into the below using tan(angle) = y/x and the
// fact that Tan(0) = 0, Tan(22.5) = .414, tan(67.5) = 2.414, tan(90) = infinity
//
// 0 <= y/x < .414 Constrained to 0 Degrees
// .414 <= y/x < 2.414 Constrained to 45 Degrees
// 2.414 <= y/x Constrained to 90 Degrees
//
// For more precision, we will multiply everything by 1000 to give us finally
// the following table
//
// 0 <= (1000*y)/x < 414 Constrained to 0 Degrees
// 414 <= (1000*y)/x < 2414 Constrained to 45 Degrees
// 2414 <= (1000*y)/x Constrained to 90 Degrees
void CLineTool::AdjustPointsForConstraint(MTI *pmti) { if (pmti != NULL) { int iAngle = 0;
long lcy = abs( (pmti->ptDown).y - (pmti->pt).y ); long lcx = abs( (pmti->ptDown).x - (pmti->pt).x ); long lResult;
if (lcx != 0) { lResult = (lcy*1000)/lcx; } else { lResult = 2414; // default to 90 degrees if x value is 0.
}
if (lResult >= 2414) { iAngle = 90; } else { if (lResult >= 414) { iAngle = 45; } else { iAngle = 0; } }
// int iWidthHeight = min( abs(pmti->ptDown.x - pmti->pt.x),
// abs(pmti->ptDown.y - pmti->pt.y));
int iWidthHeight = ( abs(pmti->ptDown.x - pmti->pt.x) + abs(pmti->ptDown.y - pmti->pt.y) ) / 2 ;
switch (iAngle) { default: //if for some reason, angle is not valid case, use 0
case 0: pmti->pt.y = pmti->ptDown.y; break;
case 45: if (pmti->pt.x < pmti->ptDown.x) { pmti->pt.x = pmti->ptDown.x - iWidthHeight; } else { pmti->pt.x = pmti->ptDown.x + iWidthHeight; }
if (pmti->pt.y < pmti->ptDown.y) { pmti->pt.y = pmti->ptDown.y - iWidthHeight; } else { pmti->pt.y = pmti->ptDown.y + iWidthHeight; }
break;
case 90: pmti->pt.x = pmti->ptDown.x; break; } } }
/***************************************************************************/
CRectTool::CRectTool() { m_nCmdID = IDMB_RECTTOOL; }
/***************************************************************************/
CRoundRectTool::CRoundRectTool() { m_nCmdID = IDMB_RNDRECTTOOL; }
/***************************************************************************/
CEllipseTool::CEllipseTool() { m_nCmdID = IDMB_ELLIPSETOOL; }
/***************************************************************************/
CPickColorTool::CPickColorTool() { m_bIsUndoable = FALSE; m_bCanBePrevTool = FALSE; m_bToggleWithPrev = TRUE; m_Color = ::GetSysColor( COLOR_BTNFACE ); m_nCursorID = IDC_EYEDROP; m_nCmdID = IDMY_PICKCOLOR; }
/***************************************************************************/
void CPickColorTool::OnActivate(BOOL bActivate) { g_bPickingColor = bActivate;
m_Color = ::GetSysColor( COLOR_BTNFACE );
CImgTool::OnActivate(bActivate); }
/***************************************************************************/
void CPickColorTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { CImgTool::OnStartDrag(pImgWnd, pmti); OnDrag(pImgWnd, pmti); }
/***************************************************************************/
void CPickColorTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { COLORREF cr = GetPixel(pImgWnd->m_pImg->hDC, pmti->pt.x, pmti->pt.y);
BYTE red = GetRValue( cr ); BYTE green = GetGValue( cr ); BYTE blue = GetBValue( cr );
if (theApp.m_bPaletted) m_Color = PALETTERGB( red, green, blue ); else m_Color = RGB( red, green, blue );
if (g_pImgToolWnd && g_pImgToolWnd->m_hWnd && IsWindow(g_pImgToolWnd->m_hWnd) ) g_pImgToolWnd->InvalidateOptions(); }
/***************************************************************************/
void CPickColorTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { if (pmti->fCtrlDown) // pick transparent color
{ SetTransColor (m_Color); } else if (pmti->fLeft) SetDrawColor ( m_Color ); else SetEraseColor( m_Color );
m_Color = ::GetSysColor( COLOR_BTNFACE );
if (g_pImgToolWnd && g_pImgToolWnd->m_hWnd && IsWindow(g_pImgToolWnd->m_hWnd) ) g_pImgToolWnd->InvalidateOptions();
SelectPrevious(); CImgTool::OnEndDrag( pImgWnd, pmti ); }
/***************************************************************************/
void CPickColorTool::OnCancel(CImgWnd* pImgWnd) { SelectPrevious(); CImgTool::OnCancel(pImgWnd); }
/***************************************************************************/
void CPickColorTool::OnPaintOptions( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) { CPalette* pOldPal = NULL;
if (theApp.m_pPalette) { pOldPal = pDC->SelectPalette( theApp.m_pPalette, FALSE ); pDC->RealizePalette(); }
CBrush br;
if (br.CreateSolidBrush( m_Color )) { pDC->FillRect( &paintRect, &br );
br.DeleteObject(); }
if (pOldPal) pDC->SelectPalette( pOldPal, FALSE ); }
/***************************************************************************/
CFloodTool::CFloodTool() { m_nCursorID = IDC_FLOOD; m_nCmdID = IDMB_FILLTOOL; m_bFilled = TRUE; }
/***************************************************************************/
void CFloodTool::OnPaintOptions(CDC* pDC, const CRect& paintRect, const CRect& optionsRect) { // PaintStdPattern(pDC, paintRect, optionsRect);
}
/***************************************************************************/
void CFloodTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { CImgTool::OnClickOptions(pWnd, optionsRect, clickPoint); }
/***************************************************************************/
void CFloodTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { CImgTool::OnStartDrag( pImgWnd, pmti );
CPalette *pcPaletteOld = NULL;
IMG* pimg = pImgWnd->m_pImg;
CDC* pDC = CDC::FromHandle( pimg->hDC );
CBrush brush; CBrush* pOldBrush = NULL;
COLORREF color; if (pmti->fCtrlDown && crTrans != TRANS_COLOR_NONE) { color = crTrans; } else { color = pmti->fLeft ? crLeft : crRight; } if (theApp.m_pPalette) { pcPaletteOld = pDC->SelectPalette( theApp.m_pPalette, FALSE ); pDC->RealizePalette(); }
if (brush.CreateSolidBrush( color )) { pOldBrush = pDC->SelectObject( &brush );
COLORREF crFillThis = pDC->GetPixel( pmti->pt.x, pmti->pt.y );
BYTE iRed = GetRValue( crFillThis ); BYTE iGreen = GetGValue( crFillThis ); BYTE iBlue = GetBValue( crFillThis );
if (theApp.m_bPaletted) crFillThis = PALETTERGB( iRed, iGreen, iBlue ); else crFillThis = RGB( iRed, iGreen, iBlue );
pDC->ExtFloodFill( pmti->pt.x, pmti->pt.y, crFillThis, FLOODFILLSURFACE );
pDC->SelectObject( pOldBrush );
InvalImgRect ( pimg, NULL ); CommitImgRect( pimg, NULL ); } else { theApp.SetGdiEmergency(); }
if (pcPaletteOld) pDC->SelectPalette( pcPaletteOld, FALSE ); }
/***************************************************************************/
void CFloodTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { pImgWnd->FinishUndo(CRect(0, 0, pImgWnd->m_pImg->cxWidth, pImgWnd->m_pImg->cyHeight));
CImgTool::OnEndDrag(pImgWnd, pmti); }
/***************************************************************************/
CRect CSelectTool::c_selectRect; CImageWell CSelectTool::c_imageWell(IDB_SELOPT, CSize(37, 23));
CSelectTool::CSelectTool() { m_bIsUndoable = FALSE; m_nCmdID = IDMB_PICKTOOL; m_bCanBePrevTool = FALSE; }
/***************************************************************************/
void CSelectTool::OnPaintOptions( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) { CPoint pt(optionsRect.left + (optionsRect.Width() - 37) / 2, optionsRect.top + (optionsRect.Height() / 2 - 23) / 2);
CRect selRect(pt.x - 3, pt.y - 3, pt.x + 37 + 3, pt.y + 23 + 3);
CBrush* pOldBrush;
pOldBrush = pDC->SelectObject( GetSysBrush(theImgBrush.m_bOpaque ? COLOR_HIGHLIGHT : COLOR_BTNFACE));
pDC->PatBlt(selRect.left, selRect.top, selRect.Width(), selRect.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
selRect.OffsetRect(0, optionsRect.Height() / 2);
pOldBrush = pDC->SelectObject(GetSysBrush(theImgBrush.m_bOpaque ? COLOR_BTNFACE : COLOR_HIGHLIGHT));
pDC->PatBlt(selRect.left, selRect.top, selRect.Width(), selRect.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
c_imageWell.Open();
c_imageWell.DrawImage(pDC, pt, 0);
pt.y += optionsRect.Height() / 2;
c_imageWell.DrawImage(pDC, pt, 1);
c_imageWell.Close(); }
/***************************************************************************/
void CSelectTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { BOOL bNewOpaque = clickPoint.y < optionsRect.Height() / 2;
if (bNewOpaque != theImgBrush.m_bOpaque) { HideBrush();
theImgBrush.m_bOpaque = bNewOpaque; theImgBrush.RecalcMask(crRight);
CImgWnd::GetCurrent()->MoveBrush(theImgBrush.m_rcSelection);
pWnd->InvalidateOptions(); } }
/***************************************************************************/
void CSelectTool::InvertSelectRect(CImgWnd* pImgWnd) { if (c_selectRect.IsRectEmpty()) return;
CClientDC dc( pImgWnd );
CBrush* pOldBrush = NULL; int iLineWidth = pImgWnd->GetZoom();
if (g_brSelectHorz.m_hObject != NULL) pOldBrush = dc.SelectObject( &g_brSelectHorz ); else pOldBrush = (CBrush*)dc.SelectStockObject( BLACK_BRUSH );
CRect invertRect = c_selectRect;
pImgWnd->ImageToClient( invertRect );
int iWidth = invertRect.Width(); int iHeight = invertRect.Height();
dc.PatBlt( invertRect.left, invertRect.top, iWidth - iLineWidth, iLineWidth, PATINVERT ); dc.PatBlt( invertRect.left, invertRect.top + iHeight - iLineWidth, iWidth - iLineWidth, iLineWidth, PATINVERT );
if (g_brSelectVert.m_hObject != NULL) dc.SelectObject( &g_brSelectVert );
dc.PatBlt( invertRect.left, invertRect.top + iLineWidth * 2, iLineWidth, iHeight - iLineWidth * 3, PATINVERT ); dc.PatBlt( invertRect.right - iLineWidth, invertRect.top, iLineWidth, iHeight, PATINVERT );
if (pOldBrush != NULL) dc.SelectObject( pOldBrush ); }
/***************************************************************************/
void CSelectTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShow) { if (!bShow) { InvertSelectRect(pImgWnd); c_selectRect.SetRect(0, 0, 0, 0); } }
/***************************************************************************/
void CSelectTool::OnActivate(BOOL bActivate) { if (!bActivate) { if (theImgBrush.m_pImg != NULL) { if (! theImgBrush.m_bFirstDrag) CommitSelection(TRUE);
InvalImgRect(theImgBrush.m_pImg, NULL); // erase selection tracker
theImgBrush.m_pImg = NULL; } }
CImgTool::OnActivate(bActivate); }
/***************************************************************************/
void CSelectTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { CImgTool::OnStartDrag(pImgWnd, pmti);
CommitSelection(TRUE);
pImgWnd->EraseTracker();
theImgBrush.m_bMakingSelection = TRUE; }
/***************************************************************************/
void CSelectTool::OnDrag(CImgWnd* pImgWnd, MTI* pmti) { CRect newSelectRect(pmti->ptDown.x, pmti->ptDown.y, pmti->pt.x, pmti->pt.y); FixRect(&newSelectRect); newSelectRect.right += 1; newSelectRect.bottom += 1;
if (newSelectRect.left < 0) newSelectRect.left = 0; if (newSelectRect.top < 0) newSelectRect.top = 0; if (newSelectRect.right > pImgWnd->GetImg()->cxWidth) newSelectRect.right = pImgWnd->GetImg()->cxWidth; if (newSelectRect.bottom > pImgWnd->GetImg()->cyHeight) newSelectRect.bottom = pImgWnd->GetImg()->cyHeight;
if (newSelectRect != c_selectRect) { InvertSelectRect(pImgWnd); c_selectRect = newSelectRect; InvertSelectRect(pImgWnd); }
SetStatusBarPosition(pmti->ptDown); SetStatusBarSize(c_selectRect.Size()); }
/***************************************************************************/
void CSelectTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { InvertSelectRect(pImgWnd); c_selectRect.SetRect(0, 0, 0, 0);
CRect rcPick;
theImgBrush.m_bMakingSelection = FALSE;
if (pmti->ptDown.x > pmti->pt.x) { rcPick.left = pmti->pt.x; rcPick.right = pmti->ptDown.x; } else { rcPick.left = pmti->ptDown.x; rcPick.right = pmti->pt.x; }
if (pmti->ptDown.y > pmti->pt.y) { rcPick.top = pmti->pt.y; rcPick.bottom = pmti->ptDown.y; } else { rcPick.top = pmti->ptDown.y; rcPick.bottom = pmti->pt.y; }
if (rcPick.left < 0) rcPick.left = 0; if (rcPick.top < 0) rcPick.top = 0; if (rcPick.right > pImgWnd->m_pImg->cxWidth - 1) rcPick.right = pImgWnd->m_pImg->cxWidth - 1; if (rcPick.bottom > pImgWnd->m_pImg->cyHeight - 1) rcPick.bottom = pImgWnd->m_pImg->cyHeight - 1;
if (rcPick.Width() == 0 || rcPick.Height() == 0) { theImgBrush.TopLeftHandle();
theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE; g_bCustomBrush = FALSE; SetCombineMode(combineColor);
InvalImgRect(pImgWnd->m_pImg, NULL); // redraw selection
theImgBrush.m_pImg = NULL; } else { rcPick.right += 1; rcPick.bottom += 1;
pImgWnd->MakeBrush(pImgWnd->m_pImg->hDC, rcPick ); }
ClearStatusBarSize();
CImgTool::OnEndDrag(pImgWnd, pmti);
if (pmti->fRight && !pmti->fLeft) { CPoint pt = pmti->pt;
pImgWnd->OnRButtonDownInSel(&pt); }
}
/***************************************************************************/
void CSelectTool::OnCancel(CImgWnd* pImgWnd) { if (! theImgBrush.m_bMakingSelection && CWnd::GetCapture() != pImgWnd) { // We were not selecting or dragging, just cancel the select tool...
CommitSelection(TRUE);
theImgBrush.TopLeftHandle();
theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE; g_bCustomBrush = FALSE; SetCombineMode(combineColor);
if (theImgBrush.m_pImg != NULL) InvalImgRect(theImgBrush.m_pImg, NULL); // redraw selection
theImgBrush.m_pImg = NULL; CImgTool::OnCancel(pImgWnd); return; }
if (!theImgBrush.m_bMakingSelection && CWnd::GetCapture() == pImgWnd) { HideBrush();
if (!theImgBrush.m_bMoveSel && !theImgBrush.m_bSmearSel) { if (g_bCustomBrush) { theImgBrush.TopLeftHandle();
g_bCustomBrush = FALSE; SetCombineMode(combineColor); } else { if (theImgBrush.m_pImg) CommitSelection(TRUE); InvalImgRect(pImgWnd->m_pImg, NULL); // erase the dragger
} } }
InvertSelectRect(pImgWnd); c_selectRect.SetRect(0, 0, 0, 0);
theImgBrush.TopLeftHandle();
g_bCustomBrush = FALSE; theImgBrush.m_pImg = NULL; theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE; theImgBrush.m_bMakingSelection = FALSE;
InvalImgRect(pImgWnd->m_pImg, NULL);
CImgTool::OnCancel(pImgWnd); }
/***************************************************************************/
BOOL CSelectTool::IsToolModal(void) { if (theImgBrush.m_pImg) { return(TRUE); }
return(CImgTool::IsToolModal()); }
/***************************************************************************/
UINT CSelectTool::GetCursorID() { CPoint point; GetCursorPos(&point); CImgWnd* pImgWnd = (CImgWnd*)CWnd::WindowFromPoint(point);
if (pImgWnd->IsKindOf(RUNTIME_CLASS(CImgWnd)) && pImgWnd->GetImg() == pImgCur && theImgBrush.m_pImg != NULL) { pImgWnd->ScreenToClient(&point); pImgWnd->ClientToImage(point);
if (theImgBrush.m_rcSelection.PtInRect(point)) return IDCUR_MOVE; }
return m_nCursorID; }
/***************************************************************************/
CRect CZoomTool::c_zoomRect; CImgWnd* CZoomTool::c_pImgWnd; CImageWell CZoomTool::c_imageWell(IDB_ZOOMOPT, CSize(23, 9));
/***************************************************************************/
CZoomTool::CZoomTool() { m_bIsUndoable = FALSE; m_bCanBePrevTool = FALSE; m_bToggleWithPrev = TRUE;
m_nCursorID = IDC_ZOOMIN; m_nCmdID = IDMB_ZOOMTOOL; }
/***************************************************************************/
void CZoomTool::OnPaintOptions( CDC* pDC, const CRect& paintRect, const CRect& optionsRect ) { int nCurZoom = CImgWnd::GetCurrent()->GetZoom(); int dy = optionsRect.Height() / 4; CPoint pt(optionsRect.left + (optionsRect.Width() - 23) / 2, optionsRect.top + optionsRect.Height() / dy);
c_imageWell.Open();
if (nCurZoom == 1) { CBrush* pOldBrush; pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT)); pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4, PATCOPY); pDC->SelectObject(pOldBrush); } pDC->SetTextColor(GetSysColor( nCurZoom == 1 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->SetBkColor(GetSysColor( nCurZoom == 1 ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); c_imageWell.DrawImage(pDC, pt, 0, SRCCOPY); pt.y += dy;
if (nCurZoom == 2) { CBrush* pOldBrush; pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT)); pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4, PATCOPY); pDC->SelectObject(pOldBrush); } pDC->SetTextColor(GetSysColor( nCurZoom == 2 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->SetBkColor(GetSysColor( nCurZoom == 2 ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); c_imageWell.DrawImage(pDC, pt, 1, SRCCOPY); pt.y += dy;
if (nCurZoom == 6) { CBrush* pOldBrush; pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT)); pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4, PATCOPY); pDC->SelectObject(pOldBrush); } pDC->SetTextColor(GetSysColor( nCurZoom == 6 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->SetBkColor(GetSysColor( nCurZoom == 6 ? COLOR_HIGHLIGHT : COLOR_BTNFACE)); c_imageWell.DrawImage(pDC, pt, 2, SRCCOPY); pt.y += dy;
if (nCurZoom == 8) { CBrush* pOldBrush; pOldBrush = pDC->SelectObject(GetSysBrush(COLOR_HIGHLIGHT)); pDC->PatBlt(pt.x - 8, pt.y - 2, 23 + 16, 9 + 4, PATCOPY); pDC->SelectObject(pOldBrush); } pDC->SetTextColor(GetSysColor( nCurZoom == 8 ? COLOR_HIGHLIGHTTEXT : COLOR_BTNTEXT)); pDC->SetBkColor(GetSysColor( nCurZoom == 8 ? COLOR_HIGHLIGHT : COLOR_BTNFACE));; c_imageWell.DrawImage(pDC, pt, 3, SRCCOPY);
c_imageWell.Close(); }
/***************************************************************************/
void CZoomTool::OnClickOptions(CImgToolWnd* pWnd, const CRect& optionsRect, const CPoint& clickPoint) { int nNewZoom = clickPoint.y / (optionsRect.Height() / 4) + 1; if (nNewZoom >= 3) nNewZoom *= 2;
if (nNewZoom != CImgWnd::GetCurrent()->GetZoom()) { CImgWnd::GetCurrent()->SetZoom(nNewZoom); CImgWnd::GetCurrent()->CheckScrollBars();
pWnd->InvalidateOptions(); }
SelectPrevious(); }
/***************************************************************************/
void CZoomTool::OnLeave(CImgWnd* pImgWnd, MTI* pmti) { InvertZoomRect(); c_zoomRect.SetRect(0, 0, 0, 0); }
/***************************************************************************/
void CZoomTool::OnShowDragger(CImgWnd* pImgWnd, BOOL bShow) { InvertZoomRect(); }
/***************************************************************************/
void CZoomTool::InvertZoomRect() { if (c_zoomRect.IsRectEmpty()) return;
CClientDC dc(c_pImgWnd); CBrush* pOldBrush = (CBrush*)dc.SelectStockObject(NULL_BRUSH); dc.SetROP2(R2_NOT); CRect invertRect = c_zoomRect; c_pImgWnd->ImageToClient(invertRect); dc.Rectangle(&invertRect); dc.SelectObject(pOldBrush); }
/***************************************************************************/
void CZoomTool::OnMove(CImgWnd* pImgWnd, MTI* pmti) { if (pImgWnd->GetZoom() > 1) return;
CRect viewRect; pImgWnd->GetClientRect(&viewRect); int nPrevZoom = pImgWnd->GetPrevZoom();
CRect newZoomRect; CSize viewSize = viewRect.Size(); if (viewSize.cx > pImgWnd->m_pImg->cxWidth * nPrevZoom) viewSize.cx = pImgWnd->m_pImg->cxWidth * nPrevZoom; if (viewSize.cy > pImgWnd->m_pImg->cyHeight * nPrevZoom) viewSize.cy = pImgWnd->m_pImg->cyHeight * nPrevZoom; newZoomRect.left = pmti->pt.x; newZoomRect.top = pmti->pt.y; newZoomRect.right = newZoomRect.left + viewSize.cx / nPrevZoom; newZoomRect.bottom = newZoomRect.top + viewSize.cy / nPrevZoom; newZoomRect.OffsetRect(-newZoomRect.Width() / 2, -newZoomRect.Height() / 2);
int xAdjust = 0; int yAdjust = 0;
if (newZoomRect.left < 0) xAdjust = -newZoomRect.left; else if ((xAdjust = pImgWnd->m_pImg->cxWidth - newZoomRect.right) > 0) xAdjust = 0;
if (newZoomRect.top < 0) yAdjust = -newZoomRect.top; else if ((yAdjust = pImgWnd->m_pImg->cyHeight - newZoomRect.bottom) > 0) yAdjust = 0;
newZoomRect.OffsetRect(xAdjust, yAdjust);
if (newZoomRect != c_zoomRect) { InvertZoomRect(); c_pImgWnd = pImgWnd; c_zoomRect = newZoomRect; InvertZoomRect(); } }
/***************************************************************************/
void CZoomTool::OnStartDrag(CImgWnd* pImgWnd, MTI* pmti) { CImgTool::OnStartDrag(pImgWnd, pmti);
c_pImgWnd = pImgWnd; InvertZoomRect();
if (pImgWnd->GetZoom() == 1) { pImgWnd->SetZoom( pImgWnd->GetPrevZoom() ); pImgWnd->CheckScrollBars(); pImgWnd->SetScroll(-c_zoomRect.left - 1, -c_zoomRect.top - 1); } else { pImgWnd->SetZoom(1); pImgWnd->CheckScrollBars(); }
c_zoomRect.SetRect(0, 0, 0, 0); }
/***************************************************************************/
void CZoomTool::OnEndDrag(CImgWnd* pImgWnd, MTI* pmti) { SelectPrevious(); CImgTool::OnEndDrag(pImgWnd, pmti); }
/***************************************************************************/
void CZoomTool::OnCancel(CImgWnd* pImgWnd) { InvertZoomRect(); c_zoomRect.SetRect(0, 0, 0, 0); SelectPrevious(); CImgTool::OnCancel(pImgWnd); }
/***************************************************************************/
|