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

1204 lines
36 KiB

#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 "props.h"
#include "undo.h"
#include "srvritem.h"
#ifdef _DEBUG
#undef THIS_FILE
static CHAR BASED_CODE THIS_FILE[] = __FILE__;
#endif
#include "memtrace.h"
BOOL GetMFDimensions(
HANDLE hMF, /* handle to the CF_METAFILEPICT object from clipbrd */
HDC hDC, /* display context */
long *pWidth, /* width of picture in pixels, OUT param */
long *pHeight, /* height of picture in pixels, OUT param */
long *pcXPelsPerMeter, /* horizontal resolution, OUT param */
long *pcYPelsPerMeter, /* vertical resolution, OUT param */
IMG* pImg)
;
BOOL PlayMetafileIntoDC(
HANDLE hMF,
RECT *pRect,
HDC hDC)
;
/***************************************************************************/
void CImgWnd::OnDestroyClipboard()
{
if (m_hPoints)
{
::GlobalFree( m_hPoints );
m_hPoints = NULL;
}
}
/***************************************************************************/
void CImgWnd::CopyBMAndPal(HBITMAP *pBM, CPalette ** ppPal)
{
IMG* pImg = m_pImg;
CRect copyRect;
if (theImgBrush.m_pImg == NULL)
{
HideBrush();
copyRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight);
}
else
{
copyRect = rcDragBrush;
copyRect.right -= 1;
copyRect.bottom -= 1;
}
BOOL bRegion = (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL);
#ifdef FHSELCLIP
if (bRegion)
{
if (! m_wClipboardFormat)
m_wClipboardFormat = RegisterClipboardFormat( TEXT("MSPaintFreehand") );
if (theImgBrush.m_bFirstDrag)
// PickupSelection(); but no way to tell if we do it twice...
PrepareForBrushChange( TRUE, FALSE );
CFreehandSelectTool* pTool = (CFreehandSelectTool*)CImgTool::GetCurrent();
ASSERT( pTool );
if (m_wClipboardFormat && pTool)
{
CPoint* pptArray;
int iEntries;
BOOL bData = pTool->CopyPointsToMemArray( &pptArray, &iEntries );
if (bData && iEntries)
{
HGLOBAL hMem = ::GlobalAlloc( GHND | GMEM_MOVEABLE | GMEM_DDESHARE,
iEntries * sizeof( POINT )
+ sizeof( short ));
if (hMem)
{
short* pShort = (short*)::GlobalLock( hMem );
*pShort++ = iEntries;
LPPOINT pPts = (LPPOINT)pShort;
for (int iPt = 0; iPt < iEntries; iPt++, pPts++)
{
pPts->x = pptArray[iPt].x - pTool->m_cRectBounding.left;
pPts->y = pptArray[iPt].y - pTool->m_cRectBounding.top;
}
::GlobalUnlock( hMem );
if (m_hPoints)
{
::GlobalFree( m_hPoints );
m_hPoints = NULL;
}
m_hPoints = SetClipboardData( m_wClipboardFormat, hMem );
}
else
theApp.SetMemoryEmergency();
delete [] pptArray;
}
}
else
theApp.SetGdiEmergency();
}
#endif // FHSELCLIP
if ( theImgBrush.m_pImg )
{
CPalette* ppalOld = SetImgPalette( &theImgBrush.m_dc );
// Copy the selection...
CRect rc( 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy );
*pBM = CopyDC( &theImgBrush.m_dc, &rc );
if (ppalOld)
theImgBrush.m_dc.SelectPalette( ppalOld, TRUE );
}
else
// Copy the whole image...
*pBM = CopyDC( CDC::FromHandle( m_pImg->hDC ), &copyRect );
if (theApp.m_pPalette && (*ppPal=new CPalette)!=NULL)
{
LOGPALETTE256 logPal;
logPal.palVersion = 0x300;
logPal.palNumEntries = (WORD)theApp.m_pPalette->GetPaletteEntries( 0, 256,
&logPal.palPalEntry[0]);
if ( logPal.palNumEntries )
{
theApp.m_pPalette->GetPaletteEntries( 0, logPal.palNumEntries,
&logPal.palPalEntry[0] );
(*ppPal)->CreatePalette( (LPLOGPALETTE)&logPal );
}
}
}
void CImgWnd::CmdCopy()
{
if (TextToolProcessed( ID_EDIT_COPY ))
{
return;
}
CBitmapObj* pResObject = new CBitmapObj;
if (pResObject)
{
IMG* pImgStruct = new IMG;
if (pImgStruct)
{
if (FillBitmapObj(c_pImgWndCur, pResObject, pImgStruct))
{
pImgStruct->m_pFirstImgWnd = NULL;
pImgStruct->m_pBitmapObj = pResObject;
HDC hDCSave = pImgStruct->hDC;
pImgStruct->hDC = NULL;
pImgStruct->hMaskDC = NULL;
pImgStruct->hMaskBitmap = NULL;
pImgStruct->hMaskBitmapOld = NULL;
pImgStruct->hBitmap = NULL;
pImgStruct->m_pPalette = NULL;
CopyBMAndPal(&pImgStruct->hBitmap, &pImgStruct->m_pPalette);
if (pImgStruct->hBitmap)
{
pImgStruct->hDC = CreateCompatibleDC(hDCSave);
if (pImgStruct->hDC)
{
pImgStruct->hBitmapOld = (HBITMAP)SelectObject(
pImgStruct->hDC, pImgStruct->hBitmap);
pImgStruct->m_hPalOld = pImgStruct->m_pPalette
? SelectPalette(pImgStruct->hDC,
(HPALETTE)pImgStruct->m_pPalette->m_hObject, FALSE)
: NULL;
// get a server item suitable to generate the clipboard data
CPBView* pView = (CPBView*)
((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
CPBSrvrItem* pItem = new CPBSrvrItem(pView->GetDocument(),
pResObject);
if (pItem)
{
pItem->CopyToClipboard(FALSE);
delete pItem;
return;
}
}
}
}
else
{
// the IMG and all it contains will get cleaned up when
// pResObject is deleted, but only if FillBitmapObj succeeded
delete pImgStruct;
}
}
delete pResObject;
}
}
/***************************************************************************/
void CImgWnd::CmdCut()
{
if (TextToolProcessed( ID_EDIT_CUT ))
return;
// BOGUS:
// CmdCopy doesn't just copy -- it can change the state of the selection
// this forces the CmdClear to act in the context of the new state
// save off a flag for CmdClear to special-case like 'first-drag'
BOOL *pFlag;
if (theImgBrush.m_pImg && theImgBrush.m_bFirstDrag)
{
pFlag = &theImgBrush.m_bCuttingFromImage;
}
else
pFlag = NULL;
CmdCopy();
TRY
{
if (pFlag)
*pFlag = TRUE;
CmdClear();
}
CATCH_ALL(e)
{
// don't leave the flag set
if (pFlag)
*pFlag = FALSE;
THROW_LAST();
}
END_CATCH_ALL
// normal execution path
if (pFlag)
*pFlag = FALSE;
}
/***************************************************************************/
void CImgWnd::CmdPaste()
{
if (TextToolProcessed( ID_EDIT_PASTE ))
return;
CancelToolMode(FALSE);
CommitSelection(TRUE);
HideBrush();
SetupRubber( m_pImg );
EraseTracker();
theImgBrush.m_pImg = NULL;
DrawTracker();
SetUndo( m_pImg );
if (! PasteImageClip())
AfxMessageBox( IDS_ERROR_CLIPBOARD, MB_OK | MB_ICONHAND );
}
/***************************************************************************/
HBITMAP CImgWnd::CopyDC( CDC* pImgDC, CRect* prcClip )
{
// BLOCK: copy the image to hStdBitmap for the clipboard
CDC dc;
CBitmap bm;
CBitmap* pOldStdBitmap;
int cxWidth = prcClip->Width();
int cyHeight = prcClip->Height();
if (! dc.CreateCompatibleDC ( pImgDC )
|| ! bm.CreateCompatibleBitmap( pImgDC, cxWidth, cyHeight ))
{
theApp.SetGdiEmergency();
return FALSE;
}
pOldStdBitmap = dc.SelectObject( &bm );
CPalette* pOldPalette = SetImgPalette( &dc );
dc.BitBlt( 0, 0, cxWidth, cyHeight, pImgDC, prcClip->left, prcClip->top, SRCCOPY );
dc.SelectObject( pOldStdBitmap );
if (pOldPalette)
dc.SelectPalette( pOldPalette, FALSE );
// return the standard format (bitmap) data
return (HBITMAP)bm.Detach();
}
/***************************************************************************/
BOOL CImgWnd::IsPasteAvailable()
{
BOOL bPasteIsAvailable = FALSE;
BOOL bBitmapAvailable = IsClipboardFormatAvailable( CF_BITMAP );
BOOL bDIBAvailable = IsClipboardFormatAvailable( CF_DIB );
BOOL bTextAvailable = IsClipboardFormatAvailable( CF_TEXT );
BOOL bMFAvailable = IsClipboardFormatAvailable( CF_METAFILEPICT );
if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
{
CTextTool* pTextTool = (CTextTool*)CImgTool::GetCurrent();
if (pTextTool != NULL
&& pTextTool->GetTextEditField() != NULL)
bPasteIsAvailable = bTextAvailable;
}
else
{
bPasteIsAvailable = bBitmapAvailable || bDIBAvailable || bMFAvailable;
}
return bPasteIsAvailable;
}
/***************************************************************************/
BOOL CImgWnd::IsSelectionAvailable( void )
{
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 ) ))
{
DWORD dwSel = pTextEdit->GetEditWindow()->GetSel();
BOOL bReturn = (HIWORD( dwSel) != LOWORD( dwSel ));
if (! bReturn)
bReturn = (pTextEdit->GetEditWindow()->GetWindowTextLength()
!= (int)LOWORD( dwSel ));
return bReturn;
}
}
}
if (CImgTool::GetCurrentID() == IDMB_PICKTOOL
|| CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
{
return (theImgBrush.m_pImg != NULL && ! g_bCustomBrush);
}
return FALSE;
}
/***************************************************************************/
int PASCAL CheckPastedSize(int nWidth, int nHeight, IMG* pImg)
{
int nRet = IDNO;
// If the image is a bitmap and the bitmap in the clipboard is larger,
// then give the suer the option2 of growing the image...
if (nWidth > pImg->cxWidth
|| nHeight > pImg->cyHeight)
{
CSize size( max(nWidth, pImg->cxWidth),
max(nHeight, pImg->cyHeight) );
theUndo.BeginUndo( TEXT("Resize Bitmap") );
VERIFY( pImg->m_pBitmapObj->SetSizeProp( P_Size, size ) );
theUndo.EndUndo();
// PSS says users don't want to see this dialog
#if 0
// WARNING!!! MB_SYSTEMMODAL is _necessary_. No message boxes should
// be run while the clipboard is opened. Loss of focus to other apps
// can be disasterous! The clipboard will be hung or if the clipboard
// is closed, the contents could be changed by another app.
nRet = AfxMessageBox( IDS_ENLAGEBITMAPFORCLIP,
MB_YESNOCANCEL | MB_ICONQUESTION | MB_SYSTEMMODAL );
switch (nRet)
{
case IDYES:
{
CSize size( max(nWidth, pImg->cxWidth),
max(nHeight, pImg->cyHeight) );
theUndo.BeginUndo( TEXT("Resize Bitmap") );
VERIFY( pImg->m_pBitmapObj->SetSizeProp( P_Size, size ) );
theUndo.EndUndo();
}
break;
}
#endif
}
return(nRet);
}
struct CStgMedium : public STGMEDIUM
{
CStgMedium()
{
ZeroMemory(this, sizeof(*this));
}
~CStgMedium()
{
ReleaseStgMedium(this);
}
};
HGLOBAL
_GetClipboardData (CLIPFORMAT cf, TYMED tymed, STGMEDIUM *pMedium)
{
IDataObject *pdo = NULL;
HANDLE hRet = NULL;
if (SUCCEEDED(OleGetClipboard (&pdo)))
{
FORMATETC fmt = { 0 };
fmt.cfFormat = cf;
fmt.lindex = -1;
fmt.tymed = tymed;
fmt.dwAspect = DVASPECT_CONTENT;
pMedium->tymed = tymed;
if (SUCCEEDED(pdo->GetData (&fmt, pMedium)))
{
hRet = pMedium->hGlobal;
}
else
{
ReleaseStgMedium(pMedium);
}
pdo->Release ();
}
else
{
TRACE( TEXT("Cannot open clipboard!\n") );
}
return hRet;
}
BOOL CImgWnd::PasteImageClip()
{
CWaitCursor wait;
/////////////////////////////////////////////////////////////////////////
// Find out what format is available on the clipboard. if it is
// A. CF_BITMAP only - Set the mask bits opaque and blt the bitmap
// into ICimageDC
// In both cases, if the destination bitmap differs in size from
// source bitmap, user is asked if he/she wants the src bitmap
// stretched/clipped to new size
/////////////////////////////////////////////////////////////////////////
if (! m_wClipboardFormat)
m_wClipboardFormat = (WORD)RegisterClipboardFormat( TEXT("MSPaintFreehand") );
// Enumerate the cliboard contents to determine what is available.
// If a CF_BITMAP is seen, set a flag and proceed. If a SDKPAINT
// private format is seen, stop looking further
BOOL bBitmapAvailable = FALSE;
#ifdef FHSELCLIP
BOOL bPrivateAvailable = FALSE;
#endif // FHSELCLIP
BOOL bPaletteAvailable = FALSE;
BOOL bDIBAvailable = FALSE;
BOOL bMFAvailable = FALSE;
WORD wClipFmt = 0;
BITMAP bmData;
LONG cXPelsPerMeter = 0;
LONG cYPelsPerMeter = 0;
BOOL bResizedBitmap = FALSE;
CPalette* ppalClipboard = NULL;
CBitmap* pbmClipboard = NULL;
LPSTR lpDib = NULL;
HPALETTE hPal = NULL;
HBITMAP hBitmap = NULL;
HGLOBAL hDIB = NULL;
HGLOBAL hMF = NULL;
CStgMedium stgMedium;
BOOL bGotClip = FALSE;
hPal = (HPALETTE)_GetClipboardData( CF_PALETTE, TYMED_GDI, &stgMedium );
if (hPal)
{
bPaletteAvailable = TRUE;
ppalClipboard = CPalette::FromHandle( hPal );
ReleaseStgMedium(&stgMedium);
}
if (!bGotClip)
{
hDIB = (HGLOBAL)_GetClipboardData( CF_DIB, TYMED_HGLOBAL, &stgMedium );
if (hDIB)
{
lpDib = (LPSTR)::GlobalLock( hDIB );
if (lpDib)
{
bmData.bmWidth = DIBWidth ( lpDib );
bmData.bmHeight = DIBHeight( lpDib );
if (bmData.bmWidth && bmData.bmHeight)
{
bDIBAvailable = TRUE;
bPaletteAvailable = FALSE;
PBITMAPINFOHEADER pbmih = (PBITMAPINFOHEADER) lpDib;
if (pbmih->biSize >= sizeof(BITMAPINFOHEADER))
{
cXPelsPerMeter = pbmih->biXPelsPerMeter;
cYPelsPerMeter = pbmih->biYPelsPerMeter;
}
}
}
}
#ifdef _DEBUG
TRACE1( "Loaded the DIB %s.\n", (bDIBAvailable? TEXT("Yes"): TEXT("No")) );
#endif
bGotClip = bDIBAvailable;
}
if (!bGotClip)
{
hBitmap = (HBITMAP)_GetClipboardData( CF_BITMAP, TYMED_GDI, &stgMedium );
if (hBitmap)
{
pbmClipboard = CBitmap::FromHandle( hBitmap );
if (pbmClipboard->GetObject( sizeof( BITMAP ), &bmData ))
{
bBitmapAvailable = TRUE;
DIBSECTION ds;
if (pbmClipboard->GetObject( sizeof( ds ), &ds ))
{
cXPelsPerMeter = ds.dsBmih.biXPelsPerMeter;
cYPelsPerMeter = ds.dsBmih.biYPelsPerMeter;
}
if (bPaletteAvailable)
{
if (!ppalClipboard)
bBitmapAvailable = FALSE;
}
}
}
#ifdef _DEBUG
TRACE1( "Loaded the Bitmap %s.\n", (bBitmapAvailable? TEXT("Yes"): TEXT("No")) );
#endif
bGotClip = bBitmapAvailable;
}
if (!bGotClip)
{
hMF = (HGLOBAL)_GetClipboardData(CF_METAFILEPICT, TYMED_MFPICT, &stgMedium);
if (hMF)
{
CDC dcMF;
if (dcMF.CreateCompatibleDC( NULL ))
{
if (GetMFDimensions(hMF, dcMF.m_hDC, &bmData.bmWidth,
&bmData.bmHeight, &cXPelsPerMeter, &cYPelsPerMeter, m_pImg))
{
bMFAvailable = TRUE;
}
}
}
bGotClip = bMFAvailable;
}
if (!bGotClip)
{
return FALSE;
}
switch (CheckPastedSize(bmData.bmWidth, bmData.bmHeight, m_pImg))
{
default:
return TRUE;
case IDYES:
bResizedBitmap = TRUE;
break;
case IDNO:
break;
}
CDC stdDC;
BOOL bOkay = FALSE;
CBitmap* pbmOld = NULL;
CPalette* ppalOld = NULL;
if (bBitmapAvailable)
{
CBitmap bmClipboard;
CBitmap* pbmOldCopy = NULL;
CPalette* ppalOldCopy = NULL;
CDC* pdcCopy = NULL;
if (! stdDC.CreateCompatibleDC( NULL ))
{
theApp.SetGdiEmergency();
goto LReturn;
}
pbmOld = stdDC.SelectObject( pbmClipboard );
if (! pbmOld)
{
theApp.SetGdiEmergency();
goto LReturn;
}
if (ppalClipboard)
{
ppalOld = stdDC.SelectPalette( ppalClipboard, FALSE );
stdDC.RealizePalette();
}
// duplicate the bitmap
if (! bmClipboard.CreateBitmap( bmData.bmWidth, bmData.bmHeight,
bmData.bmPlanes, bmData.bmBitsPixel, NULL ))
{
theApp.SetMemoryEmergency();
goto LReturn;
}
pdcCopy = new CDC;
if (pdcCopy == NULL)
{
theApp.SetMemoryEmergency();
goto LReturn;
}
if (! pdcCopy->CreateCompatibleDC( NULL ))
{
delete pdcCopy;
theApp.SetGdiEmergency();
goto LReturn;
}
pbmOldCopy = pdcCopy->SelectObject( &bmClipboard );
if (ppalClipboard)
{
ppalOldCopy = pdcCopy->SelectPalette( ppalClipboard, FALSE );
pdcCopy->RealizePalette();
}
pdcCopy->BitBlt( 0, 0, bmData.bmWidth, bmData.bmHeight, &stdDC, 0, 0, SRCCOPY );
if (ppalOldCopy)
pdcCopy->SelectPalette( ppalOldCopy, FALSE );
pdcCopy->SelectObject( pbmOldCopy );
delete pdcCopy;
stdDC.SelectObject( &bmClipboard );
// Unload the bitmap
stdDC.SelectObject( pbmOld );
pbmOld = NULL;
if (ppalOld)
{
stdDC.SelectPalette( ppalOld, FALSE );
ppalOld = NULL;
}
// if we still do not know the image resolution, use the display resolution
if (cXPelsPerMeter == 0 && cYPelsPerMeter == 0)
{
cXPelsPerMeter = MulDiv(::GetDeviceCaps(stdDC, LOGPIXELSX),10000, 254);
cYPelsPerMeter = MulDiv(::GetDeviceCaps(stdDC, LOGPIXELSY),10000, 254);
}
stdDC.DeleteDC();
// Now we convert our nice DDB to a DIB and back so we can
// convert color bitmaps to monochrome nicely and deal with
// palette differences...
DWORD dwSize;
lpDib = (LPSTR) DibFromBitmap(
(HBITMAP)bmClipboard.GetSafeHandle(),
BI_RGB,
0,
ppalClipboard,
NULL,
dwSize,
cXPelsPerMeter,
cYPelsPerMeter );
}
if (bMFAvailable)
{
CDC dcMF;
if (dcMF.CreateCompatibleDC(CDC::FromHandle(m_pImg->hDC)))
{
CBitmap bmMF;
if (bmMF.CreateCompatibleBitmap(CDC::FromHandle(m_pImg->hDC),
bmData.bmWidth, bmData.bmHeight))
{
dcMF.SelectObject(&bmMF);
//not needed for DIBSection!!!
if (ppalClipboard)
{
dcMF.SelectPalette(ppalClipboard, FALSE);
}
CRect rc(0, 0, bmData.bmWidth, bmData.bmHeight);
PlayMetafileIntoDC(hMF, &rc, dcMF.m_hDC);
// Select out the bitmap and palette
dcMF.DeleteDC();
DWORD dwSize;
lpDib = (LPSTR) DibFromBitmap(
(HBITMAP)bmMF.m_hObject, BI_RGB, 0,
ppalClipboard, NULL, dwSize,
cXPelsPerMeter, cYPelsPerMeter );
}
}
}
if (lpDib)
{
CPalette* ppalDib = CreateDIBPalette( lpDib );
ppalDib = FixupDibPalette( lpDib, ppalDib );
HBITMAP hbmDib = DIBToBitmap( lpDib, theApp.m_pPalette, m_pImg->hDC );
if (bDIBAvailable)
::GlobalUnlock( hDIB );
else
FreeDib( lpDib );
if (hbmDib != NULL
&& stdDC.CreateCompatibleDC( CDC::FromHandle( m_pImg->hDC ) ))
{
CRect rtBrush( 0, 0, bmData.bmWidth, bmData.bmHeight );
BOOL bBrushMade = FALSE;
CBitmap bmDib;
bmDib.Attach( hbmDib );
pbmOld = stdDC.SelectObject( &bmDib );
if (m_pImg->m_pPalette)
{
ppalOld = stdDC.SelectPalette( m_pImg->m_pPalette, FALSE );
stdDC.RealizePalette();
}
#ifdef FHSELCLIP
if (bPrivateAvailable)
{
HGLOBAL hPts = (HGLOBAL)_GetClipboardData( m_wClipboardFormat );
if (hPts)
{
short* lpShort = (short*)::GlobalLock( hPts );
if (lpShort)
{
BOOL bError = FALSE;
int iEntries = *lpShort++;
LPPOINT lpPts = (LPPOINT)lpShort;
CImgTool::Select( IDMB_PICKRGNTOOL );
CFreehandSelectTool* pTool = (CFreehandSelectTool*)CImgTool::GetCurrent();
if (pTool)
{
if (pTool->CreatePolyRegion( GetZoom(), lpPts, iEntries )
&& MakeBrush( stdDC.m_hDC, rtBrush ))
{
bBrushMade = TRUE;
}
}
::GlobalUnlock( hPts );
}
}
}
#endif // FHSELCLIP
if (! bBrushMade)
{
if (CImgTool::GetCurrentID() != IDMB_PICKTOOL)
CImgTool::Select( IDMB_PICKTOOL );
bBrushMade = MakeBrush( stdDC.m_hDC, rtBrush );
}
if (bBrushMade)
{
// We have to "move" the brush so it appears...
CRect rect( 0, 0, theImgBrush.m_rcSelection.Width(),
theImgBrush.m_rcSelection.Height() );
if (! bResizedBitmap)
{
// Move the brush so that it is in the upper-left corner of
// the view (in case it's scrolled)...
rect.OffsetRect( -m_xScroll, -m_yScroll );
}
MoveBrush( rect );
DirtyImg( m_pImg );
theImgBrush.m_bFirstDrag = FALSE;
bOkay = TRUE;
}
else
{
TRACE( TEXT("Paste: MakeBrush failed!\n") );
}
if (ppalOld)
{
ppalOld = stdDC.SelectPalette( ppalOld, FALSE );
ppalOld = NULL;
}
stdDC.SelectObject( pbmOld );
pbmOld = NULL;
bmDib.Detach();
}
if (hbmDib != NULL)
::DeleteObject( hbmDib );
if (ppalDib != NULL)
delete ppalDib;
}
LReturn:
if (pbmOld != NULL)
stdDC.SelectObject( pbmOld );
if (ppalOld != NULL)
stdDC.SelectPalette( ppalOld, FALSE );
return bOkay;
}
/***************************************************************************/
/* very similar to PasteImageClip, but this will paste into an existing */
/* selection (theImgBrush), resizing it if necessary, and not moving it */
/***************************************************************************/
BOOL CImgWnd::PasteImageFile( LPSTR lpDib )
{
CDC stdDC;
CRect cRectSelection = theImgBrush.m_rcSelection;
BOOL bOkay = FALSE;
if (lpDib == NULL)
return bOkay;
int iWidth = (int)DIBWidth ( lpDib );
int iHeight = (int)DIBHeight( lpDib );
if (CImgTool::GetCurrentID()==IDMB_PICKTOOL && theImgBrush.m_bFirstDrag)
{
if (iWidth < theImgBrush.m_size.cx)
{
cRectSelection.right = cRectSelection.left + iWidth - 1;
}
if (iHeight < theImgBrush.m_size.cy)
{
cRectSelection.bottom = cRectSelection.top + iHeight - 1;
}
// If the image is a bitmap and the bitmap in the clipboard is larger,
// then give the user the option of growing the image...
if (iWidth > theImgBrush.m_size.cx
|| iHeight > theImgBrush.m_size.cy)
{
cRectSelection.right = cRectSelection.left + iWidth - 1;
cRectSelection.bottom = cRectSelection.top + iHeight - 1;
// PSS says users don't want to see this dialog
#if 0
switch (AfxMessageBox( IDS_ENLAGEBITMAPFORCLIP,
MB_YESNOCANCEL | MB_ICONQUESTION ))
{
default:
return bOkay;
break;
case IDYES:
cRectSelection.right = cRectSelection.left + iWidth - 1;
cRectSelection.bottom = cRectSelection.top + iHeight - 1;
break;
case IDNO:
break;
}
#endif
}
}
else
{
int xPos = -m_xScroll;
int yPos = -m_yScroll;
switch (CheckPastedSize(iWidth, iHeight, m_pImg))
{
case IDYES:
xPos = yPos = 0;
break;
case IDNO:
break;
default:
return(bOkay);
}
CImgTool::Select(IDMB_PICKTOOL);
cRectSelection = CRect(xPos, yPos, xPos+iWidth, yPos+iHeight);
}
MakeBrush( m_pImg->hDC, cRectSelection );
// MakeBrush sets this
theImgBrush.m_bFirstDrag = FALSE;
if (! stdDC.CreateCompatibleDC( CDC::FromHandle( m_pImg->hDC ) ))
{
theApp.SetGdiEmergency();
return bOkay;
}
CPalette* ppalDib = CreateDIBPalette( lpDib );
ppalDib = FixupDibPalette( lpDib, ppalDib );
HBITMAP hbmDib = DIBToBitmap( lpDib, theApp.m_pPalette, m_pImg->hDC );
SetUndo( m_pImg );
if (hbmDib != NULL)
{
CBitmap bmDib;
CPalette* ppalOld = NULL;
CBitmap* pbmOld = NULL;
bmDib.Attach( hbmDib );
pbmOld = stdDC.SelectObject( &bmDib );
if (m_pImg->m_pPalette)
{
ppalOld = stdDC.SelectPalette( m_pImg->m_pPalette, FALSE );
stdDC.RealizePalette();
}
if (MakeBrush( stdDC.m_hDC, CRect( CPoint( 0, 0 ), cRectSelection.Size() ) ))
{
theImgBrush.m_bFirstDrag = FALSE;
// We have to "move" the brush so it appears...
MoveBrush( cRectSelection );
DirtyImg( m_pImg );
bOkay = TRUE;
}
else
{
TRACE( TEXT("Paste: MakeBrush failed!\n") );
}
if (ppalOld != NULL)
{
ppalOld = stdDC.SelectPalette( ppalOld, FALSE );
}
stdDC.SelectObject( pbmOld );
bmDib.Detach();
::DeleteObject( hbmDib );
}
if (ppalDib != NULL)
delete ppalDib;
return bOkay;
}
/***************************************************************************/
// Stolen from PBrush
//
/****************************Module*Header******************************\
* Module Name: metafile.c *
* Routines to paste a metafile as a bitmap. *
* Copyright (c) 1987 - 1991 Microsoft Corporation *
\***********************************************************************/
/* Computes dimensions of a metafile picture in pixels */
BOOL GetMFDimensions(
HANDLE hMF, /* handle to the CF_METAFILEPICT object from clipbrd */
HDC hDC, /* display context */
long *pWidth, /* width of picture in pixels, OUT param */
long *pHeight, /* height of picture in pixels, OUT param */
long *pcXPelsPerMeter, /* horizontal resolution, OUT param */
long *pcYPelsPerMeter, /* vertical resolution, OUT param */
IMG* pImg)
{
METAFILEPICT FAR *lpMfp, Picture;
int MapModeOld=0;
RECT Rect;
long xScale, yScale, Scale;
int hRes, vRes; /* horz and vert resolution, in pixels */
int hSize, vSize; /* horz and vert size, in mm */
int fResult = FALSE;
if (!hMF || !(lpMfp = (METAFILEPICT FAR *)GlobalLock(hMF)))
return FALSE;
/* copy metafile picture hdr */
Picture = *lpMfp;
GlobalUnlock(hMF);
/* Do not modify given DC's attributes */
SaveDC(hDC);
/* set the mapping mode */
MapModeOld = SetMapMode(hDC, Picture.mm);
if (Picture.mm != MM_ISOTROPIC && Picture.mm != MM_ANISOTROPIC)
{
/* For modes other than ISOTROPIC and ANISOTROPIC the picture
* dimensions are given in logical units.
/* Convert logical units to pixels. */
Rect.left = 0; Rect.right = Picture.xExt;
Rect.top = 0; Rect.bottom = Picture.yExt;
if (!LPtoDP(hDC, (LPPOINT)&Rect, 2))
goto Error;
*pWidth = Rect.right - Rect.left + 1;
*pHeight = Rect.bottom - Rect.top + 1;
fResult = TRUE;
}
else /* ISOTROPIC or ANISOTROPIC mode,
* using the xExt and yExt, determine pixel width and height of
* the image */
{
hRes = GetDeviceCaps(hDC, HORZRES);
vRes = GetDeviceCaps(hDC, VERTRES);
hSize = GetDeviceCaps(hDC, HORZSIZE);
vSize = GetDeviceCaps(hDC, VERTSIZE);
*pcXPelsPerMeter = hRes * 1000 / hSize;
*pcYPelsPerMeter = vRes * 1000 / vSize;
if (Picture.xExt == 0) /* assume default size, aspect ratio */
{
*pWidth = pImg->cxWidth;
*pHeight = pImg->cyHeight;
}
else if (Picture.xExt > 0) /* use suggested size in HIMETRIC units */
{
// convert suggested extents(in .01 mm units) for picture to pixel units.
// xPixelsPermm = hRes/hSize;, yPixelsPermm = vRes/vSize;
// Use Pixels Per logical unit.
// *pWidth = Picture.xExt*xPixelsPermm/100;
// *pHeight = Picture.yExt*yPixelsPermm/100;
*pWidth = ((long)Picture.xExt * hRes/hSize/100);
*pHeight = ((long)Picture.yExt * vRes/vSize/100);
}
else if (Picture.xExt < 0) /* use suggested aspect ratio, default size */
{
// 1 log unit = .01 mm.
// (# of log units in imageWid pixels)/xExt;
xScale = 100L * (long) pImg->cxWidth *
hSize/hRes/-Picture.xExt;
// (# of log units in imageHgt pixels)/yExt;
yScale = 100L * (long) pImg->cyHeight *
vSize/vRes/-Picture.yExt;
// choose the minimum to accomodate the entire image
Scale = min(xScale, yScale);
// use scaled Pixels Per log unit.
*pWidth = ((long)-Picture.xExt * Scale *
hRes/hSize / 100);
*pHeight = ((long)-Picture.yExt * Scale *
vRes/vSize / 100);
}
fResult = TRUE;
}
Error:
if (MapModeOld)
SetMapMode(hDC, MapModeOld); /* select the old mapping mode */
RestoreDC(hDC, -1);
return fResult;
}
BOOL PlayMetafileIntoDC(
HANDLE hMF,
RECT *pRect,
HDC hDC)
{
HBRUSH hbrBackground;
METAFILEPICT FAR *lpMfp;
if (!(lpMfp = (METAFILEPICT FAR *)GlobalLock(hMF)))
return FALSE;
SaveDC(hDC);
/* Setup background color for the bitmap */
hbrBackground = CreateSolidBrush(crRight);
if (hbrBackground)
{
FillRect(hDC, pRect, hbrBackground);
DeleteObject(hbrBackground);
}
SetMapMode(hDC, lpMfp->mm);
if (lpMfp->mm == MM_ISOTROPIC || lpMfp->mm == MM_ANISOTROPIC)
SetViewportExtEx(hDC, pRect->right-pRect->left, pRect->bottom-pRect->top,
NULL);
PlayMetaFile(hDC, lpMfp->hMF);
GlobalUnlock(hMF);
RestoreDC(hDC, -1);
return TRUE;
}