Leaked source code of windows server 2003
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.

1050 lines
27 KiB

  1. //
  2. // GRPTR.CPP
  3. // More Graphic Objects
  4. //
  5. // Copyright Microsoft 1998-
  6. //
  7. //
  8. // The remote pointer is handled by blitting to and from the screen to a
  9. // memory bitmap rather than letting Windows draw it. This is to get a
  10. // reasonably continuous tracking of the pointer.
  11. //
  12. // In order to do this we create a memory bitmap that is the pointer size
  13. // times 2 by 3. The top left square of the 2*3 array is used to hold the
  14. // screen contents before the pointer is written. It may be used at any
  15. // time to remove the pointer from the screen. The lower 2*2 square is
  16. // used to hold the currently displayed pointer plus surrounding screen
  17. // bits. The pointer may be anywhere within the 2*2 sector, as defined by
  18. // "offset".
  19. //
  20. // ------------------
  21. // | | |
  22. // | | |
  23. // | saved | unused |
  24. // | | |
  25. // | | |
  26. // |----------------|
  27. // | |
  28. // | -------- |
  29. // | | | |
  30. // | | rem | |
  31. // | | ptr | |
  32. // | | | |
  33. // | | | |
  34. // | -------- |
  35. // | |
  36. // ------------------
  37. //
  38. // Operations consist of
  39. //
  40. // If there is no pointer there currently then
  41. //
  42. // 1. Copy lower 2*2 segment from the screen
  43. // 2. Save the remote pointer square to the saved area
  44. // 3. Draw the icon into rem ptr square
  45. // 4. Blit the 2*2 back to the screen
  46. //
  47. // If there is an old rem ptr and the new one lies within the same 2*2 area
  48. // then as above but copy "saved" to "old rem ptr" before step 2 to remove
  49. // it.
  50. //
  51. // If the new pointer lies off the old square then copy "saved" back to the
  52. // display before proceeding as in the no pointer case.
  53. //
  54. //
  55. // PRECOMP
  56. #include "precomp.h"
  57. //
  58. // Runtime class information
  59. //
  60. //
  61. // Local defines
  62. //
  63. #define DRAW 1
  64. #define UNDRAW 2
  65. //
  66. //
  67. // Function: ~DCWbColorToIconMap
  68. //
  69. // Purpose: Destructor
  70. //
  71. //
  72. DCWbColorToIconMap::~DCWbColorToIconMap(void)
  73. {
  74. // Delete all the objects in the user map and release the icon handles
  75. HICON hIcon;
  76. POSITION position = GetHeadPosition();
  77. COLOREDICON * pColoredIcon;
  78. while (position)
  79. {
  80. pColoredIcon = (COLOREDICON *)GetNext(position);
  81. // Destroy the icon
  82. if (pColoredIcon != NULL)
  83. {
  84. ::DestroyIcon(pColoredIcon->hIcon);
  85. delete pColoredIcon;
  86. }
  87. }
  88. EmptyList();
  89. }
  90. //
  91. //
  92. // Function: DCWbGraphicPointer::DCWbGraphicPointer
  93. //
  94. // Purpose: Constructor for remote pointer objects
  95. //
  96. //
  97. DCWbGraphicPointer::DCWbGraphicPointer(WbUser* _pUser)
  98. {
  99. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::DCWbGraphicPointer");
  100. // We haven't yet created our mem DC
  101. m_hSaveBitmap = NULL;
  102. m_hOldBitmap = NULL;
  103. // Save the user pointer
  104. ASSERT(_pUser != NULL);
  105. m_pUser = _pUser;
  106. // Set the bounding rectangle of the object
  107. m_uiIconWidth = ::GetSystemMetrics(SM_CXICON);
  108. m_uiIconHeight = ::GetSystemMetrics(SM_CYICON);
  109. m_boundsRect.left = 0;
  110. m_boundsRect.top = 0;
  111. m_boundsRect.right = m_uiIconWidth;
  112. m_boundsRect.bottom = m_uiIconHeight;
  113. // Show that the object is not drawn
  114. m_bDrawn = FALSE;
  115. ::SetRectEmpty(&m_rectLastDrawn);
  116. // Show that we do not have an icon for drawing yet
  117. m_hIcon = NULL;
  118. // Create a memory DC compatible with the display
  119. m_hMemDC = ::CreateCompatibleDC(NULL);
  120. }
  121. //
  122. //
  123. // Function: DCWbGraphicPointer::~DCWbGraphicPointer
  124. //
  125. // Purpose: Destructor for remote pointer objects
  126. //
  127. //
  128. DCWbGraphicPointer::~DCWbGraphicPointer(void)
  129. {
  130. // Restore the original bitmap to the memory DC
  131. if (m_hOldBitmap != NULL)
  132. {
  133. SelectBitmap(m_hMemDC, m_hOldBitmap);
  134. m_hOldBitmap = NULL;
  135. }
  136. if (m_hSaveBitmap != NULL)
  137. {
  138. DeleteBitmap(m_hSaveBitmap);
  139. m_hSaveBitmap = NULL;
  140. }
  141. if (m_hMemDC != NULL)
  142. {
  143. ::DeleteDC(m_hMemDC);
  144. m_hMemDC = NULL;
  145. }
  146. if(g_pMain)
  147. {
  148. g_pMain->RemoveGraphicPointer(this);
  149. }
  150. }
  151. //
  152. //
  153. // Function: Color
  154. //
  155. // Purpose: Set the color of the pointer. An icon of the appropriate
  156. // color is created if necessary.
  157. //
  158. //
  159. void DCWbGraphicPointer::SetColor(COLORREF newColor)
  160. {
  161. newColor = SET_PALETTERGB( newColor ); // make it use color matching
  162. // If this is a color change
  163. if (m_clrPenColor != newColor)
  164. {
  165. COLOREDICON* pColoredIcon;
  166. POSITION position = g_pUsers->GetHeadPosition();
  167. BOOL found = FALSE;
  168. while (position && !found)
  169. {
  170. pColoredIcon = (COLOREDICON *)g_pIcons->GetNext(position);
  171. if (newColor == pColoredIcon->color)
  172. {
  173. found = TRUE;
  174. }
  175. }
  176. if(!found)
  177. {
  178. m_hIcon = CreateColoredIcon(newColor);
  179. }
  180. // Set the color
  181. m_clrPenColor = newColor;
  182. }
  183. }
  184. //
  185. //
  186. // Function: CreateSaveBitmap
  187. //
  188. // Purpose: Create a bitmap for saving the bits under the pointer.
  189. //
  190. //
  191. void DCWbGraphicPointer::CreateSaveBitmap(WbDrawingArea * pDrawingArea)
  192. {
  193. HBITMAP hImage = NULL;
  194. HBITMAP hOld = NULL;
  195. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::CreateSaveBitmap");
  196. // If we already have a save bitmap, exit immediately
  197. if (m_hSaveBitmap != NULL)
  198. {
  199. TRACE_MSG(("Already have save bitmap"));
  200. return;
  201. }
  202. // Load the pointer bitmap
  203. hImage = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(REMOTEPOINTERXORDATA));
  204. if (!hImage)
  205. {
  206. ERROR_OUT(("Could not load pointer bitmap"));
  207. goto CleanupSaveBitmap;
  208. }
  209. // Select the pointer bitmap into the memory DC. We do this to
  210. // allow creation of a compatible bitmap (otherwise we would get
  211. // a default monochrome format when calling CreateCompatibleBitmap).
  212. hOld = SelectBitmap(m_hMemDC, hImage);
  213. if (hOld == NULL)
  214. {
  215. ERROR_OUT(("Could not select bitmap into DC"));
  216. goto CleanupSaveBitmap;
  217. }
  218. // Create a bitmap to save the bits under the icon. This bitmap is
  219. // created with space for building the new screen image before
  220. // blitting it to the screen.
  221. m_hSaveBitmap = ::CreateCompatibleBitmap(m_hMemDC,
  222. 2 * m_uiIconWidth * pDrawingArea->ZoomOption(),
  223. 3 * m_uiIconHeight * pDrawingArea->ZoomOption());
  224. if (!m_hSaveBitmap)
  225. {
  226. ERROR_OUT(("Could not create save bitmap"));
  227. goto CleanupSaveBitmap;
  228. }
  229. // Select in the save bits bitmap
  230. m_hOldBitmap = hOld;
  231. hOld = NULL;
  232. SelectBitmap(m_hMemDC, m_hSaveBitmap);
  233. // Default zoom factor is 1
  234. m_iZoomSaved = 1;
  235. CleanupSaveBitmap:
  236. if (hOld != NULL)
  237. {
  238. // Put back the original bitmap--we failed to create the save bmp
  239. SelectBitmap(m_hMemDC, hOld);
  240. }
  241. if (hImage != NULL)
  242. {
  243. ::DeleteBitmap(hImage);
  244. }
  245. }
  246. //
  247. //
  248. // Function: CreateColoredIcon
  249. //
  250. // Purpose: Create an icon of the correct color for this pointer. The
  251. // DCWbGraphicPointer class keeps a static list of icons
  252. // created previously. These are re-used as necessary.
  253. //
  254. //
  255. HICON DCWbGraphicPointer::CreateColoredIcon(COLORREF color)
  256. {
  257. HICON hColoredIcon = NULL;
  258. HBRUSH hBrush = NULL;
  259. HBRUSH hOldBrush;
  260. HBITMAP hImage = NULL;
  261. HBITMAP hOldBitmap;
  262. HBITMAP hMask = NULL;
  263. COLOREDICON *pColoredIcon;
  264. ICONINFO ii;
  265. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::CreateColoredIcon");
  266. hBrush = ::CreateSolidBrush(color);
  267. if (!hBrush)
  268. {
  269. TRACE_MSG(("Couldn't create color brush"));
  270. goto CreateIconCleanup;
  271. }
  272. // Load the mask bitmap
  273. hMask = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(REMOTEPOINTERANDMASK));
  274. if (!hMask)
  275. {
  276. TRACE_MSG(("Could not load mask bitmap"));
  277. goto CreateIconCleanup;
  278. }
  279. // Load the image bitmap
  280. hImage = ::LoadBitmap(g_hInstance, MAKEINTRESOURCE(REMOTEPOINTERXORDATA));
  281. if (!hImage)
  282. {
  283. TRACE_MSG(("Could not load pointer bitmap"));
  284. goto CreateIconCleanup;
  285. }
  286. // Select in the icon color
  287. hOldBrush = SelectBrush(m_hMemDC, hBrush);
  288. // Select the image bitmap into the memory DC
  289. hOldBitmap = SelectBitmap(m_hMemDC, hImage);
  290. // Fill the image bitmap with color
  291. ::FloodFill(m_hMemDC, m_uiIconWidth / 2, m_uiIconHeight / 2, RGB(0, 0, 0));
  292. SelectBitmap(m_hMemDC, hOldBitmap);
  293. SelectBrush(m_hMemDC, hOldBrush);
  294. //
  295. // Now use the image and mask bitmaps to create an icon
  296. //
  297. ii.fIcon = TRUE;
  298. ii.xHotspot = 0;
  299. ii.yHotspot = 0;
  300. ii.hbmMask = hMask;
  301. ii.hbmColor = hImage;
  302. // Create a new icon from the data and mask
  303. hColoredIcon = ::CreateIconIndirect(&ii);
  304. // Add the new icon to the static list
  305. ASSERT(g_pIcons);
  306. pColoredIcon = new COLOREDICON;
  307. if (!pColoredIcon)
  308. {
  309. ERROR_OUT(("Failed to allocate COLORICON object"));
  310. DestroyIcon(hColoredIcon);
  311. hColoredIcon = NULL;
  312. }
  313. else
  314. {
  315. pColoredIcon->color = color;
  316. pColoredIcon->hIcon = hColoredIcon;
  317. g_pIcons->AddTail(pColoredIcon);
  318. }
  319. CreateIconCleanup:
  320. // Free the image bitmap
  321. if (hImage != NULL)
  322. {
  323. ::DeleteBitmap(hImage);
  324. }
  325. // Free the mask bitmap
  326. if (hMask != NULL)
  327. {
  328. ::DeleteBitmap(hMask);
  329. }
  330. if (hBrush != NULL)
  331. {
  332. ::DeleteBrush(hBrush);
  333. }
  334. return(hColoredIcon);
  335. }
  336. //
  337. //
  338. // Function: GetPage
  339. //
  340. // Purpose: Return the page of the pointer. An invalid page is returned
  341. // if the pointer is not active.
  342. //
  343. //
  344. WB_PAGE_HANDLE DCWbGraphicPointer::GetPage(void) const
  345. {
  346. // If this pointer is active, return its actual page
  347. if (m_bActive == TRUE)
  348. return(m_hPage);
  349. else
  350. return(WB_PAGE_HANDLE_NULL);
  351. }
  352. void DCWbGraphicPointer::SetPage(WB_PAGE_HANDLE hNewPage)
  353. {
  354. m_hPage = hNewPage;
  355. }
  356. //
  357. //
  358. // Function: DrawnRect
  359. //
  360. // Purpose: Return the rectangle where the pointer was last drawn
  361. //
  362. //
  363. void DCWbGraphicPointer::GetDrawnRect(LPRECT lprc)
  364. {
  365. ::SetRectEmpty(lprc);
  366. if (m_bDrawn)
  367. {
  368. *lprc = m_rectLastDrawn;
  369. }
  370. }
  371. //
  372. //
  373. // Function: IsLocalPointer
  374. //
  375. // Purpose: Return TRUE if this is the local user's pointer
  376. //
  377. //
  378. BOOL DCWbGraphicPointer::IsLocalPointer(void) const
  379. {
  380. ASSERT(m_pUser != NULL);
  381. return m_pUser->IsLocalUser();
  382. }
  383. //
  384. //
  385. // Function: operator==
  386. //
  387. // Purpose: Return TRUE if the specified remote pointer is the same as
  388. // this one.
  389. //
  390. //
  391. BOOL DCWbGraphicPointer::operator==(const DCWbGraphicPointer& pointer) const
  392. {
  393. return (m_pUser == pointer.m_pUser);
  394. }
  395. //
  396. //
  397. // Function: operator!=
  398. //
  399. // Purpose: Return FALSE if the specified pointer is the same as this
  400. //
  401. //
  402. BOOL DCWbGraphicPointer::operator!=(const DCWbGraphicPointer& pointer) const
  403. {
  404. return (!((*this) == pointer));
  405. }
  406. //
  407. //
  408. // Function: DCWbGraphicPointer::Draw
  409. //
  410. // Purpose: Draw the pointer object without saving the bits under it
  411. //
  412. //
  413. void DCWbGraphicPointer::Draw(HDC hDC, WbDrawingArea * pDrawingArea)
  414. {
  415. RECT rcUpdate;
  416. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::Draw");
  417. rcUpdate = m_boundsRect;
  418. // Check that we have an icon to draw
  419. if (m_hIcon == NULL)
  420. {
  421. WARNING_OUT(("Icon not found"));
  422. return;
  423. }
  424. if (pDrawingArea == NULL)
  425. {
  426. ERROR_OUT(("No drawing area passed in"));
  427. return;
  428. }
  429. // Create the save bitmap if necessary
  430. CreateSaveBitmap(pDrawingArea);
  431. PointerDC(hDC, pDrawingArea, &rcUpdate, pDrawingArea->ZoomFactor());
  432. // Draw the icon to the DC passed
  433. ::DrawIcon(hDC, rcUpdate.left, rcUpdate.top, m_hIcon);
  434. SurfaceDC(hDC, pDrawingArea);
  435. }
  436. //
  437. //
  438. // Function: DCWbGraphicPointer::DrawSave
  439. //
  440. // Purpose: Draw the pointer object after saving the bits under it
  441. //
  442. //
  443. void DCWbGraphicPointer::DrawSave(HDC hDC, WbDrawingArea * pDrawingArea)
  444. {
  445. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::DrawSave");
  446. // Pretend that we are not drawn
  447. m_bDrawn = FALSE;
  448. // Call the redraw member
  449. Redraw(hDC, pDrawingArea);
  450. }
  451. //
  452. //
  453. // Function: DCWbGraphicPointer::Redraw
  454. //
  455. // Purpose: Draw the pointer in its current position after erasing it
  456. // from the DC using the saved version.
  457. //
  458. //
  459. void DCWbGraphicPointer::Redraw(HDC hDC, WbDrawingArea * pDrawingArea)
  460. {
  461. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::Redraw");
  462. RECT clipBox;
  463. ::GetClipBox(hDC, &clipBox);
  464. // Create the save bitmap if necessary
  465. CreateSaveBitmap(pDrawingArea);
  466. // If we are not yet drawn, we must copy data from the screen
  467. // to initialize the save bitmaps.
  468. if (!m_bDrawn)
  469. {
  470. TRACE_MSG(("Pointer not yet drawn"));
  471. // Only do anything if the pointer will be visible
  472. if (::IntersectRect(&clipBox, &clipBox, &m_boundsRect))
  473. {
  474. // Pretend that we were drawn at the same place and copy the screen
  475. // bits into memory to build the image.
  476. GetBoundsRect(&m_rectLastDrawn);
  477. CopyFromScreen(hDC, pDrawingArea);
  478. // Save the bits under the pointer
  479. SaveMemory();
  480. // Draw the pointer
  481. DrawMemory();
  482. // Copy the new image to the screen
  483. CopyToScreen(hDC, pDrawingArea);
  484. // Show that the pointer is now drawn
  485. m_bDrawn = TRUE;
  486. }
  487. }
  488. else
  489. {
  490. TRACE_MSG(("Pointer already drawn at %d %d",
  491. m_rectLastDrawn.left, m_rectLastDrawn.top));
  492. // Calculate the update rectangle
  493. RECT rcUpdate;
  494. GetBoundsRect(&rcUpdate);
  495. ::UnionRect(&rcUpdate, &rcUpdate, &m_rectLastDrawn);
  496. // Check whether any of the update is visible
  497. if (::IntersectRect(&clipBox, &clipBox, &rcUpdate))
  498. {
  499. // Check whether we can do better by drawing in memory before
  500. // going to the screen.
  501. GetBoundsRect(&rcUpdate);
  502. if (::IntersectRect(&rcUpdate, &rcUpdate, &m_rectLastDrawn))
  503. {
  504. TRACE_MSG(("Drawing in memory first"));
  505. // The old and new positions of the pointers overlap. We can
  506. // reduce flicker by building the new image in memory and
  507. // blitting to the screen.
  508. // Copy overlap rectangle to memory
  509. CopyFromScreen(hDC, pDrawingArea);
  510. // Undraw the pointer from the overlap rectangle
  511. UndrawMemory();
  512. // Save the bits under the new pointer position (from memory)
  513. SaveMemory();
  514. // Draw the new pointer into memory
  515. DrawMemory();
  516. // Copy the new image to the screen
  517. CopyToScreen(hDC, pDrawingArea);
  518. }
  519. else
  520. {
  521. TRACE_MSG(("No overlap - remove and redraw"));
  522. // The old and new pointer positions do not overlap. We can remove
  523. // the old pointer and draw the new in the usual way.
  524. // Copy the saved bits under the pointer to the screen
  525. UndrawScreen(hDC, pDrawingArea);
  526. // Pretend that we were drawn at the same place and copy the screen
  527. // bits into memory to build the image.
  528. GetBoundsRect(&m_rectLastDrawn);
  529. CopyFromScreen(hDC, pDrawingArea);
  530. // Save the bits under the pointer
  531. SaveMemory();
  532. // Draw the pointer
  533. DrawMemory();
  534. // Copy the new image to the screen
  535. CopyToScreen(hDC, pDrawingArea);
  536. }
  537. // Show that the pointer is now drawn
  538. m_bDrawn = TRUE;
  539. }
  540. }
  541. // If the pointer was drawn, save the rectangle in which it was drawn
  542. if (m_bDrawn)
  543. {
  544. GetBoundsRect(&m_rectLastDrawn);
  545. }
  546. }
  547. //
  548. //
  549. // Function: DCWbGraphicPointer::Undraw
  550. //
  551. // Purpose: Draw the marker object
  552. //
  553. //
  554. void DCWbGraphicPointer::Undraw(HDC hDC, WbDrawingArea * pDrawingArea)
  555. {
  556. // If we are not drawn, do nothing
  557. if (m_bDrawn)
  558. {
  559. // Create the save bitmap if necessary
  560. CreateSaveBitmap(pDrawingArea);
  561. // Copy the saved bits onto the screen
  562. UndrawScreen(hDC, pDrawingArea);
  563. // Show that we are no longer drawn
  564. m_bDrawn = FALSE;
  565. }
  566. }
  567. //
  568. //
  569. // Function: CopyFromScreen
  570. //
  571. // Purpose: Save the bits around the old and new pointer positions
  572. // to memory.
  573. //
  574. //
  575. BOOL DCWbGraphicPointer::CopyFromScreen(HDC hDC, WbDrawingArea * pDrawingArea)
  576. {
  577. BOOL bResult = FALSE;
  578. RECT rcUpdate;
  579. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::CopyFromScreen");
  580. // Get the update rectangle needed
  581. GetBoundsRect(&rcUpdate);
  582. ::UnionRect(&rcUpdate, &rcUpdate, &m_rectLastDrawn);
  583. PointerDC(hDC, pDrawingArea, &rcUpdate, pDrawingArea->ZoomFactor());
  584. // Copy the bits
  585. bResult = ::BitBlt(m_hMemDC, 0,
  586. m_uiIconHeight * m_iZoomSaved,
  587. rcUpdate.right - rcUpdate.left,
  588. rcUpdate.bottom - rcUpdate.top,
  589. hDC, rcUpdate.left, rcUpdate.top, SRCCOPY);
  590. if (!bResult)
  591. {
  592. WARNING_OUT(("CopyFromScreen - Could not copy to bitmap"));
  593. }
  594. SurfaceDC(hDC, pDrawingArea);
  595. return(bResult);
  596. }
  597. //
  598. //
  599. // Function: CopyToScreen
  600. //
  601. // Purpose: Copy the saved bits around the old and new pointers back
  602. // to the screen.
  603. //
  604. //
  605. BOOL DCWbGraphicPointer::CopyToScreen(HDC hDC, WbDrawingArea * pDrawingArea)
  606. {
  607. BOOL bResult = FALSE;
  608. RECT rcUpdate;
  609. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::CopyToScreen");
  610. // Get the update rectangle needed
  611. GetBoundsRect(&rcUpdate);
  612. ::UnionRect(&rcUpdate, &rcUpdate, &m_rectLastDrawn);
  613. PointerDC(hDC, pDrawingArea, &rcUpdate);
  614. bResult = ::BitBlt(hDC, rcUpdate.left, rcUpdate.top,
  615. rcUpdate.right - rcUpdate.left, rcUpdate.bottom - rcUpdate.top,
  616. m_hMemDC, 0, m_uiIconHeight * m_iZoomSaved, SRCCOPY);
  617. if (!bResult)
  618. {
  619. WARNING_OUT(("CopyToScreen - Could not copy from bitmap"));
  620. }
  621. SurfaceDC(hDC, pDrawingArea);
  622. return(bResult);
  623. }
  624. //
  625. //
  626. // Function: UndrawMemory
  627. //
  628. // Purpose: Copy the saved bits under the pointer to the memory copy of
  629. // the screen, thus erasing the pointer from the image.
  630. //
  631. //
  632. BOOL DCWbGraphicPointer::UndrawMemory()
  633. {
  634. BOOL bResult = FALSE;
  635. RECT rcUpdate;
  636. SIZE offset;
  637. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::UndrawMemory");
  638. // Get the update rectangle needed
  639. GetBoundsRect(&rcUpdate);
  640. ::UnionRect(&rcUpdate, &rcUpdate, &m_rectLastDrawn);
  641. offset.cx = m_rectLastDrawn.left - rcUpdate.left;
  642. offset.cy = m_rectLastDrawn.top - rcUpdate.top;
  643. bResult = ::BitBlt(m_hMemDC, offset.cx * m_iZoomSaved,
  644. (m_uiIconHeight + offset.cy) * m_iZoomSaved,
  645. m_uiIconWidth * m_iZoomSaved,
  646. m_uiIconHeight * m_iZoomSaved,
  647. m_hMemDC,
  648. 0,
  649. 0,
  650. SRCCOPY);
  651. if (bResult == FALSE)
  652. {
  653. WARNING_OUT(("UndrawMemory - Could not copy from bitmap"));
  654. }
  655. TRACE_MSG(("Copied to memory %d,%d from memory %d,%d size %d,%d",
  656. offset.cx * m_iZoomSaved,
  657. (m_uiIconHeight + offset.cy) * m_iZoomSaved,
  658. 0,
  659. 0,
  660. m_uiIconWidth * m_iZoomSaved,
  661. m_uiIconHeight * m_iZoomSaved));
  662. return(bResult);
  663. }
  664. //
  665. //
  666. // Function: SaveMemory
  667. //
  668. // Purpose: Copy the area of the memory image that will be under the
  669. // pointer to the save area.
  670. //
  671. //
  672. BOOL DCWbGraphicPointer::SaveMemory(void)
  673. {
  674. BOOL bResult = FALSE;
  675. RECT rcUpdate;
  676. SIZE offset;
  677. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::SaveMemory");
  678. // Get the update rectangle needed
  679. GetBoundsRect(&rcUpdate);
  680. ::UnionRect(&rcUpdate, &rcUpdate, &m_rectLastDrawn);
  681. offset.cx = m_boundsRect.left - rcUpdate.left;
  682. offset.cy = m_boundsRect.top - rcUpdate.top;
  683. bResult = ::BitBlt(m_hMemDC, 0,
  684. 0,
  685. m_uiIconWidth * m_iZoomSaved,
  686. m_uiIconHeight * m_iZoomSaved,
  687. m_hMemDC,
  688. offset.cx * m_iZoomSaved,
  689. (m_uiIconHeight + offset.cy) * m_iZoomSaved,
  690. SRCCOPY);
  691. if (bResult == FALSE)
  692. {
  693. TRACE_MSG(("SaveMemory - Could not copy from bitmap"));
  694. }
  695. TRACE_MSG(("Copied to memory %d,%d from memory %d,%d size %d,%d",
  696. 0,
  697. 0,
  698. offset.cx * m_iZoomSaved,
  699. (m_uiIconHeight + offset.cy) * m_iZoomSaved,
  700. m_uiIconWidth * m_iZoomSaved,
  701. m_uiIconHeight * m_iZoomSaved));
  702. return(bResult);
  703. }
  704. //
  705. //
  706. // Function: DrawMemory
  707. //
  708. // Purpose: Draw the pointer onto the memory image copy.
  709. //
  710. //
  711. BOOL DCWbGraphicPointer::DrawMemory(void)
  712. {
  713. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::DrawMemory");
  714. BOOL bResult = FALSE;
  715. // Check that we have an icon to draw
  716. if (m_hIcon == NULL)
  717. {
  718. WARNING_OUT(("No icon to draw"));
  719. }
  720. else
  721. {
  722. RECT rcUpdate;
  723. SIZE offset;
  724. // Get the update rectangle needed
  725. GetBoundsRect(&rcUpdate);
  726. ::UnionRect(&rcUpdate, &rcUpdate, &m_rectLastDrawn);
  727. offset.cx = m_boundsRect.left - rcUpdate.left;
  728. offset.cy = m_boundsRect.top - rcUpdate.top;
  729. // Draw the icon to the DC passed
  730. bResult = ::DrawIcon(m_hMemDC, offset.cx * m_iZoomSaved,
  731. (m_uiIconHeight + offset.cy) * m_iZoomSaved +
  732. (m_uiIconHeight * (m_iZoomSaved - 1))/2,
  733. m_hIcon);
  734. if (bResult == FALSE)
  735. {
  736. WARNING_OUT(("DrawMemory - Could not draw icon"));
  737. }
  738. TRACE_MSG(("Write pointer to memory at %d,%d",
  739. offset.cx * m_iZoomSaved,
  740. (m_uiIconHeight + offset.cy) * m_iZoomSaved +
  741. (m_uiIconHeight * (m_iZoomSaved - 1))/2));
  742. }
  743. return(bResult);
  744. }
  745. //
  746. //
  747. // Function: UndrawScreen
  748. //
  749. // Purpose: Copy the saved bits under the pointer to the screen.
  750. //
  751. //
  752. BOOL DCWbGraphicPointer::UndrawScreen(HDC hDC, WbDrawingArea * pDrawingArea)
  753. {
  754. BOOL bResult = FALSE;
  755. RECT rcUpdate;
  756. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::UndrawScreen");
  757. rcUpdate = m_rectLastDrawn;
  758. PointerDC(hDC, pDrawingArea, &rcUpdate);
  759. // We are undrawing - copy the saved bits to the DC passed
  760. bResult = ::BitBlt(hDC, rcUpdate.left, rcUpdate.top,
  761. rcUpdate.right - rcUpdate.left, rcUpdate.bottom - rcUpdate.top,
  762. m_hMemDC, 0, 0, SRCCOPY);
  763. if (!bResult)
  764. {
  765. WARNING_OUT(("UndrawScreen - Could not copy from bitmap"));
  766. }
  767. SurfaceDC(hDC, pDrawingArea);
  768. return(bResult);
  769. }
  770. //
  771. //
  772. // Function: Update
  773. //
  774. // Purpose: Update the pointer information stored in the user
  775. // information.
  776. //
  777. //
  778. void DCWbGraphicPointer::Update(void)
  779. {
  780. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::Update");
  781. // Only do the update if we have been changed
  782. if (m_bChanged)
  783. {
  784. // Make the update (the pointer information is held in the associated
  785. // user object)
  786. ASSERT(m_pUser != NULL);
  787. m_pUser->Update();
  788. // Show that we have not changed since the last update
  789. m_bChanged = FALSE;
  790. }
  791. }
  792. //
  793. //
  794. // Function: SetActive
  795. //
  796. // Purpose: Update the pointer information to show that the pointer
  797. // is now active.
  798. //
  799. //
  800. void DCWbGraphicPointer::SetActive(WB_PAGE_HANDLE hPage, POINT point)
  801. {
  802. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::SetActive");
  803. // Set the member variables
  804. MoveTo(point.x, point.y);
  805. m_hPage = hPage;
  806. m_bActive = TRUE;
  807. m_bChanged = TRUE;
  808. // Distribute the update
  809. Update();
  810. }
  811. //
  812. //
  813. // Function: SetInactive
  814. //
  815. // Purpose: Update the pointer information to show that the pointer
  816. // is no longer active.
  817. //
  818. //
  819. void DCWbGraphicPointer::SetInactive(void)
  820. {
  821. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::SetInactive");
  822. // Set the member variables
  823. m_bActive = FALSE;
  824. m_bChanged = TRUE;
  825. // Distribute the update
  826. Update();
  827. }
  828. //
  829. //
  830. // Function: PointerDC
  831. //
  832. // Purpose: Scale the DC to 1:1, set a zero origin and convert the
  833. // supplied rectangle into window coordinates. This is because
  834. // we have to do the zoom mapping ourselves when we are doing
  835. // remote pointer blitting, otherwise the system does
  836. // stretchblits and screws up. Note that the SurfaceToClient
  837. // function gives us a client rectangle (ie it is 3 * as big
  838. // when we are zoomed)
  839. //
  840. //
  841. void DCWbGraphicPointer::PointerDC
  842. (
  843. HDC hDC,
  844. WbDrawingArea * pDrawingArea,
  845. LPRECT lprc,
  846. int zoom
  847. )
  848. {
  849. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::PointerDC");
  850. // default zoom to be the saved value
  851. if (zoom == 0)
  852. {
  853. zoom = m_iZoomSaved;
  854. }
  855. else
  856. {
  857. m_iZoomSaved = zoom;
  858. }
  859. // If we are currently zoomed then do the scaling
  860. if (zoom != 1)
  861. {
  862. ::ScaleViewportExtEx(hDC, 1, zoom, 1, zoom, NULL);
  863. TRACE_MSG(("Scaled screen viewport down by %d", zoom));
  864. pDrawingArea->SurfaceToClient(lprc);
  865. ::SetWindowOrgEx(hDC, 0, 0, NULL);
  866. }
  867. }
  868. //
  869. //
  870. // Function: SurfaceDC
  871. //
  872. // Purpose: Scale the DC back to the correct zoom factor and reset the
  873. // origin to the surface offset
  874. //
  875. //
  876. void DCWbGraphicPointer::SurfaceDC(HDC hDC, WbDrawingArea * pDrawingArea)
  877. {
  878. MLZ_EntryOut(ZONE_FUNCTION, "DCWbGraphicPointer::SurfaceDC");
  879. if (m_iZoomSaved != 1)
  880. {
  881. POINT pt;
  882. ::ScaleViewportExtEx(hDC, m_iZoomSaved, 1, m_iZoomSaved, 1, NULL);
  883. TRACE_MSG(("Scaled screen viewport up by %d", m_iZoomSaved));
  884. pDrawingArea->GetOrigin(&pt);
  885. ::SetWindowOrgEx(hDC, pt.x, pt.y, NULL);
  886. }
  887. }