|
|
#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 "imgcolor.h"
#include "imgbrush.h"
#include "imgwell.h"
#include "imgtools.h"
#include "tedit.h"
#include "t_text.h"
#include "t_fhsel.h"
#include "toolbox.h"
#include "undo.h"
#include "props.h"
#include "cmpmsg.h"
#include "imgdlgs.h"
#include "ferr.h"
#include "thumnail.h"
#ifdef _DEBUG
#undef THIS_FILE
static CHAR BASED_CODE THIS_FILE[] = __FILE__; #endif
IMPLEMENT_DYNAMIC(CImgWnd, CWnd)
#include "memtrace.h"
/***************************************************************************/ // helper fns
static CTedit *_GetTextEdit() { if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL) { CTextTool* pTextTool = (CTextTool*)CImgTool::GetCurrent();
if ((pTextTool != NULL) && pTextTool->IsKindOf(RUNTIME_CLASS( CTextTool ))) { CTedit* pTextEdit = pTextTool->GetTextEditField();
if ((pTextEdit != NULL) && pTextEdit->IsKindOf(RUNTIME_CLASS( CTedit ))) { return pTextEdit; } } } return NULL; }
BOOL IsUserEditingText() { return (_GetTextEdit() != NULL); }
BOOL TextToolProcessed( UINT nMessage ) { CTedit *pTextEdit = _GetTextEdit(); if (pTextEdit) { pTextEdit->SendMessage( WM_COMMAND, nMessage ); return TRUE; } return FALSE; }
/***************************************************************************/
BEGIN_MESSAGE_MAP(CImgWnd, CWnd) ON_WM_CREATE() #if 0
ON_WM_DESTROY() #endif
ON_WM_SETFOCUS() ON_WM_KILLFOCUS() ON_WM_PAINT() ON_WM_SIZE() ON_WM_HSCROLL() ON_WM_VSCROLL() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONDBLCLK() ON_WM_LBUTTONUP() ON_WM_RBUTTONDOWN() ON_WM_RBUTTONDBLCLK() ON_WM_RBUTTONUP() ON_WM_MOUSEMOVE() ON_WM_KEYDOWN() ON_WM_KEYUP() ON_WM_TIMER() ON_WM_CANCELMODE() ON_WM_WINDOWPOSCHANGING() ON_WM_DESTROYCLIPBOARD() ON_WM_PALETTECHANGED() ON_WM_SETCURSOR() ON_WM_MOUSEWHEEL () END_MESSAGE_MAP()
/***************************************************************************/
CRect rcDragBrush;
CImgBrush theBackupBrush;
CImgWnd* g_pMouseImgWnd = NULL; CImgWnd* g_pDragBrushWnd = NULL;
// Current Image Viewer
CImgWnd* CImgWnd::c_pImgWndCur = NULL; CDragger* CImgWnd::c_pResizeDragger = NULL; CTracker::STATE CImgWnd::c_dragState = CTracker::nil;
// Mouse Tracking Information
MTI mti; BOOL bIgnoreMouse;
/***************************************************************************/
CImgWnd::CImgWnd(IMG* pImg) { m_pNextImgWnd = NULL; m_nZoom = 1; m_nZoomPrev = 4; m_xScroll = 0; m_yScroll = 0; m_LineX = 1; m_LineY = 1; m_ptDispPos.x = -1; m_ptDispPos.y = -1; c_pImgWndCur = this; m_pwndThumbNailView = NULL; m_wClipboardFormat = 0; m_hPoints = NULL; m_WheelDelta = 0; ASSERT(pImg != NULL); m_pImg = pImg; m_pImg->m_nLastChanged = -1; }
/***************************************************************************/
CImgWnd::CImgWnd(CImgWnd *pImgWnd) { m_pImg = pImgWnd->m_pImg; m_pNextImgWnd = pImgWnd->m_pNextImgWnd; m_nZoom = pImgWnd->m_nZoom; m_nZoomPrev = pImgWnd->m_nZoomPrev; m_xScroll = pImgWnd->m_xScroll, m_yScroll = pImgWnd->m_yScroll; m_ptDispPos = pImgWnd->m_ptDispPos; m_pwndThumbNailView = NULL; m_wClipboardFormat = 0; m_hPoints = NULL; }
/***************************************************************************/
CImgWnd::~CImgWnd() { if (c_pImgWndCur == this) c_pImgWndCur = NULL;
if (g_pMouseImgWnd == this) g_pMouseImgWnd = NULL;
HideBrush(); fDraggingBrush = FALSE;
g_bBrushVisible = FALSE;
if (g_pDragBrushWnd == this) { g_pDragBrushWnd = NULL; }
if (m_hPoints) { ::GlobalFree( m_hPoints ); m_hPoints = NULL; } }
/***************************************************************************/
BOOL CImgWnd::Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID) { static CString sImgWndClass;
if (sImgWndClass.IsEmpty()) sImgWndClass = AfxRegisterWndClass( CS_DBLCLKS );
ASSERT( ! sImgWndClass.IsEmpty() );
dwStyle |= WS_CLIPSIBLINGS;
return CWnd::Create( sImgWndClass, NULL, dwStyle, rect, pParentWnd, nID ); }
/***************************************************************************/
int CImgWnd::OnCreate( LPCREATESTRUCT lpCreateStruct ) { if (m_pImg) AddImgWnd( m_pImg, this );
return CWnd::OnCreate(lpCreateStruct); }
/***************************************************************************/
#if 0
void CImgWnd::OnDestroy() { if (c_pImgWndCur == this) c_pImgWndCur = NULL;
HideBrush(); fDraggingBrush = FALSE;
CWnd::OnDestroy(); } #endif
/***************************************************************************/
void CImgWnd::OnPaletteChanged(CWnd *pPaletteWnd) { #if 0
// obviously this never gets hit or somebody would have realized by now...
CImgWnd::OnPaletteChanged(pPaletteWnd); #endif
Invalidate(); }
/***************************************************************************/
BOOL CImgWnd::OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message) { if (nHitTest==HTCLIENT && pWnd->m_hWnd==m_hWnd) { // We do our own cursor stuff in our own client area, but not in the
// text box
return(TRUE); }
return((BOOL)Default()); }
/***************************************************************************/
void CImgWnd::OnWindowPosChanging( WINDOWPOS FAR* lpwndpos ) { CWnd::OnWindowPosChanging( lpwndpos ); }
/***************************************************************************/ // Image View Painting Functions
//
void CImgWnd::OnPaint() { CPaintDC dc(this);
if (dc.m_hDC == NULL) { theApp.SetGdiEmergency(); return; }
if (m_pImg == NULL) return;
if (g_pMouseImgWnd == this) CImgTool::HideDragger( this );
CPalette* ppalOld = SetImgPalette( &dc, FALSE );
DrawBackground( &dc, (CRect*)&dc.m_ps.rcPaint ); DrawImage ( &dc, (CRect*)&dc.m_ps.rcPaint ); DrawTracker ( &dc, (CRect*)&dc.m_ps.rcPaint );
if (g_pMouseImgWnd == this) CImgTool::ShowDragger( this );
if (m_pwndThumbNailView != NULL) m_pwndThumbNailView->RefreshImage();
if (ppalOld) dc.SelectPalette( ppalOld, FALSE ); }
/***************************************************************************/
BOOL CImgWnd::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo ) { if (nCode == CN_COMMAND) { switch (nID) { case IDMX_VS_PAGEUP: SendMessage( WM_VSCROLL, SB_PAGEUP, 0L ); return TRUE;
case IDMX_VS_PAGEDOWN: SendMessage( WM_VSCROLL, SB_PAGEDOWN, 0L ); return TRUE;
case IDMX_HS_PAGEUP: SendMessage( WM_HSCROLL, SB_PAGEUP, 0L ); return TRUE;
case IDMX_HS_PAGEDOWN: SendMessage( WM_HSCROLL, SB_PAGEDOWN, 0L ); return TRUE;
}
CImgTool* pImgTool = CImgTool::FromID( nID );
if (pImgTool != NULL) { pImgTool->Select(); return TRUE; } } return CWnd::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ); }
void CImgWnd::GetDrawRects(const CRect* pPaintRect, const CRect* pReqDestRect, CRect& srcRect, CRect& destRect) { // Find the sub-rectangle of srcRect that corresponds to
// the pPaintRect sub-rectangle of destRect.
srcRect = *pPaintRect; srcRect.right += m_nZoom - 1; srcRect.bottom += m_nZoom - 1;
ClientToImage( srcRect );
srcRect.left = max(0, srcRect.left); srcRect.top = max(0, srcRect.top );
srcRect.right = min(m_pImg->cxWidth , srcRect.right ); srcRect.bottom = min(m_pImg->cyHeight, srcRect.bottom);
if (pReqDestRect == NULL) { destRect = srcRect; ImageToClient( destRect ); } else { destRect = *pReqDestRect; } }
/***************************************************************************/ // Draw the actual image 'a bitmap'. Drawing is
// optimized to only deal with the pixels inside paintRect. This function
// reduces flashing by drawing the image and optional grid in an off-screen
// bitmap and then transfering that bitmap to the screen.
//
void CImgWnd::DrawImage( CDC* pDC, const CRect* pPaintRect, CRect* pDestRect, BOOL bDoGrid ) { ASSERT( pDC != NULL ); ASSERT( m_pImg != NULL );
CRect destRect; CRect srcRect;
GetDrawRects(pPaintRect, pDestRect, srcRect, destRect);
if (srcRect.Width() <= 0 || srcRect.Height() <= 0) { // Nothing to paint...
return; }
if (! IsGridVisible() && m_nZoom == 1) { // Optimize the easy case... (Can't speed up magnified views
// because of the bogus hack we have to do in StretchCopy.)
if (theApp.m_pPalette && ((m_pImg->cPlanes * m_pImg->cBitCount) == 1)) { pDC->SetTextColor( PALETTEINDEX( 0 ) ); pDC->SetBkColor ( PALETTEINDEX( 1 ) ); }
BitBlt(pDC->m_hDC, destRect.left , destRect.top, destRect.Width(), destRect.Height(), m_pImg->hDC, srcRect.left , srcRect.top, SRCCOPY);
return; }
CDC tempDC; CBitmap tempBitmap; CBitmap* pOldTempBitmap;
if (! tempDC.CreateCompatibleDC(pDC) || ! tempBitmap.CreateCompatibleBitmap(pDC, destRect.Width() + 1, destRect.Height() + 1)) { theApp.SetGdiEmergency(FALSE); return; }
pOldTempBitmap = tempDC.SelectObject(&tempBitmap);
ASSERT(pOldTempBitmap != NULL);
CPalette* pOldPalette = SetImgPalette( &tempDC, FALSE ); // Background ??
// If we're zoomed in, use COLORONCOLOR for easy pixel-by-pixel editing
// Otherwise use HALFTONE for nice appearance
if (m_nZoom < 2) { tempDC.SetStretchBltMode(HALFTONE); } else { tempDC.SetStretchBltMode(COLORONCOLOR); }
if (m_pImg->cPlanes * m_pImg->cBitCount == 1) { tempDC.SetTextColor( RGB( 0x00, 0x00, 0x00 )); tempDC.SetBkColor ( RGB( 0xFF, 0xFF, 0xFF )); }
// Bitmaps...
StretchCopy(tempDC.m_hDC, 0, 0, destRect.Width(), destRect.Height(), m_pImg->hDC, srcRect.left, srcRect.top, srcRect.Width(), srcRect.Height()); // Draw the grid...
if (IsGridVisible() && bDoGrid) DrawGrid( &tempDC, srcRect, destRect );
// Transfer to the screen...
pDC->BitBlt(destRect.left, destRect.top, destRect.Width(), destRect.Height(), &tempDC, 0, 0, SRCCOPY); // Cleanup...
if (pOldPalette) tempDC.SelectPalette( pOldPalette, FALSE ); // Background ??
tempDC.SelectObject(pOldTempBitmap); }
/***************************************************************************/ // Draw a border and bevel around the image and fill the rest of
// the window with gray. If pPaintRect is not NULL, painting is
// optimized to only draw with the rectangle.
//
void CImgWnd::DrawBackground(CDC* pDC, const CRect* pPaintRect) { ASSERT( pDC != NULL );
CRect clientRect;
if (pPaintRect == NULL) { // Draw everything...
GetClientRect( &clientRect ); pPaintRect = &clientRect; }
CRect srcRect; CRect imageRect;
GetDrawRects(pPaintRect, NULL, srcRect, imageRect);
// Erase area around image, border, and bevel...
CBrush* pOldBrush = pDC->SelectObject( GetSysBrush( COLOR_APPWORKSPACE ) );
if (imageRect.top > pPaintRect->top) { // Top...
pDC->PatBlt(pPaintRect->left, pPaintRect->top, pPaintRect->Width(), imageRect.top - pPaintRect->top, PATCOPY); }
if (imageRect.left > pPaintRect->left) { // Left...
pDC->PatBlt(pPaintRect->left, imageRect.top, imageRect.left - pPaintRect->left, imageRect.Height(), PATCOPY); }
if (imageRect.right < pPaintRect->right) { // Right...
pDC->PatBlt(imageRect.right, imageRect.top, pPaintRect->right - imageRect.right, imageRect.Height(), PATCOPY); }
if (imageRect.bottom < pPaintRect->bottom) { // Bottom...
pDC->PatBlt(pPaintRect->left, imageRect.bottom, pPaintRect->Width(), pPaintRect->bottom - imageRect.bottom, PATCOPY); }
pDC->SelectObject(pOldBrush); }
/***************************************************************************/
void CImgWnd::SetImg(IMG* pImg) { m_pNextImgWnd = pImg->m_pFirstImgWnd; pImg->m_pFirstImgWnd = this; m_pImg = pImg; }
/***************************************************************************/
CPalette* CImgWnd::SetImgPalette( CDC* pdc, BOOL bForce ) { CPalette* ppal = NULL;
// If we do not realize as a background brush when in-place, we can get
// an infinite recursion of the container and us trying to realize the
// palette
if (theApp.m_pwndInPlaceFrame) { bForce = TRUE; }
if (theApp.m_pPalette && theApp.m_pPalette->m_hObject) { ppal = pdc->SelectPalette( theApp.m_pPalette, bForce );
pdc->RealizePalette(); } return ppal; }
/***************************************************************************/
HPALETTE CImgWnd::SetImgPalette( HDC hdc, BOOL bForce ) { HPALETTE hpal = NULL;
// If we do not realize as a background brush when in-place, we can get
// an infinite recursion of the container and us trying to realize the
// palette
if (theApp.m_pwndInPlaceFrame) { bForce = TRUE; }
if (theApp.m_pPalette && theApp.m_pPalette->m_hObject) { hpal = ::SelectPalette( hdc, (HPALETTE)theApp.m_pPalette->m_hObject, bForce );
::RealizePalette( hdc ); } return hpal; }
/***************************************************************************/
void CImgWnd::SetZoom(int nZoom) { if (m_nZoom > 1) m_nZoomPrev = m_nZoom;
CommitSelection(TRUE);
if (nZoom > 1) { // deselect the text tool if it's around
CImgTool* pImgTool = CImgTool::GetCurrent();
if (pImgTool != NULL && CImgTool::GetCurrentID() == IDMX_TEXTTOOL) { CImgTool::Select(IDMB_PENCILTOOL); } }
HideBrush(); SetupRubber( m_pImg ); EraseTracker(); theImgBrush.m_pImg = NULL; DrawTracker();
CPBView* pView = (CPBView*)GetParent();
if (pView != NULL && pView->IsKindOf( RUNTIME_CLASS( CPBView ) )) if (nZoom == 1) pView->HideThumbNailView(); else pView->ShowThumbNailView();
Invalidate(FALSE);
m_nZoom = nZoom; }
/***************************************************************************/
void CImgWnd::SetScroll(int xPos, int yPos) { if (xPos > 0) xPos = 0; else if (xPos < -m_pImg->cxWidth) xPos = -m_pImg->cxWidth;
if (yPos > 0) yPos = 0; else if (yPos < -m_pImg->cyHeight) yPos = -m_pImg->cyHeight;
m_xScroll = xPos; m_yScroll = yPos;
Invalidate( FALSE );
CheckScrollBars(); }
/***************************************************************************/
void CImgWnd::CheckScrollBars() { // Tacky recursion blocker is required because this is called from
// the OnSize handler and turning scroll bars on or off changes
// the size of our window...
static BOOL bInHere = FALSE;
if (bInHere) return;
bInHere = TRUE;
int cxVScrollBar = GetSystemMetrics( SM_CXVSCROLL ); int cyHScrollBar = GetSystemMetrics( SM_CYHSCROLL );
// Figure the client area size if there were no scroll bars...
CRect clientRect;
GetClientRect( &clientRect );
int cxWidth = clientRect.Width(); int cyHeight = clientRect.Height();
BOOL hHasHBar = ((GetStyle() & WS_HSCROLL) != 0); BOOL bHasVBar = ((GetStyle() & WS_VSCROLL) != 0);
if (hHasHBar) cyHeight += cyHScrollBar;
if (bHasVBar) cxWidth += cxVScrollBar;
// Figure the size of the thing we are scrolling (the subject)...
CSize subjectSize;
GetImgSize( m_pImg, subjectSize );
int iTrackerSize = 2 * CTracker::HANDLE_SIZE;
subjectSize.cx = (subjectSize.cx * m_nZoom ) + iTrackerSize; subjectSize.cy = (subjectSize.cy * m_nZoom ) + iTrackerSize;
m_LineX = (subjectSize.cx + 31) / 32; m_LineY = (subjectSize.cy + 31) / 32;
// Nasty loop takes care of case where we only need a vertical
// scroll bar because we added a horizontal scroll bar and
// vice versa... (Will only ever loop twice.)
BOOL bNeedHBar = FALSE; BOOL bNeedVBar = FALSE; BOOL bChange;
do { bChange = FALSE;
if (! bNeedVBar && subjectSize.cy > cyHeight) { bChange = TRUE; bNeedVBar = TRUE; cxWidth -= cxVScrollBar; }
if (! bNeedHBar && subjectSize.cx > cxWidth) { bChange = TRUE; bNeedHBar = TRUE; cyHeight -= cyHScrollBar; } } while (bChange);
SetRedraw( FALSE );
SCROLLINFO si;
si.cbSize = sizeof( si ); si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; si.nMin = 0;
// We subtract 1 because subjectSize is the size we want, so the range
// should be 0 to subjectSize-1
si.nMax = (subjectSize.cx - 1) / m_nZoom; si.nPage = cxWidth / m_nZoom; si.nPos = -m_xScroll; SetScrollInfo( SB_HORZ, &si, FALSE );
si.nMax = (subjectSize.cy - 1) / m_nZoom; si.nPage = cyHeight / m_nZoom; si.nPos = -m_yScroll; SetScrollInfo( SB_VERT, &si, FALSE );
si.fMask = SIF_POS; GetScrollInfo( SB_HORZ, &si ); if ( -m_xScroll != si.nPos ) m_xScroll = -si.nPos ; GetScrollInfo( SB_VERT, &si ); if ( -m_yScroll != si.nPos ) m_yScroll = -si.nPos;
SetRedraw ( TRUE ); Invalidate( FALSE );
bInHere = FALSE; }
/***************************************************************************/
void CImgWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*) { OnScroll(FALSE, nSBCode, nPos); }
/***************************************************************************/
void CImgWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar*) { OnScroll(TRUE, nSBCode, nPos); }
/***************************************************************************/
void CImgWnd::OnScroll(BOOL bVert, UINT nSBCode, UINT nPos) { SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof( ScrollInfo ); ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
GetScrollInfo( (bVert? SB_VERT: SB_HORZ), &ScrollInfo ); int iScroll = ScrollInfo.nPage/4; int iNewPos = ScrollInfo.nPos;
switch (nSBCode) { case SB_TOP: iNewPos = 0; break;
case SB_BOTTOM: iNewPos = ScrollInfo.nMax; break;
case SB_LINEDOWN: iNewPos += iScroll; break;
case SB_LINEUP: iNewPos -= iScroll; break;
case SB_PAGEDOWN: iNewPos += iScroll * 4; break;
case SB_PAGEUP: iNewPos -= iScroll * 4; break;
case SB_THUMBPOSITION: case SB_THUMBTRACK: iNewPos = nPos; break; }
if (iNewPos < ScrollInfo.nMin) iNewPos = 0; else if (iNewPos > ScrollInfo.nMax-(int)ScrollInfo.nPage+1) iNewPos = ScrollInfo.nMax-(int)ScrollInfo.nPage+1;
iScroll = -(iNewPos - ScrollInfo.nPos); Invalidate(FALSE);
if (bVert) m_yScroll = -iNewPos; else m_xScroll = -iNewPos;
ScrollInfo.fMask = SIF_POS; ScrollInfo.nPos = iNewPos; SetScrollInfo( (bVert? SB_VERT: SB_HORZ), &ScrollInfo, TRUE ); }
/***************************************************************************/ BOOL CImgWnd::OnMouseWheel (UINT nFlags, short zDelta, CPoint pt) { //
// Don't handle zoom and datazoom.
//
if (nFlags & (MK_SHIFT | MK_CONTROL)) { return FALSE; }
int nBar; int *pScroll;
if (GetWindowLong(GetSafeHwnd(), GWL_STYLE) & WS_VSCROLL) { nBar = SB_VERT; pScroll = &m_yScroll; } else { nBar = SB_HORZ; pScroll = &m_xScroll; }
SCROLLINFO ScrollInfo;
ScrollInfo.cbSize = sizeof( ScrollInfo ); ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
GetScrollInfo( nBar, &ScrollInfo ); m_WheelDelta -= zDelta; if (abs(m_WheelDelta) >= WHEEL_DELTA) { int iScroll = ScrollInfo.nPage/4 * (m_WheelDelta/WHEEL_DELTA); int iNewPos = ScrollInfo.nPos + iScroll;
if (iNewPos < ScrollInfo.nMin) iNewPos = 0; else if (iNewPos > ScrollInfo.nMax-(int)ScrollInfo.nPage+1) iNewPos = ScrollInfo.nMax-(int)ScrollInfo.nPage+1;
Invalidate(FALSE);
*pScroll = -iNewPos;
ScrollInfo.fMask = SIF_POS; ScrollInfo.nPos = iNewPos; SetScrollInfo( nBar, &ScrollInfo, TRUE ); m_WheelDelta= m_WheelDelta % WHEEL_DELTA; CImgTool* pImgTool = CImgTool::GetCurrent(); mti.ptPrev = mti.pt; mti.pt = pt; pImgTool->OnMove (this, &mti); }
return TRUE; } /***************************************************************************/
void CImgWnd::PrepareForBrushChange(BOOL bPickup, BOOL bErase) { if (theImgBrush.m_pImg != NULL && theImgBrush.m_bFirstDrag) { if (bPickup) PickupSelection();
SetUndo(m_pImg);
theImgBrush.m_bLastDragWasFirst = TRUE; theImgBrush.m_bFirstDrag = FALSE; theImgBrush.m_rcDraggedFrom = rcDragBrush;
if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL) { HideBrush(); bErase = FALSE; }
if (bErase) { // Clear the background...
HideBrush();
FillImgRect( m_pImg->hDC, &theImgBrush.m_rcDraggedFrom, crRight );
CommitImgRect(m_pImg, &theImgBrush.m_rcDraggedFrom); InvalImgRect (m_pImg, &theImgBrush.m_rcDraggedFrom);
FinishUndo(theImgBrush.m_rcDraggedFrom);
MoveBrush(theImgBrush.m_rcSelection); } } }
/***************************************************************************/
void CImgWnd::OnCancelMode() { CmdCancel(); }
/***************************************************************************/
void CImgWnd::CmdCancel() { // This will:
// Erase the size indicator on the status bar.
// Reset the mouse cursor to an arrow.
// Release the capture.
// Cancel (and undo) any drawing operation in progress.
// Cancel the Pick Color command if it's active.
// If there's a selection, will set to whole image and select prev tool
ClearStatusBarSize();
mti.fLeft = mti.fRight = FALSE;
if (c_pResizeDragger != NULL) { EndResizeOperation(); bIgnoreMouse = TRUE; return; }
CImgTool* pImgTool = CImgTool::GetCurrent();
if (GetCapture() == this || pImgTool->IsMultPtOpInProgress()) { // Cancel dragging or multi-point operation in progress
BOOL bWasMakingSelection = theImgBrush.m_bMakingSelection;
ZoomedInDP(WM_CANCEL, 0, CPoint(0, 0));
SetCursor(LoadCursor(NULL, IDC_ARROW + 11));
if (! bWasMakingSelection) CancelPainting();
bIgnoreMouse = TRUE; } else if (pImgTool->IsToggle() || CImgTool::GetCurrentID() == IDMB_PICKTOOL || CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL || CImgTool::GetCurrentID() == IDMZ_BRUSHTOOL || CImgTool::GetCurrentID() == IDMB_POLYGONTOOL || CImgTool::GetCurrentID() == IDMX_TEXTTOOL) { pImgTool->OnCancel( this ); }
if (GetKeyState( VK_LBUTTON ) < 0 || GetKeyState( VK_RBUTTON) < 0 ) bIgnoreMouse = TRUE;
SetToolCursor(); }
/***************************************************************************/
void CImgWnd::CmdSel2Bsh() { if (! g_bCustomBrush) { if (theImgBrush.m_pImg == NULL) { // No selection, turn the whole image into a brush!
MakeBrush( m_pImg->hDC, CRect( 0, 0, m_pImg->cxWidth, m_pImg->cyHeight ) ); }
if (theImgBrush.m_bFirstDrag) { // Time to pick up the bits!
ASSERT(theImgBrush.m_pImg == m_pImg);
PickupSelection(); }
InvalImgRect(theImgBrush.m_pImg, NULL); // erase the selection tracker
CImgTool::Select(IDMZ_BRUSHTOOL); SetCombineMode(combineMatte);
g_bCustomBrush = TRUE;
theImgBrush.m_pImg = NULL; theImgBrush.CenterHandle(); } else if (CImgTool::GetCurrentID() == IDMZ_BRUSHTOOL) { CImgTool::GetCurrent()->OnCancel(this); } }
/***************************************************************************/ // Coordinate Translation and Calculation Functions
//
//
// Convert a point or rect in image view client coordinates to image
// coordinates taking magnification and scrolling into account.
//
void CImgWnd::ClientToImage(CPoint& point) { int iHandleSize = CTracker::HANDLE_SIZE;
point.x = (point.x - iHandleSize) / m_nZoom - m_xScroll; point.y = (point.y - iHandleSize) / m_nZoom - m_yScroll; }
/***************************************************************************/
void CImgWnd::ClientToImage(CRect& rect) { ClientToImage(rect.TopLeft()); ClientToImage(rect.BottomRight()); }
/***************************************************************************/ // Convert a point or rect in image coordinates to image view client
// coordinates taking magnification and scrolling into account.
//
void CImgWnd::ImageToClient(CPoint& point) { int iHandleSize = CTracker::HANDLE_SIZE;
point.x = (point.x + m_xScroll) * m_nZoom + iHandleSize; point.y = (point.y + m_yScroll) * m_nZoom + iHandleSize; }
/***************************************************************************/
void CImgWnd::ImageToClient(CRect& rect) { ImageToClient(rect.TopLeft()); ImageToClient(rect.BottomRight()); }
/***************************************************************************/ // Return a rectangle in image view coordinates surrounding the image
// taking magnification, scrolling, and the grid into account.
void CImgWnd::GetImageRect( CRect& imageRect ) { imageRect.SetRect( 0, 0, m_pImg->cxWidth, m_pImg->cyHeight );
ImageToClient( imageRect );
if (IsGridVisible()) { imageRect.right += 1; imageRect.bottom += 1; } }
/***************************************************************************/
CRect CImgWnd::GetDrawingRect( void ) { CRect rectImage; CRect rectClient;
GetImageRect ( rectImage ); GetClientRect( &rectClient );
rectImage &= rectClient; rectImage.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
return ( rectImage ); }
/***************************************************************************/
void CImgWnd::OnSetFocus(CWnd* pOldWnd) { if (m_pImg == NULL) { // Time to die... (Our img was deleted, so we'll be disappearing
// soon. Don't bother to do any of the rest of this function...
return; }
Invalidate(); BringWindowToTop(); // so updates happen here first
if (c_pImgWndCur != this && c_pImgWndCur != NULL) c_pImgWndCur->EraseTracker();
c_pImgWndCur = this;
SelectImg( m_pImg ); UpdateWindow();
CWnd::OnSetFocus( pOldWnd );
DrawTracker(); }
/***************************************************************************/
void CImgWnd::OnKillFocus(CWnd* pNewWnd) { Invalidate();
if (theImgBrush.m_pImg == NULL) HideBrush();
if (GetCapture() == this) CmdCancel();
CWnd::OnKillFocus(pNewWnd); }
/***************************************************************************/
void CImgWnd::OnSize(UINT nType, int cx, int cy) { CheckScrollBars();
CWnd::OnSize(nType, cx, cy); }
/***************************************************************************/
BOOL CImgWnd::OnMouseDown(UINT nFlags) { if (GetFocus() != this) { SetFocus(); SetActiveWindow(); }
if ((nFlags & (MK_LBUTTON | MK_RBUTTON)) == (MK_LBUTTON | MK_RBUTTON)) { ClearStatusBarSize();
BOOL bWasMakingSelection = theImgBrush.m_bMakingSelection;
ZoomedInDP(WM_CANCEL, 0, CPoint(0, 0));
SetCursor(LoadCursor(NULL, IDC_ARROW + 11));
if (! bWasMakingSelection) CancelPainting();
bIgnoreMouse = TRUE; return FALSE; }
return TRUE; }
/***************************************************************************/
BOOL CImgWnd::OnMouseMessage( UINT nFlags ) { if (bIgnoreMouse /*|| GetFocus() != this*/) { if ((nFlags & (MK_LBUTTON | MK_RBUTTON)) == 0) { bIgnoreMouse = FALSE; SetToolCursor(); } else { SetCursor( LoadCursor( NULL, IDC_ARROW ) ); }
return FALSE; }
if ((CImgTool::GetCurrentID() != IDMB_PICKTOOL) && (CImgTool::GetCurrentID() != IDMB_PICKRGNTOOL)) SetupRubber(m_pImg);
const MSG* pMsg = GetCurrentMessage(); mti.fCtrlDown = (nFlags & MK_CONTROL); ZoomedInDP( pMsg->message, (DWORD)pMsg->wParam, CPoint( (DWORD)pMsg->lParam ) );
return TRUE; }
/***************************************************************************/
void CImgWnd::OnLButtonDown( UINT nFlags, CPoint point ) { CWnd::OnLButtonDown( nFlags, point );
if (OnMouseDown( nFlags )) { OnMouseMessage( nFlags ); } }
/***************************************************************************/
void CImgWnd::OnLButtonDblClk(UINT nFlags, CPoint point) { CRect rect; GetImageRect(rect);
// When inside the image, a double click is the same as a single click
OnLButtonDown(nFlags, point); }
/***************************************************************************/
void CImgWnd::OnLButtonUp(UINT nFlags, CPoint point) { CWnd::OnLButtonUp(nFlags, point);
OnMouseMessage(nFlags); }
/***************************************************************************/
void CImgWnd::OnRButtonDown(UINT nFlags, CPoint point) { CWnd::OnRButtonDown(nFlags, point);
if (OnMouseDown(nFlags)) { OnMouseMessage(nFlags); } }
/***************************************************************************/
void CImgWnd::OnRButtonDblClk(UINT nFlags, CPoint point) { // A right button double click is the same as a right button single click
OnRButtonDown(nFlags, point); }
/***************************************************************************/
void CImgWnd::OnRButtonUp(UINT nFlags, CPoint point) { CWnd::OnRButtonUp(nFlags, point);
OnMouseMessage(nFlags); }
/***************************************************************************/
void CImgWnd::OnMouseMove(UINT nFlags, CPoint point) { CWnd::OnMouseMove(nFlags, point);
if (g_pMouseImgWnd != this && g_pMouseImgWnd != NULL) { CImgTool::GetCurrent()->OnLeave( g_pMouseImgWnd, &mti ); g_pMouseImgWnd = NULL; }
ClientToImage( point ); m_ptDispPos = point;
if (g_pMouseImgWnd == NULL) { MTI mtiEnter;
mtiEnter.pt = point; mtiEnter.ptDown = point; mtiEnter.ptPrev = point; mtiEnter.fLeft = FALSE; mtiEnter.fRight = FALSE; mtiEnter.fCtrlDown = FALSE;
CImgTool::GetCurrent()->OnEnter( g_pMouseImgWnd, &mtiEnter );
g_pMouseImgWnd = this; } OnMouseMessage( nFlags ); }
/***************************************************************************/
void CImgWnd::OnTimer(UINT nIDEvent) { OnMouseMessage( 0 ); }
/***************************************************************************/
void CImgWnd::SetToolCursor() { UINT nCursorID = CImgTool::GetCurrent()->GetCursorID(); HCURSOR hCursor = NULL;
if (nCursorID != 0) { hCursor = LoadCursor(nCursorID < 32512 ? AfxGetResourceHandle() : NULL, MAKEINTRESOURCE( nCursorID )); }
SetCursor(hCursor); }
/***************************************************************************/
void CImgWnd::EndResizeOperation() { ReleaseCapture(); delete c_pResizeDragger; c_pResizeDragger = NULL; c_dragState = CTracker::nil; ClearStatusBarSize(); }
/***************************************************************************/
void CImgWnd::ResizeMouseHandler(unsigned code, CPoint imagePt) { CRect imageRect = c_pResizeDragger->m_rect; ClientToImage(imageRect);
switch (code) { case WM_CANCEL: EndResizeOperation(); return;
case WM_LBUTTONUP: // resizing whole bitmap
if (m_pImg != theImgBrush.m_pImg && m_pwndThumbNailView) { m_pwndThumbNailView->Invalidate(); }
EndResizeOperation();
if (theImgBrush.m_pImg == NULL) { // User was resizing the whole image...
CPBView* pView = (CPBView*)((CFrameWnd*)AfxGetMainWnd())->GetActiveView(); CPBDoc* pDoc = (pView == NULL)? NULL: pView->GetDocument();
if (pDoc != NULL) { theUndo.BeginUndo( TEXT("Property Edit") );
if (GetKeyState( VK_SHIFT ) < 0) pDoc->m_pBitmapObj->SetIntProp( P_Shrink, 1 );
theApp.m_sizeBitmap = imageRect.Size();
pDoc->m_pBitmapObj->SetSizeProp( P_Size, theApp.m_sizeBitmap ); pDoc->m_pBitmapObj->SetIntProp ( P_Shrink, 0 );
theUndo.EndUndo(); } } else { // User was resizing the selection...
HideBrush(); theImgBrush.SetSize( imageRect.Size(), TRUE ); MoveBrush( imageRect ); } return;
case WM_MOUSEMOVE: switch (c_dragState) { default: ASSERT(FALSE);
case CTracker::resizingTop: imageRect.top = imagePt.y; if (imageRect.top >= imageRect.bottom) imageRect.top = imageRect.bottom - 1; break;
case CTracker::resizingLeft: imageRect.left = imagePt.x; if (imageRect.left >= imageRect.right) imageRect.left = imageRect.right - 1; break;
case CTracker::resizingRight: imageRect.right = imagePt.x; if (imageRect.right <= imageRect.left) imageRect.right = imageRect.left + 1; break;
case CTracker::resizingBottom: imageRect.bottom = imagePt.y; if (imageRect.bottom <= imageRect.top) imageRect.bottom = imageRect.top + 1; break;
case CTracker::resizingTopLeft: imageRect.left = imagePt.x; imageRect.top = imagePt.y; if (imageRect.top >= imageRect.bottom) imageRect.top = imageRect.bottom - 1; if (imageRect.left >= imageRect.right) imageRect.left = imageRect.right - 1; break;
case CTracker::resizingTopRight: imageRect.top = imagePt.y; imageRect.right = imagePt.x; if (imageRect.top >= imageRect.bottom) imageRect.top = imageRect.bottom - 1; if (imageRect.right <= imageRect.left) imageRect.right = imageRect.left + 1; break;
case CTracker::resizingBottomLeft: imageRect.left = imagePt.x; imageRect.bottom = imagePt.y; if (imageRect.left >= imageRect.right) imageRect.left = imageRect.right - 1; if (imageRect.bottom <= imageRect.top) imageRect.bottom = imageRect.top + 1; break;
case CTracker::resizingBottomRight: imageRect.right = imagePt.x; imageRect.bottom = imagePt.y; if (imageRect.right <= imageRect.left) imageRect.right = imageRect.left + 1; if (imageRect.bottom <= imageRect.top) imageRect.bottom = imageRect.top + 1; break; }
if (theImgBrush.m_pImg == NULL && m_pImg->m_bTileGrid) { // Snap to tile grid...
int cxTile = m_pImg->m_cxTile; if (cxTile != 1 && cxTile <= m_pImg->cxWidth) { imageRect.right = ((imageRect.right + cxTile / 2) / cxTile) * cxTile; }
int cyTile = m_pImg->m_cyTile; if (cyTile != 1 && cyTile <= m_pImg->cyHeight) { imageRect.bottom = ((imageRect.bottom + cyTile / 2) / cyTile) * cyTile; } }
SetStatusBarSize(imageRect.Size());
ImageToClient(imageRect);
c_pResizeDragger->Move(imageRect, TRUE); break; } }
/***************************************************************************/
void CImgWnd::StartSelectionDrag(unsigned code, CPoint newPt) { theImgBrush.CopyTo(theBackupBrush);
newPt.x /= m_nZoom; newPt.y /= m_nZoom;
mti.pt = mti.ptDown = mti.ptPrev = newPt;
SetCapture(); SetCombineMode(theImgBrush.m_bOpaque ? combineReplace : combineMatte);
if (theImgBrush.m_bFirstDrag) { ASSERT(theImgBrush.m_pImg == m_pImg);
PickupSelection(); } else if (! theImgBrush.m_bOpaque) theImgBrush.RecalcMask( crRight );
theImgBrush.TopLeftHandle(); theImgBrush.m_dragOffset = mti.pt - theImgBrush.m_rcSelection.TopLeft();
EraseTracker();
if (GetKeyState(VK_CONTROL) < 0) { // Copy the selection and start moving...
if (theImgBrush.m_bFirstDrag) { // The first time, the bits are already in
// the bitmap, so just copy them to the
// selection (which has already been done).
theImgBrush.m_bFirstDrag = FALSE; theImgBrush.m_bLastDragWasFirst = TRUE; } else { CommitSelection(TRUE); }
theImgBrush.m_bMoveSel = TRUE; } else if (GetKeyState(VK_SHIFT) < 0) { // Start a smear operation...
HideBrush();
if (theImgBrush.m_bLastDragWasFirst) CommitSelection(TRUE);
SetUndo(m_pImg); theImgBrush.m_bSmearSel = TRUE; theImgBrush.m_bFirstDrag = FALSE; theImgBrush.m_bLastDragWasFirst = TRUE; } else { // Start a move operation...
theImgBrush.m_bMoveSel = TRUE; }
g_bCustomBrush = TRUE; }
/***************************************************************************/
void CImgWnd::CancelSelectionDrag() { if (!theImgBrush.m_bSmearSel && !theImgBrush.m_bMoveSel) { TRACE(TEXT("Extraneous CancelSelectionDrag!\n")); return; }
ReleaseCapture();
theImgBrush.m_rcSelection = theImgBrush.m_rcDraggedFrom;
theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE; g_bCustomBrush = FALSE; SetCombineMode(combineColor);
theBackupBrush.CopyTo(theImgBrush); rcDragBrush = theImgBrush.m_rcSelection; rcDragBrush.right += 1; rcDragBrush.bottom += 1;
CancelPainting();
InvalImgRect(theImgBrush.m_pImg, NULL); // draw selection tracker
// "Opaque" mode may have changed...
if ((CImgTool::GetCurrentID() == IDMB_PICKTOOL) || (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)) g_pImgToolWnd->InvalidateOptions(FALSE);
// Cancel all the way now...
theImgBrush.m_pImg = NULL; }
/***************************************************************************/
void CImgWnd::SelectionDragHandler(unsigned code, CPoint newPt) { switch (code) { case WM_CANCEL: CancelSelectionDrag(); break;
case WM_MOUSEMOVE: if (theImgBrush.m_bMoveSel) PrepareForBrushChange(FALSE);
mti.ptPrev = mti.pt; mti.pt = newPt;
theImgBrush.m_rcSelection.OffsetRect( -theImgBrush.m_rcSelection.TopLeft() + (CSize)mti.pt - theImgBrush.m_dragOffset);
// Make sure the selection stays at least along the edge
// of the actual image so we don't lose the tracker...
if (theImgBrush.m_rcSelection.left > m_pImg->cxWidth) theImgBrush.m_rcSelection.OffsetRect(-theImgBrush.m_rcSelection.left + m_pImg->cxWidth, 0); if (theImgBrush.m_rcSelection.top > m_pImg->cyHeight) theImgBrush.m_rcSelection.OffsetRect(0, -theImgBrush.m_rcSelection.top + m_pImg->cyHeight); if (theImgBrush.m_rcSelection.right < 0) theImgBrush.m_rcSelection.OffsetRect(-theImgBrush.m_rcSelection.right, 0); if (theImgBrush.m_rcSelection.bottom < 0) theImgBrush.m_rcSelection.OffsetRect(0, -theImgBrush.m_rcSelection.bottom);
if (theImgBrush.m_bSmearSel) DrawBrush(m_pImg, theImgBrush.m_rcSelection.TopLeft(), TRUE); else ShowBrush(theImgBrush.m_rcSelection.TopLeft()); break;
case WM_LBUTTONUP: theImgBrush.m_bLastDragWasASmear = theImgBrush.m_bSmearSel;
if (theImgBrush.m_bSmearSel) { IMG* pImg = m_pImg;
CommitSelection(FALSE);
FinishUndo(CRect(0, 0, pImg->cxWidth, pImg->cyHeight)); } ReleaseCapture();
theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE;
g_bCustomBrush = FALSE; SetCombineMode(combineColor);
InvalImgRect(theImgBrush.m_pImg, NULL); // draw selection tracker
break; } }
/******************************************************************************/
BOOL CImgWnd::PtInTracker( CPoint cptLocation ) { CRect selRect = theImgBrush.m_rcSelection; BOOL bPtInTracker = FALSE;
selRect.left *= m_nZoom; selRect.top *= m_nZoom; selRect.right *= m_nZoom; selRect.bottom *= m_nZoom;
selRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
bPtInTracker = selRect.PtInRect( cptLocation );
return bPtInTracker; }
/******************************************************************************/
void CImgWnd::OnRButtonDownInSel(CPoint *pcPointDown) { CMenu cMenuPopup; BOOL bRC = cMenuPopup.LoadMenu(IDR_SELECTION_POPUP);
ASSERT(bRC); if (bRC) { CMenu *pcContextMenu = cMenuPopup.GetSubMenu(0); ASSERT(pcContextMenu != NULL); if (pcContextMenu != NULL) { CPoint cPointDown = *pcPointDown; ImageToClient(cPointDown); ClientToScreen(&cPointDown);
CRect cRectClient; GetClientRect(&cRectClient); ClientToScreen(&cRectClient);
// the frame actually has a clue about what items to enable...
CWnd *notify = GetParentFrame();
if (!notify) notify = GetParent(); // oh well...
pcContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cPointDown.x, cPointDown.y, notify, &cRectClient); } } }
/***************************************************************************/
void CImgWnd::ZoomedInDP(unsigned code, unsigned mouseKeys, CPoint newPt) { CPoint clientPt = newPt; CPoint imagePt = clientPt;
ClientToImage( imagePt );
if (c_pResizeDragger != NULL) { ResizeMouseHandler( code, imagePt ); return; }
int iHandleSize = CTracker::HANDLE_SIZE;
newPt.x -= iHandleSize + m_xScroll * m_nZoom; newPt.y -= iHandleSize + m_yScroll * m_nZoom;
// AdjustPointForGrid(&newPt);
IMG* pImg = m_pImg;
int cxImage = pImg->cxWidth; int cyImage = pImg->cyHeight;
CRect imageRect;
GetImageRect( imageRect );
// Check for selection manipulations...
if (GetCapture() != this && c_pImgWndCur == this && theImgBrush.m_pImg == m_pImg) { CRect selRect = theImgBrush.m_rcSelection; BOOL bPtInTracker = FALSE;
selRect.left *= m_nZoom; selRect.top *= m_nZoom; selRect.right *= m_nZoom; selRect.bottom *= m_nZoom;
selRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
bPtInTracker = PtInTracker(newPt);
if (bPtInTracker) { // Mouse is within the outer border of the tracker...
// We don't set the rubber for every mouse message when the
// selection tool is active, but we'd better set it up now!
if (pRubberImg != m_pImg) SetupRubber(m_pImg);
ClearStatusBarPosition();
CTracker::STATE state;
selRect.InflateRect( -CTracker::HANDLE_SIZE, -CTracker::HANDLE_SIZE );
state = CTracker::HitTest(selRect, newPt, CTracker::nil);
if (bPtInTracker && state == CTracker::nil) { // Actually inside the selection...
SetCursor(theApp.LoadCursor(IDCUR_MOVE));
if (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK) { StartSelectionDrag(code, newPt); } else { if (code == WM_RBUTTONDOWN || code == WM_RBUTTONDBLCLK) // some of the menu commands don't work for free form selections
OnRButtonDownInSel( &imagePt ); } } else { // In the tracker frame...
SetCursor(HCursorFromTrackerState(state));
if (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK) { // Start a resize operation...
SetCapture(); PrepareForBrushChange();
ASSERT(c_pResizeDragger == NULL); CRect rect = theImgBrush.m_rcSelection; ImageToClient(rect);
c_pResizeDragger = new CDragger(this, &rect); ASSERT(c_pResizeDragger != NULL); c_dragState = state; } }
return; } }
if (! imageRect.PtInRect( clientPt ) && code != WM_CANCEL && GetCapture() == NULL) { // The mouse is not inside the image and we're not in any
// special mode, so hide the brush...
if (g_pDragBrushWnd == this && theImgBrush.m_pImg == NULL) HideBrush();
CRect selRect = imageRect;
selRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
if (theImgBrush.m_pImg != NULL || ! selRect.PtInRect( clientPt )) { // The mouse is not in the whole image tracker
if (WM_LBUTTONDOWN == code) { if (CImgTool::GetCurrentID() != IDMX_TEXTTOOL) { CmdCancel (); }
} else { SetCursor( LoadCursor(NULL, IDC_ARROW )); }
return; }
// The mouse is in the whole image tracker, so set the cursor
// as appropriate
CTracker::STATE state = CTracker::nil;
if (c_pImgWndCur == this) state = CTracker::HitTest(imageRect, clientPt, CTracker::nil);
switch (state) { case CTracker::resizingTop: case CTracker::resizingLeft: case CTracker::resizingTopLeft: case CTracker::resizingTopRight: case CTracker::resizingBottomLeft: state = CTracker::nil; break; }
SetCursor( HCursorFromTrackerState( state ) );
// Handle mouse messages for tracker...
if (state != CTracker::nil && (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK)) { SetCapture();
ASSERT( c_pResizeDragger == NULL );
c_pResizeDragger = new CDragger( this, &imageRect );
ASSERT( c_pResizeDragger != NULL );
c_dragState = state; }
return; }
newPt.x /= m_nZoom; newPt.y /= m_nZoom;
if (! CImgTool::IsDragging()) SetStatusBarPosition( m_ptDispPos );
// Moving the selection??
if (theImgBrush.m_bMoveSel || theImgBrush.m_bSmearSel) { SelectionDragHandler( code, newPt );
return; }
AdjustPointForGrid( &newPt );
// Dispatch the event off to the current tool...
CImgTool* pImgTool = CImgTool::GetCurrent();
switch (code) { case WM_CANCEL: ReleaseCapture(); pImgTool->OnCancel(this); mti.fLeft = mti.fRight = FALSE; break;
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: // We don't set the rubber for every mouse message when the
// selection tool is active, but we'd better set it up now!
if (pRubberImg != m_pImg) SetupRubber( m_pImg );
mti.fLeft = (code == WM_LBUTTONDOWN || code == WM_LBUTTONDBLCLK); mti.fRight = (code == WM_RBUTTONDOWN || code == WM_RBUTTONDBLCLK);
mti.pt = mti.ptDown = mti.ptPrev = newPt;
// if in the polygon tool, double clicks will end operation
if (CImgTool::GetCurrentID() == IDMB_POLYGONTOOL && ((code == WM_LBUTTONDBLCLK) || (code == WM_RBUTTONDBLCLK))) { mti.ptPrev = mti.pt; mti.pt = newPt;
pImgTool->EndMultiptOperation(); // end the multipt operation
pImgTool->OnEndDrag( this, &mti );
mti.fLeft = FALSE; mti.fRight = FALSE;
break; }
SetCapture();
if (CImgTool::GetCurrentID() != IDMB_PICKRGNTOOL) HideBrush();
if (pImgTool->IsUndoable()) SetUndo(m_pImg);
pImgTool->OnStartDrag( this, &mti ); break;
case WM_LBUTTONUP: case WM_RBUTTONUP: mti.ptPrev = mti.pt; mti.pt = newPt;
if (GetCapture() != this) break;
ReleaseCapture();
pImgTool->CanEndMultiptOperation( &mti ); pImgTool->OnEndDrag( this, &mti );
if (code == WM_LBUTTONUP) { mti.fLeft = FALSE; } if (code == WM_RBUTTONUP) { mti.fRight = FALSE; } break;
case WM_MOUSEMOVE: mti.ptPrev = mti.pt; mti.pt = newPt;
if (mti.fLeft || mti.fRight) pImgTool->OnDrag(this, &mti); else pImgTool->OnMove(this, &mti); break;
case WM_TIMER: pImgTool->OnTimer( this, &mti ); break; }
UpdateWindow(); // For immediate feedback in active window
SetToolCursor(); }
/***************************************************************************/
void CImgWnd::FinishUndo(const CRect& rectUndo) { if ( EnsureUndoSize(m_pImg) ) m_pImg->m_pBitmapObj->FinishUndo(&rectUndo); else { TRACE(TEXT("Problem: Can NOT ensure undo capability!\n")); MessageBeep(0); } }
/***************************************************************************/
void CImgWnd::CancelPainting() { if (g_hUndoImgBitmap == NULL) return; // nothing to cancel!
IMG* pimg; HDC hTempDC; HBITMAP hOldBM; HPALETTE hOldPalette = NULL;
pimg = m_pImg;
if ((hTempDC = CreateCompatibleDC( pimg->hDC )) == NULL) { TRACE(TEXT("Not enough memory to undo!\n")); MessageBeep(0); return; }
HideBrush();
if (g_hUndoPalette) { if (pimg->m_hPalOld) { ::SelectPalette( pimg->hDC, pimg->m_hPalOld, FALSE ); pimg->m_hPalOld = NULL; }
if (pimg->m_pPalette) pimg->m_pPalette->DeleteObject();
pimg->m_pPalette->Attach( g_hUndoPalette ); g_hUndoPalette = NULL;
pimg->m_hPalOld = ::SelectPalette( pimg->hDC, (HPALETTE)pimg->m_pPalette->GetSafeHandle(), FALSE ); ::RealizePalette( pimg->hDC ); }
hOldBM = (HBITMAP)SelectObject( hTempDC, g_hUndoImgBitmap );
if (pimg->m_pPalette) { hOldPalette = ::SelectPalette( hTempDC, (HPALETTE)pimg->m_pPalette->GetSafeHandle(), FALSE ); ::RealizePalette( hTempDC ); }
ASSERT( hOldBM != NULL );
BitBlt( pimg->hDC, 0, 0, pimg->cxWidth, pimg->cyHeight, hTempDC, 0, 0, SRCCOPY );
if (hOldPalette != NULL) ::SelectPalette( hTempDC, hOldPalette, FALSE );
SelectObject( hTempDC, hOldBM ); DeleteDC ( hTempDC );
InvalImgRect ( m_pImg, NULL ); CommitImgRect( m_pImg, NULL ); }
#ifdef GRIDOPTIONS
/***************************************************************************/
void CImgWnd::CmdGridOptions() { CImgGridDlg dlg;
dlg.m_bPixelGrid = theApp.m_bShowGrid; dlg.m_bTileGrid = m_pImg->m_bTileGrid; dlg.m_nWidth = m_pImg->m_cxTile; dlg.m_nHeight = m_pImg->m_cyTile;
if (dlg.DoModal() != IDOK) return;
// Hide the current is dependant on the state of the grid...
BOOL bOldShowGrid = theApp.m_bShowGrid; theApp.m_bShowGrid = dlg.m_bPixelGrid; m_pImg->m_bTileGrid = dlg.m_bTileGrid; m_pImg->m_cxTile = dlg.m_nWidth; m_pImg->m_cyTile = dlg.m_nHeight;
InvalImgRect(m_pImg, NULL);
if (bOldShowGrid != theApp.m_bShowGrid) { if (c_pImgWndCur != NULL) c_pImgWndCur->Invalidate(FALSE); // Redraw tracker
} } #endif // GRIDOPTIONS
/***************************************************************************/
void CImgWnd::CmdShowGrid() { // Hide the current cross hair since the width of the lines
// is dependant on the state of the grid...
theApp.m_bShowGrid = ! theApp.m_bShowGrid;
InvalImgRect(m_pImg, NULL);
if (c_pImgWndCur != NULL) c_pImgWndCur->Invalidate(FALSE); // Redraw tracker
}
/***************************************************************************/ // Draw a grid over the image already in the bitmap in pDC. Drawing
// is optimized by restricting it to destRect.
//
void CImgWnd::DrawGrid(CDC* pDC, const CRect& srcRect, CRect& destRect) { ASSERT(pDC != NULL); ASSERT(m_pImg != NULL);
pDC->SetTextColor(RGB(192, 192, 192)); pDC->SetBkColor(RGB(128, 128, 128));
CBrush* pOldBrush = pDC->SelectObject(GetHalftoneBrush());
CRect gridRect(0, 0, m_pImg->cxWidth * m_nZoom + 1, m_pImg->cyHeight * m_nZoom + 1);
for (int x = gridRect.left; x <= gridRect.right; x += m_nZoom) pDC->PatBlt(x, gridRect.top, 1, gridRect.Height(), PATCOPY);
for (int y = gridRect.top; y <= gridRect.bottom; y += m_nZoom) pDC->PatBlt(gridRect.left, y, gridRect.Width(), 1, PATCOPY);
if (m_pImg->m_bTileGrid) { pDC->SetTextColor(RGB(0, 0, 255)); pDC->SetBkColor(RGB(0, 0, 128));
int nWidth = destRect.Width(); int nHeight = destRect.Height(); int nStep;
if (m_pImg->m_cxTile > 1 && m_pImg->m_cxTile <= m_pImg->cxWidth) { nStep = m_nZoom * m_pImg->m_cxTile; for (x = (m_pImg->m_cxTile - srcRect.left % m_pImg->m_cxTile - m_pImg->m_cxTile) * m_nZoom; x <= nWidth; x += nStep) { pDC->PatBlt(x, 0, 1, nHeight, PATCOPY); } }
if (m_pImg->m_cyTile > 1 && m_pImg->m_cyTile <= m_pImg->cyHeight) { nStep = m_nZoom * m_pImg->m_cyTile; for (y = (m_pImg->m_cyTile - srcRect.top % m_pImg->m_cyTile - m_pImg->m_cyTile) * m_nZoom; y <= nHeight; y += nStep) { pDC->PatBlt(0, y, nWidth, 1, PATCOPY); } } }
pDC->SelectObject(pOldBrush);
destRect.right += 1; destRect.bottom += 1; }
#ifdef GRIDOPTIONS
/***************************************************************************/
void CImgWnd::CmdShowTileGrid() { extern BOOL g_bDefaultTileGrid; // If neither grid is visible, show both. Otherwise leave the pixel
// grid alone and toggle the tile grid.
if (! theApp.m_bShowGrid) { m_pImg->m_bTileGrid = TRUE; theApp.m_bShowGrid = TRUE; } else { m_pImg->m_bTileGrid = !m_pImg->m_bTileGrid; }
g_bDefaultTileGrid = m_pImg->m_bTileGrid;
InvalImgRect(m_pImg, NULL);
if (c_pImgWndCur != NULL) c_pImgWndCur->Invalidate(FALSE); // Redraw tracker
} #endif // GRIDOPTIONS
/***************************************************************************/
void CImgWnd::MoveBrush( const CRect& newSelRect ) { if (! theImgBrush.m_pImg) return;
theImgBrush.m_rcSelection = newSelRect; InvalImgRect( theImgBrush.m_pImg, NULL );
theImgBrush.m_handle.cx = theImgBrush.m_handle.cy = 0;
BOOL bOldCustomBrush = g_bCustomBrush;
g_bCustomBrush = TRUE;
int wOldCombineMode = wCombineMode;
SetCombineMode( theImgBrush.m_bOpaque ? combineReplace : combineMatte ); ShowBrush( theImgBrush.m_rcSelection.TopLeft() );
g_bCustomBrush = bOldCustomBrush;
SetCombineMode( wOldCombineMode ); }
/***************************************************************************/
BOOL CImgWnd::MakeBrush( HDC hSourceDC, CRect rcSource ) { int cxWidth; int cyHeight; int iToolID = CImgTool::GetCurrentID();
if (rcSource.IsRectEmpty()) { ASSERT( FALSE );
return FALSE; }
theImgBrush.m_size = rcSource.Size();
cxWidth = theImgBrush.m_size.cx; cyHeight = theImgBrush.m_size.cy;
if (theImgBrush.m_hbmOld) ::SelectObject( theImgBrush.m_dc.m_hDC, theImgBrush.m_hbmOld );
if (theImgBrush.m_hbmMaskOld) ::SelectObject( theImgBrush.m_dc.m_hDC, theImgBrush.m_hbmMaskOld );
theImgBrush.m_hbmOld = NULL; theImgBrush.m_hbmMaskOld = NULL;
theImgBrush.m_dc.DeleteDC(); theImgBrush.m_bitmap.DeleteObject(); theImgBrush.m_maskDC.DeleteDC(); theImgBrush.m_maskBitmap.DeleteObject();
CDC* pdcSource = CDC::FromHandle( hSourceDC ); CDC* pdcBitmap = CDC::FromHandle( m_pImg->hDC );
if (! theImgBrush.m_bitmap.CreateCompatibleBitmap( pdcBitmap, cxWidth, cyHeight ) || ! theImgBrush.m_dc.CreateCompatibleDC ( pdcBitmap ) || ! theImgBrush.m_maskBitmap.CreateBitmap ( cxWidth, cyHeight, 1, 1, NULL) || ! theImgBrush.m_maskDC.CreateCompatibleDC ( pdcBitmap )) { theApp.SetGdiEmergency(); return FALSE; }
theImgBrush.m_pImg = m_pImg; theImgBrush.m_hbmOld = (HBITMAP)((theImgBrush.m_dc.SelectObject( &theImgBrush.m_bitmap ))->GetSafeHandle()); theImgBrush.m_hbmMaskOld = (HBITMAP)((theImgBrush.m_maskDC.SelectObject( &theImgBrush.m_maskBitmap ))->GetSafeHandle());
CPalette* pcOldPalette = SetImgPalette( &theImgBrush.m_dc, FALSE );
if (iToolID == IDMB_PICKRGNTOOL) { // Using StretchBlt to ensure palette mapping occurs
TRY { CBrush cBrushWhite( PALETTERGB( 0xff, 0xff, 0xff ) ); CRect cRectTmp( 0, 0, cxWidth, cyHeight );
theImgBrush.m_dc.FillRect( &cRectTmp, &cBrushWhite ); } CATCH(CResourceException, e) { theApp.SetGdiEmergency(); return FALSE; } END_CATCH
if (theImgBrush.m_cRgnPolyFreeHandSel.GetSafeHandle()) theImgBrush.m_dc.FillRgn( &theImgBrush.m_cRgnPolyFreeHandSel, CBrush::FromHandle( (HBRUSH)::GetStockObject( BLACK_BRUSH ) ) );
theImgBrush.m_dc.StretchBlt( 0, 0, cxWidth, cyHeight, pdcSource, rcSource.left, rcSource.top, cxWidth, cyHeight, SRCERASE); } else { // Using StretchBlt to ensure palette mapping occurs
theImgBrush.m_dc.StretchBlt( 0, 0, cxWidth, cyHeight, pdcSource, rcSource.left, rcSource.top, cxWidth, cyHeight, SRCCOPY ); }
theImgBrush.RecalcMask( crRight );
if (pcOldPalette) theImgBrush.m_dc.SelectPalette( pcOldPalette, FALSE );
theImgBrush.m_rcSelection = rcSource;
rcSource.right += 1; rcSource.bottom += 1;
InvalImgRect( m_pImg, NULL ); // Redraw selection tracker
rcDragBrush = rcSource; g_bBrushVisible = TRUE; g_pDragBrushWnd = this;
theImgBrush.m_bFirstDrag = TRUE; theImgBrush.m_bLastDragWasFirst = FALSE;
return TRUE; }
/***************************************************************************/
void CImgWnd::CmdClear() { if (TextToolProcessed( ID_EDIT_CLEAR )) return;
HPALETTE hOldPalette = NULL; HBRUSH hNewBrush, hOldBrush; IMG* pImg = m_pImg;
if ((hNewBrush = CreateSolidBrush( crRight )) == NULL) { theApp.SetGdiEmergency(); return; }
HideBrush();
CRect clearRect;
if (theImgBrush.m_pImg == NULL) clearRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight); else { clearRect = rcDragBrush; clearRect.right -= 1; clearRect.bottom -= 1; }
BOOL bUndo = FALSE;
if (!theImgBrush.m_pImg || theImgBrush.m_bFirstDrag || theImgBrush.m_bCuttingFromImage) { bUndo = TRUE; SetUndo(m_pImg);
if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL) { int iPoints; CPoint* pptArray; BOOL bData = ((CFreehandSelectTool*)CImgTool::GetCurrent())->CopyPointsToMemArray( &pptArray, &iPoints ); if (bData && iPoints) {
HRGN hrgn = ::CreatePolygonRgn( pptArray, iPoints, ALTERNATE );
if (hrgn) ::FillRgn( pImg->hDC, hrgn, hNewBrush );
delete [] pptArray; } else { DeleteObject ( hNewBrush ); theApp.SetMemoryEmergency(); return; } } else { hOldBrush = (HBRUSH)SelectObject(pImg->hDC, hNewBrush);
PatBlt( pImg->hDC, clearRect.left, clearRect.top, clearRect.Width(), clearRect.Height(), PATCOPY ); SelectObject( pImg->hDC, hOldBrush ); } }
InvalImgRect ( m_pImg, &clearRect ); CommitImgRect( m_pImg, &clearRect );
if (bUndo) FinishUndo(clearRect);
DirtyImg ( m_pImg ); DeleteObject ( hNewBrush );
// If we have a selection, nuke it since it's useless now...
if (theImgBrush.m_pImg != NULL) { if (theImgBrush.m_bLastDragWasFirst) { theImgBrush.m_bLastDragWasFirst = FALSE; FinishUndo(theImgBrush.m_rcDraggedFrom); }
theImgBrush.m_handle.cx = 0; theImgBrush.m_handle.cy = 0; theImgBrush.m_bMoveSel = theImgBrush.m_bSmearSel = FALSE; g_bCustomBrush = FALSE; SetCombineMode(combineColor);
InvalImgRect(theImgBrush.m_pImg, NULL); // redraw selection
theImgBrush.m_pImg = NULL; } }
/***************************************************************************/
void CImgWnd::CmdFlipBshH() { IMG* pImg = m_pImg;
HideBrush();
CRect flipRect;
if (theImgBrush.m_pImg == NULL && !g_bCustomBrush) { flipRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight); } else { flipRect = rcDragBrush; flipRect.right -= 1; flipRect.bottom -= 1; }
if ( theImgBrush.m_pImg != NULL && ! theImgBrush.m_bFirstDrag || g_bCustomBrush) { CPalette* ppal = SetImgPalette( &theImgBrush.m_dc, FALSE ); //
// Don't do halftone blts when just moving bits around
//
theImgBrush.m_dc.SetStretchBltMode (COLORONCOLOR);
StretchCopy(theImgBrush.m_dc.m_hDC, 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy, theImgBrush.m_dc.m_hDC, theImgBrush.m_size.cx - 1, 0, -theImgBrush.m_size.cx, theImgBrush.m_size.cy);
StretchCopy(theImgBrush.m_maskDC.m_hDC, 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy, theImgBrush.m_maskDC.m_hDC, theImgBrush.m_size.cx - 1, 0, -theImgBrush.m_size.cx, theImgBrush.m_size.cy);
if (ppal) theImgBrush.m_dc.SelectPalette( ppal, FALSE ); // Background ??
MoveBrush(theImgBrush.m_rcSelection); } else { SetUndo(m_pImg); SetStretchBltMode (pImg->hDC, COLORONCOLOR); StretchCopy(pImg->hDC, flipRect.left, flipRect.top, flipRect.Width(), flipRect.Height(), pImg->hDC, flipRect.left + flipRect.Width() - 1, flipRect.top, -flipRect.Width(), flipRect.Height());
InvalImgRect (m_pImg, &flipRect); CommitImgRect(m_pImg, &flipRect); FinishUndo (flipRect); DirtyImg (m_pImg); } }
/***************************************************************************/
void CImgWnd::CmdFlipBshV() { IMG* pImg = m_pImg;
HideBrush();
CRect flipRect;
if (theImgBrush.m_pImg == NULL && !g_bCustomBrush) { flipRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight); } else { flipRect = rcDragBrush; flipRect.right -= 1; flipRect.bottom -= 1; }
if ( theImgBrush.m_pImg != NULL && ! theImgBrush.m_bFirstDrag || g_bCustomBrush) { CPalette* ppal = SetImgPalette( &theImgBrush.m_dc, FALSE ); // Background ??
theImgBrush.m_dc.SetStretchBltMode (COLORONCOLOR); StretchCopy(theImgBrush.m_dc.m_hDC, 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy, theImgBrush.m_dc.m_hDC, 0, theImgBrush.m_size.cy - 1, theImgBrush.m_size.cx, -theImgBrush.m_size.cy);
StretchCopy(theImgBrush.m_maskDC.m_hDC, 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy, theImgBrush.m_maskDC.m_hDC, 0, theImgBrush.m_size.cy - 1, theImgBrush.m_size.cx, -theImgBrush.m_size.cy);
if (ppal) theImgBrush.m_dc.SelectPalette( ppal, FALSE ); // Background ??
MoveBrush(theImgBrush.m_rcSelection); } else { SetUndo(m_pImg); SetStretchBltMode (pImg->hDC, COLORONCOLOR); StretchCopy(pImg->hDC, flipRect.left, flipRect.top, flipRect.Width(), flipRect.Height(), pImg->hDC, flipRect.left, flipRect.top + flipRect.Height() - 1, flipRect.Width(), -flipRect.Height());
InvalImgRect (m_pImg, &flipRect); CommitImgRect(m_pImg, &flipRect); FinishUndo (flipRect); DirtyImg (m_pImg); } }
/***************************************************************************/
void CImgWnd::CmdDoubleBsh() { if (!g_bCustomBrush && theImgBrush.m_pImg == NULL) { MessageBeep(0); return; }
PrepareForBrushChange(TRUE, FALSE);
CRect rc = theImgBrush.m_rcSelection; rc.left -= theImgBrush.m_size.cx / 2; rc.right = rc.left + theImgBrush.m_size.cx * 2; rc.top -= theImgBrush.m_size.cy / 2; rc.bottom = rc.top + theImgBrush.m_size.cy * 2;
HideBrush();
theImgBrush.SetSize( CSize( theImgBrush.m_size.cx * 2, theImgBrush.m_size.cy * 2 ) ); MoveBrush(rc);
if (g_bCustomBrush) theImgBrush.CenterHandle(); }
/***************************************************************************/
void CImgWnd::CmdHalfBsh() { if (! g_bCustomBrush && ! theImgBrush.m_pImg) { MessageBeep(0); return; }
PrepareForBrushChange( TRUE, FALSE );
CRect rc = theImgBrush.m_rcSelection; rc.left += theImgBrush.m_size.cx / 4; rc.right = rc.left + (theImgBrush.m_size.cx + 1) / 2; rc.top += theImgBrush.m_size.cy / 4; rc.bottom = rc.top + (theImgBrush.m_size.cy + 1) / 2;
HideBrush();
theImgBrush.SetSize( CSize( (theImgBrush.m_size.cx + 1) / 2, (theImgBrush.m_size.cy + 1) / 2 ) ); MoveBrush( rc );
if (g_bCustomBrush) theImgBrush.CenterHandle(); }
/***************************************************************************/
CPalette* CImgWnd::FixupDibPalette( LPSTR lpDib, CPalette* ppalDib ) { CPBView* pView = (CPBView*)GetParent(); CPBDoc* pDoc = pView->GetDocument();
if (pDoc == NULL || lpDib == NULL || ppalDib == NULL || pDoc->m_pBitmapObj->m_pImg == NULL) return ppalDib;
IMG* pImg = pDoc->m_pBitmapObj->m_pImg; int iColorBits = pImg->cBitCount * pImg->cPlanes; BOOL bFixupDib = TRUE; BOOL bSwapPalette = TRUE;
// only if dealing with palettes
if (iColorBits != 8) return ppalDib;
CPalette* ppalPic = theApp.m_pPalette; CPalette* ppalNew = NULL; BOOL bMergedPalette = FALSE;
if (ppalPic) { int iAdds;
if ( ppalNew = MergePalettes( ppalPic, ppalDib, iAdds ) ) bMergedPalette = TRUE;
if (ppalNew) { if (! iAdds) { bSwapPalette = FALSE; if ( bMergedPalette ) { delete ppalNew; ppalNew = FALSE; bMergedPalette = FALSE; } ppalNew = ppalPic; } } else { bSwapPalette = FALSE; if ( bMergedPalette ) { delete ppalNew; ppalNew = FALSE; bMergedPalette = FALSE; } ppalNew = ppalPic; } } else { if ( bMergedPalette ) { delete ppalNew; ppalNew = FALSE; bMergedPalette = FALSE; } ppalNew = ppalDib; bFixupDib = FALSE; }
if (bFixupDib) { LOGPALETTE256 palette; COLORREF crCurColor; UINT uColorIndex; int iDibColors = DIBNumColors( lpDib ); BOOL bWinStyleDIB = IS_WIN30_DIB( lpDib ); LPBITMAPINFO lpDibInfo = (LPBITMAPINFO)lpDib; LPBITMAPCOREINFO lpCoreInfo = (LPBITMAPCOREINFO)lpDib;
palette.palVersion = 0x300; palette.palNumEntries = (WORD)ppalNew->GetPaletteEntries( 0, 256, &palette.palPalEntry[0] ); ppalNew->GetPaletteEntries( 0, palette.palNumEntries, &palette.palPalEntry[0] ); for (int iLoop = 0; iLoop < iDibColors; iLoop++) { if (bWinStyleDIB) { crCurColor = PALETTERGB( lpDibInfo->bmiColors[iLoop].rgbRed, lpDibInfo->bmiColors[iLoop].rgbGreen, lpDibInfo->bmiColors[iLoop].rgbBlue ); } else { crCurColor = PALETTERGB( lpCoreInfo->bmciColors[iLoop].rgbtRed, lpCoreInfo->bmciColors[iLoop].rgbtGreen, lpCoreInfo->bmciColors[iLoop].rgbtBlue ); } uColorIndex = ppalNew->GetNearestPaletteIndex( crCurColor );
if (bWinStyleDIB) { lpDibInfo->bmiColors[iLoop].rgbRed = palette.palPalEntry[uColorIndex].peRed; lpDibInfo->bmiColors[iLoop].rgbGreen = palette.palPalEntry[uColorIndex].peGreen; lpDibInfo->bmiColors[iLoop].rgbBlue = palette.palPalEntry[uColorIndex].peBlue; } else { lpCoreInfo->bmciColors[iLoop].rgbtRed = palette.palPalEntry[uColorIndex].peRed; lpCoreInfo->bmciColors[iLoop].rgbtGreen = palette.palPalEntry[uColorIndex].peGreen; lpCoreInfo->bmciColors[iLoop].rgbtBlue = palette.palPalEntry[uColorIndex].peBlue; } } if (! bSwapPalette) { if ( bMergedPalette ) { delete ppalNew; bMergedPalette = FALSE; } ppalNew = NULL; } }
if (bSwapPalette) { if (pImg->m_hPalOld) { ::SelectPalette( pImg->hDC, pImg->m_hPalOld, FALSE ); pImg->m_hPalOld = NULL; }
if (pImg->m_pPalette) delete pImg->m_pPalette;
pImg->m_pPalette = ppalNew; pImg->m_hPalOld = ::SelectPalette( pImg->hDC, (HPALETTE)ppalNew->GetSafeHandle(), FALSE ); ::RealizePalette( pImg->hDC ); InvalImgRect( pImg, NULL );
// Return NULL since we swapped the new palette into the pImg!
ppalNew = NULL;
theApp.m_pPalette = pImg->m_pPalette;
//
// now that we changed the app palette update the DIB Section
// color table too.
//
DWORD rgb[256]; int i,n;
n = theApp.m_pPalette->GetPaletteEntries(0, 256, (LPPALETTEENTRY)rgb); for (i=0; i<n; i++) rgb[i] = RGB(GetBValue(rgb[i]),GetGValue(rgb[i]),GetRValue(rgb[i])); SetDIBColorTable(pImg->hDC, 0, n, (LPRGBQUAD)rgb); }
// Delete any orphaned ppalDib pointers.
if ( ppalDib && ppalDib != ppalNew ) delete ppalDib;
return ppalNew; }
/***************************************************************************/
void CImgWnd::ShowBrush(CPoint ptHandle) { IMG * pimg = m_pImg;
HideBrush();
COLORREF crRealLeftColor; COLORREF crRealRightColor;
int nStrokeWidth = CImgTool::GetCurrent()->GetStrokeWidth(); int nStrokeShape = CImgTool::GetCurrent()->GetStrokeShape();
if (CImgTool::GetCurrentID() == IDMB_ERASERTOOL) { crRealRightColor = crRight; crRealLeftColor = crLeft;
crLeft = crRight; }
g_pDragBrushWnd = this;
if (g_bCustomBrush) { int nCombineMode = (theImgBrush.m_bOpaque) ? combineReplace : combineMatte;
rcDragBrush.SetRect(ptHandle.x, ptHandle.y, ptHandle.x + theImgBrush.m_size.cx, ptHandle.y + theImgBrush.m_size.cy); rcDragBrush -= (CPoint)theImgBrush.m_handle;
theImgBrush.m_rcSelection = rcDragBrush; rcDragBrush.right += 1; rcDragBrush.bottom += 1;
if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL) { // extern CTextTool g_textTool;
// g_textTool.Render(CDC::FromHandle(pimg->hDC),
// rcDragBrush, TRUE, FALSE);
} else { switch (nCombineMode) { case combineColor: theImgBrush.BltColor(pimg, rcDragBrush.TopLeft(), crLeft); break;
case combineMatte: theImgBrush.BltMatte(pimg, rcDragBrush.TopLeft()); break;
case combineReplace: theImgBrush.BltReplace(pimg, rcDragBrush.TopLeft()); break; } }
InvalImgRect(m_pImg, &rcDragBrush); } else { DrawImgLine(m_pImg, ptHandle, ptHandle, crLeft, nStrokeWidth, nStrokeShape, FALSE); rcDragBrush.left = ptHandle.x - nStrokeWidth / 2; rcDragBrush.top = ptHandle.y - nStrokeWidth / 2; rcDragBrush.right = rcDragBrush.left + nStrokeWidth; rcDragBrush.bottom = rcDragBrush.top + nStrokeWidth; }
if (CImgTool::GetCurrentID() == IDMB_ERASERTOOL) { crLeft = crRealLeftColor; crRight = crRealRightColor; }
g_bBrushVisible = TRUE; }
/***************************************************************************/
void CImgWnd::CmdSmallBrush() { if (CImgTool::GetCurrent()->GetStrokeWidth() != 0) CImgTool::GetCurrent()->SetStrokeWidth(1); }
/***************************************************************************/
void CImgWnd::CmdSmallerBrush() { if (theImgBrush.m_pImg != NULL || g_bCustomBrush) { CmdHalfBsh(); return; }
UINT nStrokeWidth = CImgTool::GetCurrent()->GetStrokeWidth();
if (nStrokeWidth > 1) CImgTool::GetCurrent()->SetStrokeWidth(nStrokeWidth - 1); }
/***************************************************************************/
void CImgWnd::CmdLargerBrush() { if (theImgBrush.m_pImg != NULL || g_bCustomBrush) { CmdDoubleBsh(); return; }
UINT nStrokeWidth = CImgTool::GetCurrent()->GetStrokeWidth();
CImgTool::GetCurrent()->SetStrokeWidth(nStrokeWidth + 1); }
/***************************************************************************/
void CImgWnd::CmdOK() { if (GetCapture() != NULL) { MessageBeep(0); return; } }
/***************************************************************************/ // Draw the tracker for this view (if it's the active one) into pDC.
// If pDC is NULL, one will be provided. Optimize drawing by limiting
// it to pPaintRect. If pPaintRect is NULL, draw the whole tracker.
//
void CImgWnd::DrawTracker( CDC* pDC, const CRect* pPaintRect ) { BOOL bDrawTrackerRgn = FALSE;
if (c_pImgWndCur != this || theImgBrush.m_bMoveSel || theImgBrush.m_bSmearSel || theImgBrush.m_bMakingSelection) { // This is not the active view, or the user is doing something
// to prevent the tracker from appearing.
return; }
BOOL bReleaseDC = FALSE; CRect clientRect;
if (pDC == NULL) { pDC = GetDC();
if (pDC == NULL) { theApp.SetGdiEmergency(FALSE); return; } bReleaseDC = TRUE; }
if (pPaintRect == NULL) { GetClientRect(&clientRect); pPaintRect = &clientRect; }
CRect trackerRect;
GetImageRect( trackerRect );
trackerRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE );
CTracker::EDGES edges = (CTracker::EDGES)(CTracker::right | CTracker::bottom);
if (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL) { bDrawTrackerRgn = TRUE; }
if (m_pImg == theImgBrush.m_pImg) { edges = CTracker::all;
trackerRect = theImgBrush.m_rcSelection;
trackerRect.left *= m_nZoom; trackerRect.top *= m_nZoom; trackerRect.right *= m_nZoom; trackerRect.bottom *= m_nZoom;
trackerRect.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE); trackerRect.OffsetRect( CTracker::HANDLE_SIZE + m_xScroll * m_nZoom, CTracker::HANDLE_SIZE + m_yScroll * m_nZoom);
if (IsGridVisible()) { trackerRect.right += 1; trackerRect.bottom += 1; } }
CTracker::DrawBorder (pDC, trackerRect, edges ); CTracker::DrawHandles(pDC, trackerRect, edges );
if (bReleaseDC) ReleaseDC(pDC); }
/***************************************************************************/ // Erase the tracker from this window. Handles whole image as well
// as selection trackers.
//
void CImgWnd::EraseTracker() { if (m_pImg == NULL) return;
CClientDC dc(this);
if (dc.m_hDC == NULL) { theApp.SetGdiEmergency(FALSE); return; }
CRect trackerRect;
if (m_pImg == theImgBrush.m_pImg) { // Tracker is a selection within the image
trackerRect = theImgBrush.m_rcSelection; ImageToClient(trackerRect); trackerRect.InflateRect(CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE);
if (IsGridVisible()) { trackerRect.right += 1; trackerRect.bottom += 1; }
InvalidateRect( &trackerRect, FALSE ); } else { // Tracker is around entire image
GetImageRect(trackerRect); trackerRect.InflateRect(CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE); DrawBackground(&dc, &trackerRect); } }
/***************************************************************************/
void CImgWnd::CmdTglOpaque() { HideBrush(); theImgBrush.m_bOpaque = !theImgBrush.m_bOpaque; theImgBrush.RecalcMask( crRight );
MoveBrush( theImgBrush.m_rcSelection );
if ((CImgTool::GetCurrentID() == IDMB_PICKTOOL) || (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)) g_pImgToolWnd->InvalidateOptions( FALSE ); }
/***************************************************************************/
void CImgWnd::CmdInvertColors() { IMG* pImg = m_pImg;
HideBrush();
CRect invertRect; if (theImgBrush.m_pImg == NULL && !g_bCustomBrush) { invertRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight); } else { invertRect = rcDragBrush; invertRect.right -= 1; invertRect.bottom -= 1; }
if (theImgBrush.m_pImg != NULL && ! theImgBrush.m_bFirstDrag || g_bCustomBrush) { CPalette* ppal = SetImgPalette( &theImgBrush.m_dc, FALSE );
theImgBrush.m_dc.PatBlt(0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy, DSTINVERT);
if (ppal) theImgBrush.m_dc.SelectPalette( ppal, FALSE ); // Background ??
theImgBrush.RecalcMask( crRight ); MoveBrush( theImgBrush.m_rcSelection ); } else { SetUndo( m_pImg );
PatBlt( pImg->hDC, invertRect.left, invertRect.top, invertRect.Width(), invertRect.Height(), DSTINVERT );
InvalImgRect ( m_pImg, &invertRect ); CommitImgRect( m_pImg, &invertRect ); FinishUndo( invertRect ); DirtyImg( m_pImg ); } }
/***************************************************************************/
void CImgWnd::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ) { CWnd::OnKeyDown( nChar, nRepCnt, nFlags ); }
/***************************************************************************/
void CImgWnd::OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags ) { CWnd::OnKeyUp( nChar, nRepCnt, nFlags ); }
/***************************************************************************/
|