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.

1071 lines
29 KiB

  1. //
  2. // CLPBD.CPP
  3. // Clipboard Handling
  4. //
  5. // Copyright Microsoft 1998-
  6. //
  7. // PRECOMP
  8. #include "precomp.h"
  9. //
  10. // NFC, SFR 5921. Maximum length of a string pasted from the clipboard.
  11. // We impose this limit as our graphic object code cant
  12. // handle more then this number of chars.
  13. //
  14. #define WB_MAX_TEXT_PASTE_LEN (INT_MAX-1)
  15. //
  16. //
  17. // Function: Paste
  18. //
  19. // Purpose: Paste a format from the clipboard
  20. //
  21. //
  22. DCWbGraphic* WbMainWindow::CLP_Paste(void)
  23. {
  24. UINT length = 0;
  25. HANDLE handle = NULL;
  26. DCWbGraphic* pGraphic = NULL;
  27. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_Paste");
  28. // Get the highest priority acceptable format in the clipboard
  29. int iFormat = CLP_AcceptableClipboardFormat();
  30. if (!iFormat)
  31. goto NoOpenClip;
  32. TRACE_MSG(("Found acceptable format %d", iFormat));
  33. // Open the clipboard
  34. if (!::OpenClipboard(m_hwnd))
  35. {
  36. WARNING_OUT(("CLP_Paste: can't open clipboard"));
  37. goto NoOpenClip;
  38. }
  39. handle = ::GetClipboardData(iFormat);
  40. if (!handle)
  41. {
  42. WARNING_OUT(("CLP_Paste: can't get data for format %d", iFormat));
  43. goto NoFormatData;
  44. }
  45. switch (iFormat)
  46. {
  47. //
  48. // Check the standard formats
  49. //
  50. case CF_DIB:
  51. {
  52. TRACE_MSG(("Pasting CF_DIB"));
  53. // Lock the handle to get a pointer to the DIB
  54. LPBITMAPINFOHEADER lpbi;
  55. lpbi = (LPBITMAPINFOHEADER) ::GlobalLock(handle);
  56. if (lpbi != NULL)
  57. {
  58. LPBITMAPINFOHEADER lpbiNew;
  59. // Make a copy of the clipboard data
  60. lpbiNew = DIB_Copy(lpbi);
  61. if (lpbiNew != NULL)
  62. {
  63. // Create a graphic object
  64. DCWbGraphicDIB* pDIB = new DCWbGraphicDIB();
  65. if (!pDIB)
  66. {
  67. ERROR_OUT(("CF_DIB clipboard handling; couldn't create new DCWbGraphicDIB object"));
  68. }
  69. else
  70. {
  71. pDIB->SetImage(lpbiNew);
  72. }
  73. TRACE_MSG(("Set DIB into graphic object %lx",pDIB));
  74. pGraphic = pDIB;
  75. }
  76. // Release the memory
  77. ::GlobalUnlock(handle);
  78. }
  79. }
  80. break;
  81. //
  82. // We have a metafile. Play it into a bitmap and then use the
  83. // data.
  84. //
  85. case CF_ENHMETAFILE:
  86. {
  87. TRACE_MSG(("Pasting CF_ENHMETAFILE"));
  88. HDC hDrawingDC;
  89. ENHMETAHEADER meta_header;
  90. HBITMAP hBitmap = NULL;
  91. HDC meta_dc = NULL;
  92. HBITMAP hSaveBitmap;
  93. HPEN hSavePen;
  94. HPALETTE hPalette;
  95. RECT meta_rect;
  96. LPBITMAPINFOHEADER lpbiNew;
  97. int tmp;
  98. // We just need a DC compatible with the drawing area wnd
  99. hDrawingDC = m_drawingArea.GetCachedDC();
  100. // make a dc
  101. meta_dc = ::CreateCompatibleDC(hDrawingDC);
  102. if (!meta_dc)
  103. goto CleanupMetaFile;
  104. // figure out image size.
  105. ::GetEnhMetaFileHeader( (HENHMETAFILE)handle,
  106. sizeof( ENHMETAHEADER ),
  107. &meta_header );
  108. meta_rect.left = meta_rect.top = 0;
  109. meta_rect.right = ((meta_header.rclFrame.right - meta_header.rclFrame.left)
  110. * ::GetDeviceCaps(hDrawingDC, LOGPIXELSX ))/2540;
  111. meta_rect.bottom = ((meta_header.rclFrame.bottom - meta_header.rclFrame.top)
  112. * ::GetDeviceCaps(hDrawingDC, LOGPIXELSY ))/2540;
  113. // Normalize coords
  114. if (meta_rect.right < meta_rect.left)
  115. {
  116. tmp = meta_rect.left;
  117. meta_rect.left = meta_rect.right;
  118. meta_rect.right = tmp;
  119. }
  120. if (meta_rect.bottom < meta_rect.top)
  121. {
  122. tmp = meta_rect.top;
  123. meta_rect.top = meta_rect.bottom;
  124. meta_rect.bottom = tmp;
  125. }
  126. // make a place to play meta in
  127. hBitmap = ::CreateCompatibleBitmap(hDrawingDC,
  128. meta_rect.right - meta_rect.left,
  129. meta_rect.bottom - meta_rect.top);
  130. if (!hBitmap)
  131. goto CleanupMetaFile;
  132. hSaveBitmap = SelectBitmap(meta_dc, hBitmap);
  133. // erase our paper
  134. hSavePen = SelectPen(meta_dc, GetStockObject(NULL_PEN));
  135. ::Rectangle(meta_dc, meta_rect.left, meta_rect.top,
  136. meta_rect.right + 1, meta_rect.bottom + 1);
  137. SelectPen(meta_dc, hSavePen);
  138. // play the tape
  139. ::PlayEnhMetaFile(meta_dc, (HENHMETAFILE)handle, &meta_rect);
  140. // unplug our new bitmap
  141. SelectBitmap(meta_dc, hSaveBitmap);
  142. // Check for a palette object in the clipboard
  143. hPalette = (HPALETTE)::GetClipboardData(CF_PALETTE);
  144. // Create a new DIB from the bitmap
  145. lpbiNew = DIB_FromBitmap(hBitmap, hPalette, FALSE);
  146. if (lpbiNew != NULL)
  147. {
  148. // Create a DIB graphic from the DIB
  149. DCWbGraphicDIB* pDIB = new DCWbGraphicDIB();
  150. if (!pDIB)
  151. {
  152. ERROR_OUT(("CF_ENHMETAFILE handling; couldn't allocate DCWbGraphicDIB object"));
  153. }
  154. else
  155. {
  156. pDIB->SetImage(lpbiNew);
  157. }
  158. TRACE_MSG(("Set bitmap DIB into graphic object %lx",pDIB));
  159. pGraphic = pDIB;
  160. }
  161. CleanupMetaFile:
  162. // Free our temp intermediate bitmap
  163. if (hBitmap != NULL)
  164. {
  165. DeleteBitmap(hBitmap);
  166. }
  167. if (meta_dc != NULL)
  168. {
  169. ::DeleteDC(meta_dc);
  170. }
  171. }
  172. break;
  173. case CF_TEXT:
  174. {
  175. LPSTR pData;
  176. TRACE_DEBUG(("Pasting text"));
  177. // Get a handle to the clipboard contents
  178. pData = (LPSTR)::GlobalLock(handle);
  179. if(pData)
  180. {
  181. // Create a text object to hold the data - get the font to
  182. // use from the tool attributes group.
  183. DCWbGraphicText* pPasteText = new DCWbGraphicText();
  184. // Use the current font attributes
  185. if (!pPasteText)
  186. {
  187. ERROR_OUT(("CF_TEXT handling; failed to allocate DCWbGraphicText object"));
  188. }
  189. else
  190. {
  191. pPasteText->SetFont(m_pCurrentTool->GetFont());
  192. pPasteText->SetText(pData);
  193. }
  194. pGraphic = pPasteText;
  195. }
  196. // Release the handle
  197. ::GlobalUnlock(handle);
  198. }
  199. break;
  200. default:
  201. {
  202. if (iFormat == g_ClipboardFormats[CLIPBOARD_PRIVATE_SINGLE_OBJ])
  203. {
  204. // There is a Whiteboard private format object in the clipboard.
  205. // The format of this object is exactly as stored in the page, we
  206. // can therefore use it immediately.
  207. TRACE_DEBUG(("Pasting a private Whiteboard object"));
  208. // Get a handle to the clipboard contents
  209. PWB_GRAPHIC pHeader;
  210. if (pHeader = (PWB_GRAPHIC) ::GlobalLock(handle))
  211. {
  212. // Add the object to the page
  213. pGraphic = DCWbGraphic::CopyGraphic(pHeader);
  214. // Release the handle
  215. ::GlobalUnlock(handle);
  216. }
  217. }
  218. else if (iFormat == g_ClipboardFormats[CLIPBOARD_PRIVATE_MULTI_OBJ])
  219. {
  220. DCWbGraphicMarker * pMarker = m_drawingArea.GetMarker();
  221. if (!pMarker)
  222. {
  223. ERROR_OUT(("Couldn't get marker from drawing area"));
  224. }
  225. else
  226. {
  227. pMarker->Paste(handle);
  228. }
  229. pGraphic = pMarker;
  230. }
  231. }
  232. break;
  233. }
  234. NoFormatData:
  235. ::CloseClipboard();
  236. NoOpenClip:
  237. return pGraphic;
  238. }
  239. //
  240. //
  241. // Function: Copy
  242. //
  243. // Purpose: Copy a graphic to the clipboard. The second parameter
  244. // indicates whether immediate rendering is required.
  245. //
  246. //
  247. BOOL WbMainWindow::CLP_Copy(DCWbGraphic* pGraphic, BOOL bRenderNow)
  248. {
  249. BOOL bResult = FALSE;
  250. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_Copy");
  251. ASSERT(pGraphic != NULL);
  252. //
  253. // We act according to the format of the selected graphic.
  254. //
  255. // For all formats we supply the Whiteboard private format (which is
  256. // just a copy of the flat representation of the graphic).
  257. //
  258. // We supply standard formats as follows.
  259. //
  260. // For bitmaps and all others we supply CF_DIB.
  261. //
  262. // For text graphics we supply CF_TEXT.
  263. //
  264. // Free up the saved delayed rendering graphic since we are about to
  265. // replace it in the clipboard
  266. CLP_FreeDelayedGraphic();
  267. // Save the page and handle of the new graphic, since they'll be used
  268. // for/ rendering it, either now or later
  269. m_hPageClip = pGraphic->Page();
  270. m_hGraphicClip = pGraphic->Handle();
  271. if (bRenderNow)
  272. {
  273. TRACE_MSG(("Rendering the graphic now"));
  274. // Have to empty the clipboard before rendering the formats.
  275. if (::OpenClipboard(m_hwnd))
  276. {
  277. // Get ownership of the clipboard
  278. ::EmptyClipboard();
  279. ::CloseClipboard();
  280. // Render the graphic
  281. bResult = CLP_RenderAllFormats(pGraphic);
  282. }
  283. // We can forget about this object now.
  284. ASSERT(m_pDelayedGraphicClip == NULL);
  285. m_hPageClip = WB_PAGE_HANDLE_NULL;
  286. m_hGraphicClip = NULL;
  287. }
  288. else
  289. {
  290. TRACE_MSG(("Delaying rendering"));
  291. // For delayed rendering we insist that the graphic has been saved
  292. // to external storage. It must therefore have a valid page and graphic
  293. // handle.
  294. ASSERT(m_hPageClip != WB_PAGE_HANDLE_NULL);
  295. ASSERT(m_hGraphicClip != NULL);
  296. // Give formats (but no data) to the clipboard
  297. bResult = CLP_DelayAllFormats(pGraphic);
  298. }
  299. return bResult;
  300. }
  301. //
  302. //
  303. // Function: DelayAllFormats
  304. //
  305. // Purpose: Copy a graphic to the clipboard with delayed rendering
  306. //
  307. //
  308. BOOL WbMainWindow::CLP_DelayAllFormats(DCWbGraphic* pGraphic)
  309. {
  310. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_DelayAllFormats");
  311. BOOL bResult = FALSE;
  312. if (::OpenClipboard(m_hwnd))
  313. {
  314. // Empty / get ownership of the clipboard
  315. bResult = ::EmptyClipboard();
  316. // Add the private format
  317. HANDLE hResult;
  318. hResult =
  319. ::SetClipboardData(g_ClipboardFormats[CLIPBOARD_PRIVATE_SINGLE_OBJ], NULL);
  320. TRACE_DEBUG(("Adding Whiteboard object to clipboard"));
  321. if (pGraphic->IsGraphicTool() == enumGraphicText)
  322. {
  323. // Text graphic
  324. hResult = ::SetClipboardData(CF_TEXT, NULL);
  325. TRACE_DEBUG(("Adding text to clipboard"));
  326. }
  327. else
  328. {
  329. // All other graphics
  330. hResult = ::SetClipboardData(CF_DIB, NULL);
  331. TRACE_DEBUG(("Adding DIB to clipboard"));
  332. }
  333. ::CloseClipboard();
  334. }
  335. return bResult;
  336. }
  337. //
  338. //
  339. // Function: RenderAllFormats
  340. //
  341. // Purpose: Render a graphic to the clipboard
  342. //
  343. //
  344. BOOL WbMainWindow::CLP_RenderAllFormats(DCWbGraphic* pGraphic)
  345. {
  346. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAllFormats");
  347. BOOL bResult = FALSE;
  348. // Open the clipboard
  349. if (bResult = ::OpenClipboard(m_hwnd))
  350. {
  351. TRACE_DEBUG(("Rendering all formats of graphic"));
  352. // Render the private format
  353. bResult &= CLP_RenderPrivateFormat(pGraphic);
  354. if (pGraphic->IsGraphicTool() == enumGraphicText)
  355. {
  356. // Text graphic
  357. bResult &= CLP_RenderAsText(pGraphic);
  358. }
  359. else if (pGraphic->IsGraphicTool() == enumGraphicDIB)
  360. {
  361. // DIBs
  362. bResult &= CLP_RenderAsImage(pGraphic);
  363. }
  364. else
  365. {
  366. bResult &= CLP_RenderAsBitmap(pGraphic);
  367. }
  368. // Close the clipboard
  369. ::CloseClipboard();
  370. }
  371. return bResult;
  372. }
  373. BOOL WbMainWindow::CLP_RenderPrivateFormat(DCWbGraphic* pGraphic)
  374. {
  375. if (pGraphic->IsGraphicTool() == enumGraphicMarker)
  376. return( ((DCWbGraphicMarker*)pGraphic)->RenderPrivateMarkerFormat() );
  377. else
  378. return(CLP_RenderPrivateSingleFormat(pGraphic));
  379. }
  380. //
  381. //
  382. // Function: RenderPrivateSingleFormat
  383. //
  384. // Purpose: Render the private format of a graphic to the clipboard.
  385. // The clipboard should be open before this call is made.
  386. //
  387. //
  388. BOOL WbMainWindow::CLP_RenderPrivateSingleFormat(DCWbGraphic* pGraphic)
  389. {
  390. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderPrivateFormat");
  391. ASSERT(pGraphic != NULL);
  392. BOOL bResult = FALSE;
  393. // Get a pointer to the graphic data
  394. PWB_GRAPHIC pHeader = CLP_GetGraphicData();
  395. if (pHeader != NULL)
  396. {
  397. // Allocate memory for the clipboard data
  398. HANDLE hMem = ::GlobalAlloc(GHND, pHeader->length);
  399. if (hMem != NULL)
  400. {
  401. // Get a pointer to the memory
  402. LPBYTE pDest = (LPBYTE)::GlobalLock(hMem);
  403. if (pDest != NULL)
  404. {
  405. // Copy the graphic data to the allocated memory
  406. memcpy(pDest, pHeader, pHeader->length);
  407. TRACE_MSG(("Copied data %d bytes into %lx",pHeader->length,pDest));
  408. // make sure copy isn't "locked" (bug 474)
  409. ((PWB_GRAPHIC)pDest)->locked = WB_GRAPHIC_LOCK_NONE;
  410. // Release the memory
  411. ::GlobalUnlock(hMem);
  412. // Pass the data to the clipboard
  413. if (::SetClipboardData(g_ClipboardFormats[CLIPBOARD_PRIVATE_SINGLE_OBJ], hMem))
  414. {
  415. TRACE_DEBUG(("Rendered data in Whiteboard format"));
  416. bResult = TRUE;
  417. }
  418. }
  419. // If we failed to put the data into the clipboard, free the memory.
  420. // (If we did put it into the clipboard we must not free it).
  421. if (bResult == FALSE)
  422. {
  423. WARNING_OUT(("Render failed"));
  424. ::GlobalFree(hMem);
  425. }
  426. }
  427. // Release the graphic data
  428. CLP_ReleaseGraphicData(pHeader);
  429. }
  430. return bResult;
  431. }
  432. //
  433. //
  434. // Function: RenderAsText
  435. //
  436. // Purpose: Render the text format of a graphic to the clipboard.
  437. // The clipboard should be open before this call is made.
  438. // This member should only be called for text graphics.
  439. //
  440. //
  441. BOOL WbMainWindow::CLP_RenderAsText
  442. (
  443. DCWbGraphic* pGraphic
  444. )
  445. {
  446. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsText");
  447. ASSERT(pGraphic != NULL);
  448. ASSERT(pGraphic->IsGraphicTool() == enumGraphicText);
  449. BOOL bResult = FALSE;
  450. // Get the total length of the clipboard format of the text
  451. StrArray& strText = ((DCWbGraphicText*) pGraphic)->strTextArray;
  452. int iCount = strText.GetSize();
  453. int iIndex;
  454. DWORD dwLength = 0;
  455. for (iIndex = 0; iIndex < iCount; iIndex++)
  456. {
  457. // Length of string plus 2 for carriage return and line feed
  458. dwLength += lstrlen(strText[iIndex]) + 2;
  459. }
  460. // One more for the terminating NULL
  461. dwLength += 1;
  462. // Allocate memory for the clipboard data
  463. HANDLE hMem = ::GlobalAlloc(GHND, dwLength);
  464. if (hMem != NULL)
  465. {
  466. // Get a pointer to the memory
  467. LPSTR pDest = (LPSTR) ::GlobalLock(hMem);
  468. if (pDest != NULL)
  469. {
  470. // Write the graphic data to the allocated memory
  471. for (iIndex = 0; iIndex < iCount; iIndex++)
  472. {
  473. _tcscpy(pDest, strText[iIndex]);
  474. pDest += lstrlen(strText[iIndex]);
  475. // Add the carriage return and line feed
  476. *pDest++ = '\r';
  477. *pDest++ = '\n';
  478. }
  479. // Add the final NULL
  480. *pDest = '\0';
  481. // Release the memory
  482. ::GlobalUnlock(hMem);
  483. // Pass the data to the clipboard
  484. if (::SetClipboardData(CF_TEXT, hMem))
  485. {
  486. TRACE_DEBUG(("Rendered data in text format"));
  487. bResult = TRUE;
  488. }
  489. }
  490. // If we failed to put the data into the clipboard, free the memory
  491. if (bResult == FALSE)
  492. {
  493. ::GlobalFree(hMem);
  494. }
  495. }
  496. return bResult;
  497. }
  498. //
  499. //
  500. // Function: RenderAsImage
  501. //
  502. // Purpose: Render the bitmap format of a graphic to the clipboard.
  503. // The clipboard should be open before this call is made.
  504. // This member should only be called for DIB graphics.
  505. //
  506. //
  507. BOOL WbMainWindow::CLP_RenderAsImage
  508. (
  509. DCWbGraphic* pGraphic
  510. )
  511. {
  512. BOOL bResult = FALSE;
  513. HANDLE hMem = NULL;
  514. BYTE* pDest = NULL;
  515. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsImage");
  516. ASSERT(pGraphic != NULL);
  517. ASSERT(pGraphic->IsGraphicTool() == enumGraphicDIB);
  518. // Get a pointer to the graphic data
  519. PWB_GRAPHIC pHeader = CLP_GetGraphicData();
  520. if (pHeader != NULL)
  521. {
  522. LPBITMAPINFOHEADER lpbi;
  523. TRACE_MSG(("Getting a DIB image from %lx",pHeader));
  524. lpbi = (LPBITMAPINFOHEADER) (((LPBYTE) pHeader) + pHeader->dataOffset);
  525. DWORD dwLength = pHeader->length - pHeader->dataOffset;
  526. // Allocate the memory
  527. hMem = ::GlobalAlloc(GHND, dwLength);
  528. if (hMem != NULL)
  529. {
  530. LPBYTE pDest = (LPBYTE)::GlobalLock(hMem);
  531. if (pDest != NULL)
  532. {
  533. TRACE_MSG(("Building DIB at %lx length %ld",pDest, dwLength));
  534. memcpy(pDest, lpbi, dwLength);
  535. ::GlobalUnlock(hMem);
  536. if (::SetClipboardData(CF_DIB, hMem))
  537. {
  538. TRACE_DEBUG(("Rendered data in DIB format"));
  539. bResult = TRUE;
  540. }
  541. // If we failed to put the data into the clipboard, free the memory
  542. if (!bResult)
  543. {
  544. ERROR_OUT(("Error putting DIB into clipboard"));
  545. ::GlobalFree(hMem);
  546. }
  547. }
  548. }
  549. else
  550. {
  551. ERROR_OUT(("Could not allocate memory for DIB"));
  552. }
  553. // Release the data
  554. CLP_ReleaseGraphicData(pHeader);
  555. }
  556. return bResult;
  557. }
  558. //
  559. // CLP_RenderAsBitmap()
  560. //
  561. // This draws all other graphics into a bitmap and pastes the DIB contents
  562. // onto the clipboard.
  563. //
  564. BOOL WbMainWindow::CLP_RenderAsBitmap(DCWbGraphic* pGraphic)
  565. {
  566. BOOL bResult = FALSE;
  567. HDC hdcDisplay = NULL;
  568. HDC hdcMem = NULL;
  569. HBITMAP hBitmap = NULL;
  570. HBITMAP hOldBitmap = NULL;
  571. HPALETTE hPalette;
  572. RECT rcBounds;
  573. POINT pt;
  574. LPBITMAPINFOHEADER lpbi;
  575. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAsBitmap");
  576. ASSERT(pGraphic != NULL);
  577. ASSERT(pGraphic->IsGraphicTool() != enumGraphicText);
  578. ASSERT(pGraphic->IsGraphicTool() != enumGraphicDIB);
  579. //
  580. // First, draw it into a bitmap
  581. // Second, get the DIB bits of the bitmap
  582. //
  583. hdcDisplay = ::CreateDC("DISPLAY", NULL, NULL, NULL);
  584. if (!hdcDisplay)
  585. {
  586. ERROR_OUT(("Can't create DISPLAY dc"));
  587. goto AsBitmapDone;
  588. }
  589. hdcMem = ::CreateCompatibleDC(hdcDisplay);
  590. if (!hdcMem)
  591. {
  592. ERROR_OUT(("Can't create DISPLAY compatible dc"));
  593. goto AsBitmapDone;
  594. }
  595. pGraphic->GetBoundsRect(&rcBounds);
  596. hBitmap = ::CreateCompatibleBitmap(hdcDisplay,
  597. (rcBounds.right - rcBounds.left), (rcBounds.bottom - rcBounds.top));
  598. if (!hBitmap)
  599. {
  600. ERROR_OUT(("Can't create compatible bitmap"));
  601. goto AsBitmapDone;
  602. }
  603. hOldBitmap = SelectBitmap(hdcMem, hBitmap);
  604. if (!hOldBitmap)
  605. {
  606. ERROR_OUT(("Failed to select compatible bitmap"));
  607. goto AsBitmapDone;
  608. }
  609. ::SetMapMode(hdcMem, MM_ANISOTROPIC);
  610. pGraphic->GetPosition(&pt);
  611. ::SetWindowOrgEx(hdcMem, pt.x, pt.y, NULL);
  612. // Clear out bitmap with white background -- now that origin has been
  613. // altered, we can use drawing area coors.
  614. ::PatBlt(hdcMem, rcBounds.left, rcBounds.top, rcBounds.right - rcBounds.left,
  615. rcBounds.bottom - rcBounds.top, WHITENESS);
  616. if (pGraphic->IsGraphicTool() == enumGraphicMarker)
  617. {
  618. ((DCWbGraphicMarker *)pGraphic)->Draw(hdcMem, TRUE);
  619. }
  620. else
  621. {
  622. pGraphic->Draw(hdcMem);
  623. }
  624. SelectBitmap(hdcMem, hOldBitmap);
  625. // Now get the dib bits...
  626. hPalette = CreateSystemPalette();
  627. lpbi = DIB_FromBitmap(hBitmap, hPalette, TRUE);
  628. if (hPalette != NULL)
  629. ::DeletePalette(hPalette);
  630. // And put the handle on the clipboard
  631. if (lpbi != NULL)
  632. {
  633. if (::SetClipboardData(CF_DIB, (HGLOBAL)lpbi))
  634. {
  635. bResult = TRUE;
  636. }
  637. else
  638. {
  639. ::GlobalFree((HGLOBAL)lpbi);
  640. }
  641. }
  642. AsBitmapDone:
  643. if (hBitmap != NULL)
  644. ::DeleteBitmap(hBitmap);
  645. if (hdcMem != NULL)
  646. ::DeleteDC(hdcMem);
  647. if (hdcDisplay != NULL)
  648. ::DeleteDC(hdcDisplay);
  649. return(bResult);
  650. }
  651. //
  652. //
  653. // Function: RenderFormat
  654. //
  655. // Purpose: Render the specified format of the graphic in the clipboard.
  656. //
  657. //
  658. BOOL WbMainWindow::CLP_RenderFormat(int iFormat)
  659. {
  660. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderFormat");
  661. BOOL bResult = FALSE;
  662. // Get a graphic from the handle
  663. DCWbGraphic* pGraphic = CLP_GetGraphic();
  664. if (pGraphic != NULL)
  665. {
  666. // Check if it is the private format that is wanted
  667. switch (iFormat)
  668. {
  669. default:
  670. {
  671. if (iFormat == g_ClipboardFormats[CLIPBOARD_PRIVATE_SINGLE_OBJ])
  672. {
  673. bResult = CLP_RenderPrivateFormat(pGraphic);
  674. }
  675. else
  676. {
  677. ERROR_OUT(("Unrecognized CLP format %d", iFormat));
  678. }
  679. }
  680. break;
  681. case CF_TEXT:
  682. {
  683. bResult = CLP_RenderAsText(pGraphic);
  684. }
  685. break;
  686. case CF_DIB:
  687. {
  688. if (pGraphic->IsGraphicTool() == enumGraphicDIB)
  689. bResult = CLP_RenderAsImage(pGraphic);
  690. else
  691. bResult = CLP_RenderAsBitmap(pGraphic);
  692. }
  693. break;
  694. }
  695. }
  696. return bResult;
  697. }
  698. //
  699. //
  700. // Function: RenderAllFormats
  701. //
  702. // Purpose: Render all formats of the graphic in the clipboard.
  703. //
  704. //
  705. BOOL WbMainWindow::CLP_RenderAllFormats(void)
  706. {
  707. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_RenderAllFormats");
  708. BOOL bResult = FALSE;
  709. // Get a graphic from the handle
  710. DCWbGraphic* pGraphic = CLP_GetGraphic();
  711. if (pGraphic != NULL)
  712. {
  713. bResult = CLP_RenderAllFormats(pGraphic);
  714. }
  715. return bResult;
  716. }
  717. //
  718. //
  719. // Function: AcceptableClipboardFormat
  720. //
  721. // Purpose: Return highest priority clipboard format if an acceptable
  722. // one is available, else return NULL.
  723. //
  724. //
  725. int WbMainWindow::CLP_AcceptableClipboardFormat(void)
  726. {
  727. // Look for any of the supported formats being available
  728. int iFormat = ::GetPriorityClipboardFormat((UINT *)g_ClipboardFormats, CLIPBOARD_ACCEPTABLE_FORMATS);
  729. if (iFormat == -1)
  730. {
  731. iFormat = 0;
  732. }
  733. // the following is a performance enhancement: if we have found at some
  734. // point that the object on the clipboard does not have whiteboard
  735. // private format, then we can discard the delayed graphic because we
  736. // know we'll never be asked to render it.
  737. if (iFormat != g_ClipboardFormats[CLIPBOARD_PRIVATE_SINGLE_OBJ])
  738. {
  739. CLP_FreeDelayedGraphic();
  740. }
  741. return iFormat;
  742. }
  743. //
  744. //
  745. // Function: LastCopiedPage
  746. //
  747. // Purpose: Return the handle of the page on which the last graphic
  748. // copied to the clipboard was located.
  749. //
  750. //
  751. WB_PAGE_HANDLE WbMainWindow::CLP_LastCopiedPage(void) const
  752. {
  753. // If there's no graphic, there shouldn't be a page either
  754. ASSERT((m_hGraphicClip != NULL) == (m_hPageClip != WB_PAGE_HANDLE_NULL));
  755. return(m_hPageClip);
  756. }
  757. WB_GRAPHIC_HANDLE WbMainWindow::CLP_LastCopiedGraphic(void) const
  758. {
  759. return(m_hGraphicClip);
  760. }
  761. //
  762. //
  763. // Function: GetGraphic
  764. //
  765. // Purpose: Retrieve the graphic object for copying to the clipboard. If
  766. // the object has been saved, then use the local copy,
  767. // otherwise get the page to construct it now.
  768. //
  769. //
  770. DCWbGraphic* WbMainWindow::CLP_GetGraphic(void)
  771. {
  772. DCWbGraphic* pGraphic;
  773. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_GetGraphic");
  774. // if we have not saved the graphic's contents, then we must have a
  775. // valid page and graphic handle, since we construct the graphic now
  776. if (m_pDelayedGraphicClip == NULL)
  777. {
  778. ASSERT(m_hPageClip != WB_PAGE_HANDLE_NULL);
  779. ASSERT(m_hGraphicClip != NULL);
  780. pGraphic = DCWbGraphic::ConstructGraphic(m_hPageClip, m_hGraphicClip);
  781. }
  782. else
  783. {
  784. pGraphic = m_pDelayedGraphicClip;
  785. TRACE_MSG(("returning delayed graphic %lx",pGraphic));
  786. }
  787. return(pGraphic);
  788. }
  789. //
  790. //
  791. // Function: GetGraphicData
  792. //
  793. // Purpose: Retrieve the graphic data for copying to the clipboard. If
  794. // the data has been saved, then get a pointer to the copy (in
  795. // global memory), otherwise get it from the page.
  796. //
  797. // The memory must be released with ReleaseGraphicData as soon
  798. // as possible.
  799. //
  800. //
  801. PWB_GRAPHIC WbMainWindow::CLP_GetGraphicData(void)
  802. {
  803. PWB_GRAPHIC pHeader;
  804. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_GetGraphicData");
  805. // if we have not saved the graphic's contents, then we must have a
  806. // valid page and graphic handle, since we get the graphic data now
  807. pHeader = m_pDelayedDataClip;
  808. if (pHeader == NULL)
  809. {
  810. ASSERT(m_hPageClip != WB_PAGE_HANDLE_NULL);
  811. ASSERT(m_hGraphicClip != NULL);
  812. pHeader = PG_GetData(m_hPageClip, m_hGraphicClip);
  813. }
  814. return(pHeader);
  815. }
  816. //
  817. //
  818. // Function: ReleaseGraphicData
  819. //
  820. // Purpose: Release the data which was accessed by an earlier call to
  821. // GetGraphicData.
  822. //
  823. //
  824. void WbMainWindow::CLP_ReleaseGraphicData(PWB_GRAPHIC pHeader)
  825. {
  826. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_ReleaseGraphicData");
  827. // release it in the right way, depending on whether we got the data
  828. // from the page, or just got a pointer to existing global data in
  829. // CLP_GetGraphicData
  830. if (m_pDelayedDataClip == NULL)
  831. {
  832. g_pwbCore->WBP_GraphicRelease(m_hPageClip, m_hGraphicClip, pHeader);
  833. }
  834. }
  835. //
  836. //
  837. // Function: SaveDelayedGraphic
  838. //
  839. // Purpose: Create a copy of the graphic which was copied to the
  840. // clipboard with delayed rendering.
  841. //
  842. //
  843. void WbMainWindow::CLP_SaveDelayedGraphic(void)
  844. {
  845. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_SaveDelayedGraphic");
  846. // Free any previously-held delayed graphic
  847. CLP_FreeDelayedGraphic();
  848. // Get the new delayed graphic object and a pointer to its data
  849. DCWbGraphic* pGraphic = CLP_GetGraphic();
  850. TRACE_MSG(("Got graphic at address %lx",pGraphic));
  851. m_pDelayedGraphicClip = pGraphic->Copy();
  852. TRACE_MSG(("Copied to %lx",m_pDelayedGraphicClip));
  853. delete pGraphic;
  854. PWB_GRAPHIC pHeader = PG_GetData(m_hPageClip, m_hGraphicClip);
  855. TRACE_MSG(("Graphic header %lx",pHeader));
  856. // Copy the graphic's data into global memory, and save the handle
  857. m_pDelayedDataClip = (PWB_GRAPHIC)::GlobalAlloc(GPTR, pHeader->length);
  858. if (m_pDelayedDataClip != NULL)
  859. {
  860. // Copy the graphic data to the allocated memory
  861. memcpy(m_pDelayedDataClip, pHeader, pHeader->length);
  862. }
  863. // Release the graphic's data (now we have our own copy)
  864. g_pwbCore->WBP_GraphicRelease(m_hPageClip, m_hGraphicClip, pHeader);
  865. // set the graphic handle to NULL because we won't be using it
  866. // any more
  867. m_hPageClip = WB_PAGE_HANDLE_NULL;
  868. m_hGraphicClip = NULL;
  869. }
  870. //
  871. //
  872. // Function: FreeDelayedGraphic
  873. //
  874. // Purpose: Free the copy of the delayed graphic (if any).
  875. //
  876. //
  877. void WbMainWindow::CLP_FreeDelayedGraphic(void)
  878. {
  879. MLZ_EntryOut(ZONE_FUNCTION, "WbMainWindow::CLP_FreeDelayedGraphic");
  880. if (m_pDelayedGraphicClip != NULL)
  881. {
  882. // free the graphic object
  883. TRACE_MSG(("Freeing delayed graphic"));
  884. delete m_pDelayedGraphicClip;
  885. m_pDelayedGraphicClip = NULL;
  886. }
  887. if (m_pDelayedDataClip != NULL)
  888. {
  889. // free the associated data
  890. TRACE_MSG(("Freeing delayed memory %x", m_pDelayedDataClip));
  891. ::GlobalFree((HGLOBAL)m_pDelayedDataClip);
  892. m_pDelayedDataClip = NULL;
  893. }
  894. }