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

  1. #include "stdafx.h"
  2. #include "global.h"
  3. #include "pbrush.h"
  4. #include "pbrusdoc.h"
  5. #include "pbrusfrm.h"
  6. #include "pbrusvw.h"
  7. #include "minifwnd.h"
  8. #include "bmobject.h"
  9. #include "imgsuprt.h"
  10. #include "imgwnd.h"
  11. #include "imgcolor.h"
  12. #include "imgbrush.h"
  13. #include "imgwell.h"
  14. #include "imgtools.h"
  15. #include "tedit.h"
  16. #include "t_text.h"
  17. #include "t_fhsel.h"
  18. #include "toolbox.h"
  19. #include "props.h"
  20. #include "undo.h"
  21. #include "srvritem.h"
  22. #ifdef _DEBUG
  23. #undef THIS_FILE
  24. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  25. #endif
  26. #include "memtrace.h"
  27. BOOL GetMFDimensions(
  28. HANDLE hMF, /* handle to the CF_METAFILEPICT object from clipbrd */
  29. HDC hDC, /* display context */
  30. long *pWidth, /* width of picture in pixels, OUT param */
  31. long *pHeight, /* height of picture in pixels, OUT param */
  32. long *pcXPelsPerMeter, /* horizontal resolution, OUT param */
  33. long *pcYPelsPerMeter, /* vertical resolution, OUT param */
  34. IMG* pImg)
  35. ;
  36. BOOL PlayMetafileIntoDC(
  37. HANDLE hMF,
  38. RECT *pRect,
  39. HDC hDC)
  40. ;
  41. /***************************************************************************/
  42. void CImgWnd::OnDestroyClipboard()
  43. {
  44. if (m_hPoints)
  45. {
  46. ::GlobalFree( m_hPoints );
  47. m_hPoints = NULL;
  48. }
  49. }
  50. /***************************************************************************/
  51. void CImgWnd::CopyBMAndPal(HBITMAP *pBM, CPalette ** ppPal)
  52. {
  53. IMG* pImg = m_pImg;
  54. CRect copyRect;
  55. if (theImgBrush.m_pImg == NULL)
  56. {
  57. HideBrush();
  58. copyRect.SetRect(0, 0, pImg->cxWidth, pImg->cyHeight);
  59. }
  60. else
  61. {
  62. copyRect = rcDragBrush;
  63. copyRect.right -= 1;
  64. copyRect.bottom -= 1;
  65. }
  66. BOOL bRegion = (CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL);
  67. #ifdef FHSELCLIP
  68. if (bRegion)
  69. {
  70. if (! m_wClipboardFormat)
  71. m_wClipboardFormat = RegisterClipboardFormat( TEXT("MSPaintFreehand") );
  72. if (theImgBrush.m_bFirstDrag)
  73. // PickupSelection(); but no way to tell if we do it twice...
  74. PrepareForBrushChange( TRUE, FALSE );
  75. CFreehandSelectTool* pTool = (CFreehandSelectTool*)CImgTool::GetCurrent();
  76. ASSERT( pTool );
  77. if (m_wClipboardFormat && pTool)
  78. {
  79. CPoint* pptArray;
  80. int iEntries;
  81. BOOL bData = pTool->CopyPointsToMemArray( &pptArray, &iEntries );
  82. if (bData && iEntries)
  83. {
  84. HGLOBAL hMem = ::GlobalAlloc( GHND | GMEM_MOVEABLE | GMEM_DDESHARE,
  85. iEntries * sizeof( POINT )
  86. + sizeof( short ));
  87. if (hMem)
  88. {
  89. short* pShort = (short*)::GlobalLock( hMem );
  90. *pShort++ = iEntries;
  91. LPPOINT pPts = (LPPOINT)pShort;
  92. for (int iPt = 0; iPt < iEntries; iPt++, pPts++)
  93. {
  94. pPts->x = pptArray[iPt].x - pTool->m_cRectBounding.left;
  95. pPts->y = pptArray[iPt].y - pTool->m_cRectBounding.top;
  96. }
  97. ::GlobalUnlock( hMem );
  98. if (m_hPoints)
  99. {
  100. ::GlobalFree( m_hPoints );
  101. m_hPoints = NULL;
  102. }
  103. m_hPoints = SetClipboardData( m_wClipboardFormat, hMem );
  104. }
  105. else
  106. theApp.SetMemoryEmergency();
  107. delete [] pptArray;
  108. }
  109. }
  110. else
  111. theApp.SetGdiEmergency();
  112. }
  113. #endif // FHSELCLIP
  114. if ( theImgBrush.m_pImg )
  115. {
  116. CPalette* ppalOld = SetImgPalette( &theImgBrush.m_dc );
  117. // Copy the selection...
  118. CRect rc( 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy );
  119. *pBM = CopyDC( &theImgBrush.m_dc, &rc );
  120. if (ppalOld)
  121. theImgBrush.m_dc.SelectPalette( ppalOld, TRUE );
  122. }
  123. else
  124. // Copy the whole image...
  125. *pBM = CopyDC( CDC::FromHandle( m_pImg->hDC ), &copyRect );
  126. if (theApp.m_pPalette && (*ppPal=new CPalette)!=NULL)
  127. {
  128. LOGPALETTE256 logPal;
  129. logPal.palVersion = 0x300;
  130. logPal.palNumEntries = (WORD)theApp.m_pPalette->GetPaletteEntries( 0, 256,
  131. &logPal.palPalEntry[0]);
  132. if ( logPal.palNumEntries )
  133. {
  134. theApp.m_pPalette->GetPaletteEntries( 0, logPal.palNumEntries,
  135. &logPal.palPalEntry[0] );
  136. (*ppPal)->CreatePalette( (LPLOGPALETTE)&logPal );
  137. }
  138. }
  139. }
  140. void CImgWnd::CmdCopy()
  141. {
  142. if (TextToolProcessed( ID_EDIT_COPY ))
  143. {
  144. return;
  145. }
  146. CBitmapObj* pResObject = new CBitmapObj;
  147. if (pResObject)
  148. {
  149. IMG* pImgStruct = new IMG;
  150. if (pImgStruct)
  151. {
  152. if (FillBitmapObj(c_pImgWndCur, pResObject, pImgStruct))
  153. {
  154. pImgStruct->m_pFirstImgWnd = NULL;
  155. pImgStruct->m_pBitmapObj = pResObject;
  156. HDC hDCSave = pImgStruct->hDC;
  157. pImgStruct->hDC = NULL;
  158. pImgStruct->hMaskDC = NULL;
  159. pImgStruct->hMaskBitmap = NULL;
  160. pImgStruct->hMaskBitmapOld = NULL;
  161. pImgStruct->hBitmap = NULL;
  162. pImgStruct->m_pPalette = NULL;
  163. CopyBMAndPal(&pImgStruct->hBitmap, &pImgStruct->m_pPalette);
  164. if (pImgStruct->hBitmap)
  165. {
  166. pImgStruct->hDC = CreateCompatibleDC(hDCSave);
  167. if (pImgStruct->hDC)
  168. {
  169. pImgStruct->hBitmapOld = (HBITMAP)SelectObject(
  170. pImgStruct->hDC, pImgStruct->hBitmap);
  171. pImgStruct->m_hPalOld = pImgStruct->m_pPalette
  172. ? SelectPalette(pImgStruct->hDC,
  173. (HPALETTE)pImgStruct->m_pPalette->m_hObject, FALSE)
  174. : NULL;
  175. // get a server item suitable to generate the clipboard data
  176. CPBView* pView = (CPBView*)
  177. ((CFrameWnd*)AfxGetMainWnd())->GetActiveView();
  178. CPBSrvrItem* pItem = new CPBSrvrItem(pView->GetDocument(),
  179. pResObject);
  180. if (pItem)
  181. {
  182. pItem->CopyToClipboard(FALSE);
  183. delete pItem;
  184. return;
  185. }
  186. }
  187. }
  188. }
  189. else
  190. {
  191. // the IMG and all it contains will get cleaned up when
  192. // pResObject is deleted, but only if FillBitmapObj succeeded
  193. delete pImgStruct;
  194. }
  195. }
  196. delete pResObject;
  197. }
  198. }
  199. /***************************************************************************/
  200. void CImgWnd::CmdCut()
  201. {
  202. if (TextToolProcessed( ID_EDIT_CUT ))
  203. return;
  204. // BOGUS:
  205. // CmdCopy doesn't just copy -- it can change the state of the selection
  206. // this forces the CmdClear to act in the context of the new state
  207. // save off a flag for CmdClear to special-case like 'first-drag'
  208. BOOL *pFlag;
  209. if (theImgBrush.m_pImg && theImgBrush.m_bFirstDrag)
  210. {
  211. pFlag = &theImgBrush.m_bCuttingFromImage;
  212. }
  213. else
  214. pFlag = NULL;
  215. CmdCopy();
  216. TRY
  217. {
  218. if (pFlag)
  219. *pFlag = TRUE;
  220. CmdClear();
  221. }
  222. CATCH_ALL(e)
  223. {
  224. // don't leave the flag set
  225. if (pFlag)
  226. *pFlag = FALSE;
  227. THROW_LAST();
  228. }
  229. END_CATCH_ALL
  230. // normal execution path
  231. if (pFlag)
  232. *pFlag = FALSE;
  233. }
  234. /***************************************************************************/
  235. void CImgWnd::CmdPaste()
  236. {
  237. if (TextToolProcessed( ID_EDIT_PASTE ))
  238. return;
  239. CancelToolMode(FALSE);
  240. CommitSelection(TRUE);
  241. HideBrush();
  242. SetupRubber( m_pImg );
  243. EraseTracker();
  244. theImgBrush.m_pImg = NULL;
  245. DrawTracker();
  246. SetUndo( m_pImg );
  247. if (! PasteImageClip())
  248. AfxMessageBox( IDS_ERROR_CLIPBOARD, MB_OK | MB_ICONHAND );
  249. }
  250. /***************************************************************************/
  251. HBITMAP CImgWnd::CopyDC( CDC* pImgDC, CRect* prcClip )
  252. {
  253. // BLOCK: copy the image to hStdBitmap for the clipboard
  254. CDC dc;
  255. CBitmap bm;
  256. CBitmap* pOldStdBitmap;
  257. int cxWidth = prcClip->Width();
  258. int cyHeight = prcClip->Height();
  259. if (! dc.CreateCompatibleDC ( pImgDC )
  260. || ! bm.CreateCompatibleBitmap( pImgDC, cxWidth, cyHeight ))
  261. {
  262. theApp.SetGdiEmergency();
  263. return FALSE;
  264. }
  265. pOldStdBitmap = dc.SelectObject( &bm );
  266. CPalette* pOldPalette = SetImgPalette( &dc );
  267. dc.BitBlt( 0, 0, cxWidth, cyHeight, pImgDC, prcClip->left, prcClip->top, SRCCOPY );
  268. dc.SelectObject( pOldStdBitmap );
  269. if (pOldPalette)
  270. dc.SelectPalette( pOldPalette, FALSE );
  271. // return the standard format (bitmap) data
  272. return (HBITMAP)bm.Detach();
  273. }
  274. /***************************************************************************/
  275. BOOL CImgWnd::IsPasteAvailable()
  276. {
  277. BOOL bPasteIsAvailable = FALSE;
  278. BOOL bBitmapAvailable = IsClipboardFormatAvailable( CF_BITMAP );
  279. BOOL bDIBAvailable = IsClipboardFormatAvailable( CF_DIB );
  280. BOOL bTextAvailable = IsClipboardFormatAvailable( CF_TEXT );
  281. BOOL bMFAvailable = IsClipboardFormatAvailable( CF_METAFILEPICT );
  282. if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  283. {
  284. CTextTool* pTextTool = (CTextTool*)CImgTool::GetCurrent();
  285. if (pTextTool != NULL
  286. && pTextTool->GetTextEditField() != NULL)
  287. bPasteIsAvailable = bTextAvailable;
  288. }
  289. else
  290. {
  291. bPasteIsAvailable = bBitmapAvailable || bDIBAvailable || bMFAvailable;
  292. }
  293. return bPasteIsAvailable;
  294. }
  295. /***************************************************************************/
  296. BOOL CImgWnd::IsSelectionAvailable( void )
  297. {
  298. if (CImgTool::GetCurrentID() == IDMX_TEXTTOOL)
  299. {
  300. CTextTool* pTextTool = (CTextTool*)CImgTool::GetCurrent();
  301. if (pTextTool != NULL
  302. && pTextTool->IsKindOf( RUNTIME_CLASS( CTextTool ) ))
  303. {
  304. CTedit* pTextEdit = pTextTool->GetTextEditField();
  305. if (pTextEdit != NULL
  306. && pTextEdit->IsKindOf( RUNTIME_CLASS( CTedit ) ))
  307. {
  308. DWORD dwSel = pTextEdit->GetEditWindow()->GetSel();
  309. BOOL bReturn = (HIWORD( dwSel) != LOWORD( dwSel ));
  310. if (! bReturn)
  311. bReturn = (pTextEdit->GetEditWindow()->GetWindowTextLength()
  312. != (int)LOWORD( dwSel ));
  313. return bReturn;
  314. }
  315. }
  316. }
  317. if (CImgTool::GetCurrentID() == IDMB_PICKTOOL
  318. || CImgTool::GetCurrentID() == IDMB_PICKRGNTOOL)
  319. {
  320. return (theImgBrush.m_pImg != NULL && ! g_bCustomBrush);
  321. }
  322. return FALSE;
  323. }
  324. /***************************************************************************/
  325. int PASCAL CheckPastedSize(int nWidth, int nHeight, IMG* pImg)
  326. {
  327. int nRet = IDNO;
  328. // If the image is a bitmap and the bitmap in the clipboard is larger,
  329. // then give the suer the option2 of growing the image...
  330. if (nWidth > pImg->cxWidth
  331. || nHeight > pImg->cyHeight)
  332. {
  333. CSize size( max(nWidth, pImg->cxWidth),
  334. max(nHeight, pImg->cyHeight) );
  335. theUndo.BeginUndo( TEXT("Resize Bitmap") );
  336. VERIFY( pImg->m_pBitmapObj->SetSizeProp( P_Size, size ) );
  337. theUndo.EndUndo();
  338. // PSS says users don't want to see this dialog
  339. #if 0
  340. // WARNING!!! MB_SYSTEMMODAL is _necessary_. No message boxes should
  341. // be run while the clipboard is opened. Loss of focus to other apps
  342. // can be disasterous! The clipboard will be hung or if the clipboard
  343. // is closed, the contents could be changed by another app.
  344. nRet = AfxMessageBox( IDS_ENLAGEBITMAPFORCLIP,
  345. MB_YESNOCANCEL | MB_ICONQUESTION | MB_SYSTEMMODAL );
  346. switch (nRet)
  347. {
  348. case IDYES:
  349. {
  350. CSize size( max(nWidth, pImg->cxWidth),
  351. max(nHeight, pImg->cyHeight) );
  352. theUndo.BeginUndo( TEXT("Resize Bitmap") );
  353. VERIFY( pImg->m_pBitmapObj->SetSizeProp( P_Size, size ) );
  354. theUndo.EndUndo();
  355. }
  356. break;
  357. }
  358. #endif
  359. }
  360. return(nRet);
  361. }
  362. struct CStgMedium : public STGMEDIUM
  363. {
  364. CStgMedium()
  365. {
  366. ZeroMemory(this, sizeof(*this));
  367. }
  368. ~CStgMedium()
  369. {
  370. ReleaseStgMedium(this);
  371. }
  372. };
  373. HGLOBAL
  374. _GetClipboardData (CLIPFORMAT cf, TYMED tymed, STGMEDIUM *pMedium)
  375. {
  376. IDataObject *pdo = NULL;
  377. HANDLE hRet = NULL;
  378. if (SUCCEEDED(OleGetClipboard (&pdo)))
  379. {
  380. FORMATETC fmt = { 0 };
  381. fmt.cfFormat = cf;
  382. fmt.lindex = -1;
  383. fmt.tymed = tymed;
  384. fmt.dwAspect = DVASPECT_CONTENT;
  385. pMedium->tymed = tymed;
  386. if (SUCCEEDED(pdo->GetData (&fmt, pMedium)))
  387. {
  388. hRet = pMedium->hGlobal;
  389. }
  390. else
  391. {
  392. ReleaseStgMedium(pMedium);
  393. }
  394. pdo->Release ();
  395. }
  396. else
  397. {
  398. TRACE( TEXT("Cannot open clipboard!\n") );
  399. }
  400. return hRet;
  401. }
  402. BOOL CImgWnd::PasteImageClip()
  403. {
  404. CWaitCursor wait;
  405. /////////////////////////////////////////////////////////////////////////
  406. // Find out what format is available on the clipboard. if it is
  407. // A. CF_BITMAP only - Set the mask bits opaque and blt the bitmap
  408. // into ICimageDC
  409. // In both cases, if the destination bitmap differs in size from
  410. // source bitmap, user is asked if he/she wants the src bitmap
  411. // stretched/clipped to new size
  412. /////////////////////////////////////////////////////////////////////////
  413. if (! m_wClipboardFormat)
  414. m_wClipboardFormat = (WORD)RegisterClipboardFormat( TEXT("MSPaintFreehand") );
  415. // Enumerate the cliboard contents to determine what is available.
  416. // If a CF_BITMAP is seen, set a flag and proceed. If a SDKPAINT
  417. // private format is seen, stop looking further
  418. BOOL bBitmapAvailable = FALSE;
  419. #ifdef FHSELCLIP
  420. BOOL bPrivateAvailable = FALSE;
  421. #endif // FHSELCLIP
  422. BOOL bPaletteAvailable = FALSE;
  423. BOOL bDIBAvailable = FALSE;
  424. BOOL bMFAvailable = FALSE;
  425. WORD wClipFmt = 0;
  426. BITMAP bmData;
  427. LONG cXPelsPerMeter = 0;
  428. LONG cYPelsPerMeter = 0;
  429. BOOL bResizedBitmap = FALSE;
  430. CPalette* ppalClipboard = NULL;
  431. CBitmap* pbmClipboard = NULL;
  432. LPSTR lpDib = NULL;
  433. HPALETTE hPal = NULL;
  434. HBITMAP hBitmap = NULL;
  435. HGLOBAL hDIB = NULL;
  436. HGLOBAL hMF = NULL;
  437. CStgMedium stgMedium;
  438. BOOL bGotClip = FALSE;
  439. hPal = (HPALETTE)_GetClipboardData( CF_PALETTE, TYMED_GDI, &stgMedium );
  440. if (hPal)
  441. {
  442. bPaletteAvailable = TRUE;
  443. ppalClipboard = CPalette::FromHandle( hPal );
  444. ReleaseStgMedium(&stgMedium);
  445. }
  446. if (!bGotClip)
  447. {
  448. hDIB = (HGLOBAL)_GetClipboardData( CF_DIB, TYMED_HGLOBAL, &stgMedium );
  449. if (hDIB)
  450. {
  451. lpDib = (LPSTR)::GlobalLock( hDIB );
  452. if (lpDib)
  453. {
  454. bmData.bmWidth = DIBWidth ( lpDib );
  455. bmData.bmHeight = DIBHeight( lpDib );
  456. if (bmData.bmWidth && bmData.bmHeight)
  457. {
  458. bDIBAvailable = TRUE;
  459. bPaletteAvailable = FALSE;
  460. PBITMAPINFOHEADER pbmih = (PBITMAPINFOHEADER) lpDib;
  461. if (pbmih->biSize >= sizeof(BITMAPINFOHEADER))
  462. {
  463. cXPelsPerMeter = pbmih->biXPelsPerMeter;
  464. cYPelsPerMeter = pbmih->biYPelsPerMeter;
  465. }
  466. }
  467. }
  468. }
  469. #ifdef _DEBUG
  470. TRACE1( "Loaded the DIB %s.\n", (bDIBAvailable? TEXT("Yes"): TEXT("No")) );
  471. #endif
  472. bGotClip = bDIBAvailable;
  473. }
  474. if (!bGotClip)
  475. {
  476. hBitmap = (HBITMAP)_GetClipboardData( CF_BITMAP, TYMED_GDI, &stgMedium );
  477. if (hBitmap)
  478. {
  479. pbmClipboard = CBitmap::FromHandle( hBitmap );
  480. if (pbmClipboard->GetObject( sizeof( BITMAP ), &bmData ))
  481. {
  482. bBitmapAvailable = TRUE;
  483. DIBSECTION ds;
  484. if (pbmClipboard->GetObject( sizeof( ds ), &ds ))
  485. {
  486. cXPelsPerMeter = ds.dsBmih.biXPelsPerMeter;
  487. cYPelsPerMeter = ds.dsBmih.biYPelsPerMeter;
  488. }
  489. if (bPaletteAvailable)
  490. {
  491. if (!ppalClipboard)
  492. bBitmapAvailable = FALSE;
  493. }
  494. }
  495. }
  496. #ifdef _DEBUG
  497. TRACE1( "Loaded the Bitmap %s.\n", (bBitmapAvailable? TEXT("Yes"): TEXT("No")) );
  498. #endif
  499. bGotClip = bBitmapAvailable;
  500. }
  501. if (!bGotClip)
  502. {
  503. hMF = (HGLOBAL)_GetClipboardData(CF_METAFILEPICT, TYMED_MFPICT, &stgMedium);
  504. if (hMF)
  505. {
  506. CDC dcMF;
  507. if (dcMF.CreateCompatibleDC( NULL ))
  508. {
  509. if (GetMFDimensions(hMF, dcMF.m_hDC, &bmData.bmWidth,
  510. &bmData.bmHeight, &cXPelsPerMeter, &cYPelsPerMeter, m_pImg))
  511. {
  512. bMFAvailable = TRUE;
  513. }
  514. }
  515. }
  516. bGotClip = bMFAvailable;
  517. }
  518. if (!bGotClip)
  519. {
  520. return FALSE;
  521. }
  522. switch (CheckPastedSize(bmData.bmWidth, bmData.bmHeight, m_pImg))
  523. {
  524. default:
  525. return TRUE;
  526. case IDYES:
  527. bResizedBitmap = TRUE;
  528. break;
  529. case IDNO:
  530. break;
  531. }
  532. CDC stdDC;
  533. BOOL bOkay = FALSE;
  534. CBitmap* pbmOld = NULL;
  535. CPalette* ppalOld = NULL;
  536. if (bBitmapAvailable)
  537. {
  538. CBitmap bmClipboard;
  539. CBitmap* pbmOldCopy = NULL;
  540. CPalette* ppalOldCopy = NULL;
  541. CDC* pdcCopy = NULL;
  542. if (! stdDC.CreateCompatibleDC( NULL ))
  543. {
  544. theApp.SetGdiEmergency();
  545. goto LReturn;
  546. }
  547. pbmOld = stdDC.SelectObject( pbmClipboard );
  548. if (! pbmOld)
  549. {
  550. theApp.SetGdiEmergency();
  551. goto LReturn;
  552. }
  553. if (ppalClipboard)
  554. {
  555. ppalOld = stdDC.SelectPalette( ppalClipboard, FALSE );
  556. stdDC.RealizePalette();
  557. }
  558. // duplicate the bitmap
  559. if (! bmClipboard.CreateBitmap( bmData.bmWidth, bmData.bmHeight,
  560. bmData.bmPlanes, bmData.bmBitsPixel, NULL ))
  561. {
  562. theApp.SetMemoryEmergency();
  563. goto LReturn;
  564. }
  565. pdcCopy = new CDC;
  566. if (pdcCopy == NULL)
  567. {
  568. theApp.SetMemoryEmergency();
  569. goto LReturn;
  570. }
  571. if (! pdcCopy->CreateCompatibleDC( NULL ))
  572. {
  573. delete pdcCopy;
  574. theApp.SetGdiEmergency();
  575. goto LReturn;
  576. }
  577. pbmOldCopy = pdcCopy->SelectObject( &bmClipboard );
  578. if (ppalClipboard)
  579. {
  580. ppalOldCopy = pdcCopy->SelectPalette( ppalClipboard, FALSE );
  581. pdcCopy->RealizePalette();
  582. }
  583. pdcCopy->BitBlt( 0, 0, bmData.bmWidth, bmData.bmHeight, &stdDC, 0, 0, SRCCOPY );
  584. if (ppalOldCopy)
  585. pdcCopy->SelectPalette( ppalOldCopy, FALSE );
  586. pdcCopy->SelectObject( pbmOldCopy );
  587. delete pdcCopy;
  588. stdDC.SelectObject( &bmClipboard );
  589. // Unload the bitmap
  590. stdDC.SelectObject( pbmOld );
  591. pbmOld = NULL;
  592. if (ppalOld)
  593. {
  594. stdDC.SelectPalette( ppalOld, FALSE );
  595. ppalOld = NULL;
  596. }
  597. // if we still do not know the image resolution, use the display resolution
  598. if (cXPelsPerMeter == 0 && cYPelsPerMeter == 0)
  599. {
  600. cXPelsPerMeter = MulDiv(::GetDeviceCaps(stdDC, LOGPIXELSX),10000, 254);
  601. cYPelsPerMeter = MulDiv(::GetDeviceCaps(stdDC, LOGPIXELSY),10000, 254);
  602. }
  603. stdDC.DeleteDC();
  604. // Now we convert our nice DDB to a DIB and back so we can
  605. // convert color bitmaps to monochrome nicely and deal with
  606. // palette differences...
  607. DWORD dwSize;
  608. lpDib = (LPSTR) DibFromBitmap(
  609. (HBITMAP)bmClipboard.GetSafeHandle(),
  610. BI_RGB,
  611. 0,
  612. ppalClipboard,
  613. NULL,
  614. dwSize,
  615. cXPelsPerMeter,
  616. cYPelsPerMeter );
  617. }
  618. if (bMFAvailable)
  619. {
  620. CDC dcMF;
  621. if (dcMF.CreateCompatibleDC(CDC::FromHandle(m_pImg->hDC)))
  622. {
  623. CBitmap bmMF;
  624. if (bmMF.CreateCompatibleBitmap(CDC::FromHandle(m_pImg->hDC),
  625. bmData.bmWidth, bmData.bmHeight))
  626. {
  627. dcMF.SelectObject(&bmMF);
  628. //not needed for DIBSection!!!
  629. if (ppalClipboard)
  630. {
  631. dcMF.SelectPalette(ppalClipboard, FALSE);
  632. }
  633. CRect rc(0, 0, bmData.bmWidth, bmData.bmHeight);
  634. PlayMetafileIntoDC(hMF, &rc, dcMF.m_hDC);
  635. // Select out the bitmap and palette
  636. dcMF.DeleteDC();
  637. DWORD dwSize;
  638. lpDib = (LPSTR) DibFromBitmap(
  639. (HBITMAP)bmMF.m_hObject, BI_RGB, 0,
  640. ppalClipboard, NULL, dwSize,
  641. cXPelsPerMeter, cYPelsPerMeter );
  642. }
  643. }
  644. }
  645. if (lpDib)
  646. {
  647. CPalette* ppalDib = CreateDIBPalette( lpDib );
  648. ppalDib = FixupDibPalette( lpDib, ppalDib );
  649. HBITMAP hbmDib = DIBToBitmap( lpDib, theApp.m_pPalette, m_pImg->hDC );
  650. if (bDIBAvailable)
  651. ::GlobalUnlock( hDIB );
  652. else
  653. FreeDib( lpDib );
  654. if (hbmDib != NULL
  655. && stdDC.CreateCompatibleDC( CDC::FromHandle( m_pImg->hDC ) ))
  656. {
  657. CRect rtBrush( 0, 0, bmData.bmWidth, bmData.bmHeight );
  658. BOOL bBrushMade = FALSE;
  659. CBitmap bmDib;
  660. bmDib.Attach( hbmDib );
  661. pbmOld = stdDC.SelectObject( &bmDib );
  662. if (m_pImg->m_pPalette)
  663. {
  664. ppalOld = stdDC.SelectPalette( m_pImg->m_pPalette, FALSE );
  665. stdDC.RealizePalette();
  666. }
  667. #ifdef FHSELCLIP
  668. if (bPrivateAvailable)
  669. {
  670. HGLOBAL hPts = (HGLOBAL)_GetClipboardData( m_wClipboardFormat );
  671. if (hPts)
  672. {
  673. short* lpShort = (short*)::GlobalLock( hPts );
  674. if (lpShort)
  675. {
  676. BOOL bError = FALSE;
  677. int iEntries = *lpShort++;
  678. LPPOINT lpPts = (LPPOINT)lpShort;
  679. CImgTool::Select( IDMB_PICKRGNTOOL );
  680. CFreehandSelectTool* pTool = (CFreehandSelectTool*)CImgTool::GetCurrent();
  681. if (pTool)
  682. {
  683. if (pTool->CreatePolyRegion( GetZoom(), lpPts, iEntries )
  684. && MakeBrush( stdDC.m_hDC, rtBrush ))
  685. {
  686. bBrushMade = TRUE;
  687. }
  688. }
  689. ::GlobalUnlock( hPts );
  690. }
  691. }
  692. }
  693. #endif // FHSELCLIP
  694. if (! bBrushMade)
  695. {
  696. if (CImgTool::GetCurrentID() != IDMB_PICKTOOL)
  697. CImgTool::Select( IDMB_PICKTOOL );
  698. bBrushMade = MakeBrush( stdDC.m_hDC, rtBrush );
  699. }
  700. if (bBrushMade)
  701. {
  702. // We have to "move" the brush so it appears...
  703. CRect rect( 0, 0, theImgBrush.m_rcSelection.Width(),
  704. theImgBrush.m_rcSelection.Height() );
  705. if (! bResizedBitmap)
  706. {
  707. // Move the brush so that it is in the upper-left corner of
  708. // the view (in case it's scrolled)...
  709. rect.OffsetRect( -m_xScroll, -m_yScroll );
  710. }
  711. MoveBrush( rect );
  712. DirtyImg( m_pImg );
  713. theImgBrush.m_bFirstDrag = FALSE;
  714. bOkay = TRUE;
  715. }
  716. else
  717. {
  718. TRACE( TEXT("Paste: MakeBrush failed!\n") );
  719. }
  720. if (ppalOld)
  721. {
  722. ppalOld = stdDC.SelectPalette( ppalOld, FALSE );
  723. ppalOld = NULL;
  724. }
  725. stdDC.SelectObject( pbmOld );
  726. pbmOld = NULL;
  727. bmDib.Detach();
  728. }
  729. if (hbmDib != NULL)
  730. ::DeleteObject( hbmDib );
  731. if (ppalDib != NULL)
  732. delete ppalDib;
  733. }
  734. LReturn:
  735. if (pbmOld != NULL)
  736. stdDC.SelectObject( pbmOld );
  737. if (ppalOld != NULL)
  738. stdDC.SelectPalette( ppalOld, FALSE );
  739. return bOkay;
  740. }
  741. /***************************************************************************/
  742. /* very similar to PasteImageClip, but this will paste into an existing */
  743. /* selection (theImgBrush), resizing it if necessary, and not moving it */
  744. /***************************************************************************/
  745. BOOL CImgWnd::PasteImageFile( LPSTR lpDib )
  746. {
  747. CDC stdDC;
  748. CRect cRectSelection = theImgBrush.m_rcSelection;
  749. BOOL bOkay = FALSE;
  750. if (lpDib == NULL)
  751. return bOkay;
  752. int iWidth = (int)DIBWidth ( lpDib );
  753. int iHeight = (int)DIBHeight( lpDib );
  754. if (CImgTool::GetCurrentID()==IDMB_PICKTOOL && theImgBrush.m_bFirstDrag)
  755. {
  756. if (iWidth < theImgBrush.m_size.cx)
  757. {
  758. cRectSelection.right = cRectSelection.left + iWidth - 1;
  759. }
  760. if (iHeight < theImgBrush.m_size.cy)
  761. {
  762. cRectSelection.bottom = cRectSelection.top + iHeight - 1;
  763. }
  764. // If the image is a bitmap and the bitmap in the clipboard is larger,
  765. // then give the user the option of growing the image...
  766. if (iWidth > theImgBrush.m_size.cx
  767. || iHeight > theImgBrush.m_size.cy)
  768. {
  769. cRectSelection.right = cRectSelection.left + iWidth - 1;
  770. cRectSelection.bottom = cRectSelection.top + iHeight - 1;
  771. // PSS says users don't want to see this dialog
  772. #if 0
  773. switch (AfxMessageBox( IDS_ENLAGEBITMAPFORCLIP,
  774. MB_YESNOCANCEL | MB_ICONQUESTION ))
  775. {
  776. default:
  777. return bOkay;
  778. break;
  779. case IDYES:
  780. cRectSelection.right = cRectSelection.left + iWidth - 1;
  781. cRectSelection.bottom = cRectSelection.top + iHeight - 1;
  782. break;
  783. case IDNO:
  784. break;
  785. }
  786. #endif
  787. }
  788. }
  789. else
  790. {
  791. int xPos = -m_xScroll;
  792. int yPos = -m_yScroll;
  793. switch (CheckPastedSize(iWidth, iHeight, m_pImg))
  794. {
  795. case IDYES:
  796. xPos = yPos = 0;
  797. break;
  798. case IDNO:
  799. break;
  800. default:
  801. return(bOkay);
  802. }
  803. CImgTool::Select(IDMB_PICKTOOL);
  804. cRectSelection = CRect(xPos, yPos, xPos+iWidth, yPos+iHeight);
  805. }
  806. MakeBrush( m_pImg->hDC, cRectSelection );
  807. // MakeBrush sets this
  808. theImgBrush.m_bFirstDrag = FALSE;
  809. if (! stdDC.CreateCompatibleDC( CDC::FromHandle( m_pImg->hDC ) ))
  810. {
  811. theApp.SetGdiEmergency();
  812. return bOkay;
  813. }
  814. CPalette* ppalDib = CreateDIBPalette( lpDib );
  815. ppalDib = FixupDibPalette( lpDib, ppalDib );
  816. HBITMAP hbmDib = DIBToBitmap( lpDib, theApp.m_pPalette, m_pImg->hDC );
  817. SetUndo( m_pImg );
  818. if (hbmDib != NULL)
  819. {
  820. CBitmap bmDib;
  821. CPalette* ppalOld = NULL;
  822. CBitmap* pbmOld = NULL;
  823. bmDib.Attach( hbmDib );
  824. pbmOld = stdDC.SelectObject( &bmDib );
  825. if (m_pImg->m_pPalette)
  826. {
  827. ppalOld = stdDC.SelectPalette( m_pImg->m_pPalette, FALSE );
  828. stdDC.RealizePalette();
  829. }
  830. if (MakeBrush( stdDC.m_hDC, CRect( CPoint( 0, 0 ), cRectSelection.Size() ) ))
  831. {
  832. theImgBrush.m_bFirstDrag = FALSE;
  833. // We have to "move" the brush so it appears...
  834. MoveBrush( cRectSelection );
  835. DirtyImg( m_pImg );
  836. bOkay = TRUE;
  837. }
  838. else
  839. {
  840. TRACE( TEXT("Paste: MakeBrush failed!\n") );
  841. }
  842. if (ppalOld != NULL)
  843. {
  844. ppalOld = stdDC.SelectPalette( ppalOld, FALSE );
  845. }
  846. stdDC.SelectObject( pbmOld );
  847. bmDib.Detach();
  848. ::DeleteObject( hbmDib );
  849. }
  850. if (ppalDib != NULL)
  851. delete ppalDib;
  852. return bOkay;
  853. }
  854. /***************************************************************************/
  855. // Stolen from PBrush
  856. //
  857. /****************************Module*Header******************************\
  858. * Module Name: metafile.c *
  859. * Routines to paste a metafile as a bitmap. *
  860. * Copyright (c) 1987 - 1991 Microsoft Corporation *
  861. \***********************************************************************/
  862. /* Computes dimensions of a metafile picture in pixels */
  863. BOOL GetMFDimensions(
  864. HANDLE hMF, /* handle to the CF_METAFILEPICT object from clipbrd */
  865. HDC hDC, /* display context */
  866. long *pWidth, /* width of picture in pixels, OUT param */
  867. long *pHeight, /* height of picture in pixels, OUT param */
  868. long *pcXPelsPerMeter, /* horizontal resolution, OUT param */
  869. long *pcYPelsPerMeter, /* vertical resolution, OUT param */
  870. IMG* pImg)
  871. {
  872. METAFILEPICT FAR *lpMfp, Picture;
  873. int MapModeOld=0;
  874. RECT Rect;
  875. long xScale, yScale, Scale;
  876. int hRes, vRes; /* horz and vert resolution, in pixels */
  877. int hSize, vSize; /* horz and vert size, in mm */
  878. int fResult = FALSE;
  879. if (!hMF || !(lpMfp = (METAFILEPICT FAR *)GlobalLock(hMF)))
  880. return FALSE;
  881. /* copy metafile picture hdr */
  882. Picture = *lpMfp;
  883. GlobalUnlock(hMF);
  884. /* Do not modify given DC's attributes */
  885. SaveDC(hDC);
  886. /* set the mapping mode */
  887. MapModeOld = SetMapMode(hDC, Picture.mm);
  888. if (Picture.mm != MM_ISOTROPIC && Picture.mm != MM_ANISOTROPIC)
  889. {
  890. /* For modes other than ISOTROPIC and ANISOTROPIC the picture
  891. * dimensions are given in logical units.
  892. /* Convert logical units to pixels. */
  893. Rect.left = 0; Rect.right = Picture.xExt;
  894. Rect.top = 0; Rect.bottom = Picture.yExt;
  895. if (!LPtoDP(hDC, (LPPOINT)&Rect, 2))
  896. goto Error;
  897. *pWidth = Rect.right - Rect.left + 1;
  898. *pHeight = Rect.bottom - Rect.top + 1;
  899. fResult = TRUE;
  900. }
  901. else /* ISOTROPIC or ANISOTROPIC mode,
  902. * using the xExt and yExt, determine pixel width and height of
  903. * the image */
  904. {
  905. hRes = GetDeviceCaps(hDC, HORZRES);
  906. vRes = GetDeviceCaps(hDC, VERTRES);
  907. hSize = GetDeviceCaps(hDC, HORZSIZE);
  908. vSize = GetDeviceCaps(hDC, VERTSIZE);
  909. *pcXPelsPerMeter = hRes * 1000 / hSize;
  910. *pcYPelsPerMeter = vRes * 1000 / vSize;
  911. if (Picture.xExt == 0) /* assume default size, aspect ratio */
  912. {
  913. *pWidth = pImg->cxWidth;
  914. *pHeight = pImg->cyHeight;
  915. }
  916. else if (Picture.xExt > 0) /* use suggested size in HIMETRIC units */
  917. {
  918. // convert suggested extents(in .01 mm units) for picture to pixel units.
  919. // xPixelsPermm = hRes/hSize;, yPixelsPermm = vRes/vSize;
  920. // Use Pixels Per logical unit.
  921. // *pWidth = Picture.xExt*xPixelsPermm/100;
  922. // *pHeight = Picture.yExt*yPixelsPermm/100;
  923. *pWidth = ((long)Picture.xExt * hRes/hSize/100);
  924. *pHeight = ((long)Picture.yExt * vRes/vSize/100);
  925. }
  926. else if (Picture.xExt < 0) /* use suggested aspect ratio, default size */
  927. {
  928. // 1 log unit = .01 mm.
  929. // (# of log units in imageWid pixels)/xExt;
  930. xScale = 100L * (long) pImg->cxWidth *
  931. hSize/hRes/-Picture.xExt;
  932. // (# of log units in imageHgt pixels)/yExt;
  933. yScale = 100L * (long) pImg->cyHeight *
  934. vSize/vRes/-Picture.yExt;
  935. // choose the minimum to accomodate the entire image
  936. Scale = min(xScale, yScale);
  937. // use scaled Pixels Per log unit.
  938. *pWidth = ((long)-Picture.xExt * Scale *
  939. hRes/hSize / 100);
  940. *pHeight = ((long)-Picture.yExt * Scale *
  941. vRes/vSize / 100);
  942. }
  943. fResult = TRUE;
  944. }
  945. Error:
  946. if (MapModeOld)
  947. SetMapMode(hDC, MapModeOld); /* select the old mapping mode */
  948. RestoreDC(hDC, -1);
  949. return fResult;
  950. }
  951. BOOL PlayMetafileIntoDC(
  952. HANDLE hMF,
  953. RECT *pRect,
  954. HDC hDC)
  955. {
  956. HBRUSH hbrBackground;
  957. METAFILEPICT FAR *lpMfp;
  958. if (!(lpMfp = (METAFILEPICT FAR *)GlobalLock(hMF)))
  959. return FALSE;
  960. SaveDC(hDC);
  961. /* Setup background color for the bitmap */
  962. hbrBackground = CreateSolidBrush(crRight);
  963. if (hbrBackground)
  964. {
  965. FillRect(hDC, pRect, hbrBackground);
  966. DeleteObject(hbrBackground);
  967. }
  968. SetMapMode(hDC, lpMfp->mm);
  969. if (lpMfp->mm == MM_ISOTROPIC || lpMfp->mm == MM_ANISOTROPIC)
  970. SetViewportExtEx(hDC, pRect->right-pRect->left, pRect->bottom-pRect->top,
  971. NULL);
  972. PlayMetaFile(hDC, lpMfp->hMF);
  973. GlobalUnlock(hMF);
  974. RestoreDC(hDC, -1);
  975. return TRUE;
  976. }