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.

3782 lines
86 KiB

  1. //
  2. // DRAW.CPP
  3. // Main Drawing Window
  4. //
  5. // Copyright Microsoft 1998-
  6. //
  7. // PRECOMP
  8. #include "precomp.h"
  9. #include "nmwbobj.h"
  10. static const TCHAR szDrawClassName[] = "T126WB_DRAW";
  11. //
  12. //
  13. // Function: Constructor
  14. //
  15. // Purpose: Initialize the drawing area object
  16. //
  17. //
  18. WbDrawingArea::WbDrawingArea(void)
  19. {
  20. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::WbDrawingArea");
  21. g_pDraw = this;
  22. m_hwnd = NULL;
  23. m_hDCWindow = NULL;
  24. m_hDCCached = NULL;
  25. m_originOffset.cx = 0;
  26. m_originOffset.cy = 0;
  27. m_posScroll.x = 0;
  28. m_posScroll.y = 0;
  29. // Show that the drawing area is not zoomed
  30. m_iZoomFactor = 1;
  31. m_iZoomOption = 1;
  32. // Show that the left mouse button is up
  33. m_bLButtonDown = FALSE;
  34. m_bIgnoreNextLClick = FALSE;
  35. m_bBusy = FALSE;
  36. m_bLocked = FALSE;
  37. m_HourGlass = FALSE;
  38. m_bSync = TRUE;
  39. // Indicate that the cached zoom scroll position is invalid
  40. m_zoomRestoreScroll = FALSE;
  41. // Show that we are not currently editing text
  42. m_bGotCaret = FALSE;
  43. m_bTextEditorActive = FALSE;
  44. m_pTextEditor = NULL;
  45. // Show that no graphic object is in progress
  46. m_pGraphicTracker = NULL;
  47. // Show that the marker is not present.
  48. m_bMarkerPresent = FALSE;
  49. m_bNewMarkedGraphic = FALSE;
  50. m_pSelectedGraphic = NULL;
  51. m_bTrackingSelectRect = FALSE;
  52. // Show that no area is currently marked
  53. ::SetRectEmpty(&m_rcMarkedArea);
  54. // Show we haven't got a tool yet
  55. m_pToolCur = NULL;
  56. // Show that we dont have a page attached yet
  57. g_pCurrentWorkspace = NULL;
  58. g_pConferenceWorkspace = NULL;
  59. // Create the brush to be used to draw the marker rectangle
  60. WORD bits[] = {204, 204, 51, 51, 204, 204, 51, 51};
  61. HBITMAP hBmpMarker = ::CreateBitmap(8, 8, 1, 1, bits);
  62. m_hMarkerBrush = ::CreatePatternBrush(hBmpMarker);
  63. ::DeleteBitmap(hBmpMarker);
  64. DBG_SAVE_FILE_LINE
  65. m_pMarker = new DrawObj(rectangle_chosen, TOOLTYPE_SELECT);
  66. if(m_pMarker)
  67. {
  68. m_pMarker->SetPenColor(RGB(0,0,0), TRUE);
  69. m_pMarker->SetFillColor(RGB(255,255,255), FALSE);
  70. m_pMarker->SetLineStyle(PS_DOT);
  71. m_pMarker->SetPenThickness(1);
  72. RECT rect;
  73. ::SetRectEmpty(&rect);
  74. m_pMarker->SetRect(&rect);
  75. m_pMarker->SetBoundsRect(&rect);
  76. }
  77. }
  78. //
  79. //
  80. // Function: Destructor
  81. //
  82. // Purpose: Close down the drawing area
  83. //
  84. //
  85. WbDrawingArea::~WbDrawingArea(void)
  86. {
  87. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::~WbDrawingArea");
  88. if (m_pTextEditor != NULL)
  89. {
  90. m_pTextEditor->AbortEditGently();
  91. }
  92. if (m_pMarker != NULL)
  93. {
  94. delete m_pMarker;
  95. m_pMarker = NULL;
  96. }
  97. if (m_hMarkerBrush != NULL)
  98. {
  99. DeleteBrush(m_hMarkerBrush);
  100. m_hMarkerBrush = NULL;
  101. }
  102. if (m_hwnd != NULL)
  103. {
  104. ::DestroyWindow(m_hwnd);
  105. ASSERT(m_hwnd == NULL);
  106. }
  107. ::UnregisterClass(szDrawClassName, g_hInstance);
  108. g_pDraw = NULL;
  109. }
  110. //
  111. // WbDrawingArea::Create()
  112. //
  113. BOOL WbDrawingArea::Create(HWND hwndParent, LPCRECT lprect)
  114. {
  115. WNDCLASSEX wc;
  116. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::Create");
  117. // Get our cursor
  118. m_hCursor = ::LoadCursor(g_hInstance, MAKEINTRESOURCE( PENFREEHANDCURSOR));
  119. //
  120. // Register the window class
  121. //
  122. ZeroMemory(&wc, sizeof(wc));
  123. wc.cbSize = sizeof(wc);
  124. wc.style = CS_OWNDC;
  125. wc.lpfnWndProc = DrawWndProc;
  126. wc.hInstance = g_hInstance;
  127. wc.hCursor = m_hCursor;
  128. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  129. wc.lpszClassName = szDrawClassName;
  130. if (!::RegisterClassEx(&wc))
  131. {
  132. ERROR_OUT(("WbDraw::Create register class failed"));
  133. return(FALSE);
  134. }
  135. //
  136. // Create our window
  137. //
  138. ASSERT(m_hwnd == NULL);
  139. if (!::CreateWindowEx(WS_EX_CLIENTEDGE, szDrawClassName, NULL,
  140. WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER |
  141. WS_CLIPCHILDREN,
  142. lprect->left, lprect->top, lprect->right - lprect->left,
  143. lprect->bottom - lprect->top,
  144. hwndParent, NULL, g_hInstance, this))
  145. {
  146. ERROR_OUT(("Error creating drawing area window"));
  147. return(FALSE);
  148. }
  149. ASSERT(m_hwnd != NULL);
  150. //
  151. // Initialize remaining data members
  152. //
  153. ASSERT(!m_bBusy);
  154. ASSERT(!(m_bLocked && g_pNMWBOBJ->m_LockerID != g_MyMemberID));
  155. ASSERT(!m_HourGlass);
  156. // Start and end points of the last drawing operation
  157. m_ptStart.x = m_originOffset.cx;
  158. m_ptStart.y = m_originOffset.cy;
  159. m_ptEnd = m_ptStart;
  160. // Get the zoom factor to be used
  161. m_iZoomOption = DRAW_ZOOMFACTOR;
  162. m_hDCWindow = ::GetDC(m_hwnd);
  163. m_hDCCached = m_hDCWindow;
  164. PrimeDC(m_hDCCached);
  165. ::SetWindowOrgEx(m_hDCCached, m_originOffset.cx, m_originOffset.cy, NULL);
  166. return(TRUE);
  167. }
  168. //
  169. // DrawWndProc()
  170. // Message handler for the drawing area
  171. //
  172. LRESULT CALLBACK DrawWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  173. {
  174. LRESULT lResult = 0;
  175. WbDrawingArea * pDraw = (WbDrawingArea *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
  176. switch (message)
  177. {
  178. case WM_NCCREATE:
  179. pDraw = (WbDrawingArea *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
  180. ASSERT(pDraw);
  181. pDraw->m_hwnd = hwnd;
  182. ::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pDraw);
  183. goto DefWndProc;
  184. break;
  185. case WM_NCDESTROY:
  186. ASSERT(pDraw);
  187. //
  188. // When you call GetDC(), the HDC you get back is only valid
  189. // as long as the HWND it refers to is. So we must release
  190. // it here.
  191. //
  192. pDraw->ShutDownDC();
  193. pDraw->m_hwnd = NULL;
  194. break;
  195. case WM_PAINT:
  196. ASSERT(pDraw);
  197. pDraw->OnPaint();
  198. break;
  199. case WM_MOUSEMOVE:
  200. ASSERT(pDraw);
  201. pDraw->OnMouseMove((UINT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
  202. break;
  203. case WM_LBUTTONDOWN:
  204. ASSERT(pDraw);
  205. pDraw->DeleteSelection();
  206. pDraw->OnLButtonDown((UINT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
  207. break;
  208. case WM_LBUTTONUP:
  209. ASSERT(pDraw);
  210. pDraw->OnLButtonUp((UINT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
  211. break;
  212. case WM_CONTEXTMENU:
  213. ASSERT(pDraw);
  214. pDraw->OnContextMenu((short)LOWORD(lParam), (short)HIWORD(lParam));
  215. break;
  216. case WM_SIZE:
  217. ASSERT(pDraw);
  218. pDraw->OnSize((UINT)wParam, (short)LOWORD(lParam), (short)HIWORD(lParam));
  219. break;
  220. case WM_HSCROLL:
  221. ASSERT(pDraw);
  222. pDraw->OnHScroll(GET_WM_HSCROLL_CODE(wParam, lParam),
  223. GET_WM_HSCROLL_POS(wParam, lParam));
  224. break;
  225. case WM_MOUSEWHEEL:
  226. ASSERT(pDraw);
  227. lParam = 0;
  228. if((short) HIWORD(wParam) > 0)
  229. {
  230. wParam = SB_LINEUP;
  231. }
  232. else
  233. {
  234. wParam = SB_LINEDOWN;
  235. }
  236. pDraw->OnVScroll(GET_WM_VSCROLL_CODE(wParam, lParam),
  237. GET_WM_VSCROLL_POS(wParam, lParam));
  238. wParam = SB_ENDSCROLL;
  239. //
  240. // Just work like a vertical scroll
  241. //
  242. case WM_VSCROLL:
  243. ASSERT(pDraw);
  244. pDraw->OnVScroll(GET_WM_VSCROLL_CODE(wParam, lParam),
  245. GET_WM_VSCROLL_POS(wParam, lParam));
  246. break;
  247. case WM_CTLCOLOREDIT:
  248. ASSERT(pDraw);
  249. lResult = pDraw->OnEditColor((HDC)wParam);
  250. break;
  251. case WM_SETFOCUS:
  252. ASSERT(pDraw);
  253. pDraw->OnSetFocus();
  254. break;
  255. case WM_ACTIVATE:
  256. ASSERT(pDraw);
  257. pDraw->OnActivate(GET_WM_ACTIVATE_STATE(wParam, lParam));
  258. break;
  259. case WM_SETCURSOR:
  260. ASSERT(pDraw);
  261. lResult = pDraw->OnCursor((HWND)wParam, LOWORD(lParam), HIWORD(lParam));
  262. break;
  263. case WM_CANCELMODE:
  264. ASSERT(pDraw);
  265. pDraw->OnCancelMode();
  266. break;
  267. case WM_TIMER:
  268. ASSERT(pDraw);
  269. pDraw->OnTimer((UINT)wParam);
  270. break;
  271. default:
  272. DefWndProc:
  273. lResult = DefWindowProc(hwnd, message, wParam, lParam);
  274. break;
  275. }
  276. return(lResult);
  277. }
  278. //
  279. //
  280. // Function: RealizePalette
  281. //
  282. // Purpose: Realize the drawing area palette
  283. //
  284. //
  285. void WbDrawingArea::RealizePalette( BOOL bBackground )
  286. {
  287. UINT entriesChanged;
  288. HDC hdc = m_hDCCached;
  289. if (g_pCurrentWorkspace != NULL)
  290. {
  291. HPALETTE hPalette = PG_GetPalette();
  292. if (hPalette != NULL)
  293. {
  294. // get our 2cents in
  295. m_hOldPalette = ::SelectPalette(hdc, hPalette, bBackground);
  296. entriesChanged = ::RealizePalette(hdc);
  297. // if mapping changes go repaint
  298. if (entriesChanged > 0)
  299. ::InvalidateRect(m_hwnd, NULL, TRUE);
  300. }
  301. }
  302. }
  303. LRESULT WbDrawingArea::OnEditColor(HDC hdc)
  304. {
  305. HPALETTE hPalette = PG_GetPalette();
  306. if (hPalette != NULL)
  307. {
  308. ::SelectPalette(hdc, hPalette, FALSE);
  309. ::RealizePalette(hdc);
  310. }
  311. COLORREF rgb;
  312. m_pTextEditor->GetPenColor(&rgb);
  313. ::SetTextColor(hdc, SET_PALETTERGB( rgb) );
  314. return((LRESULT)::GetSysColorBrush(COLOR_WINDOW));
  315. }
  316. //
  317. //
  318. // Function: OnPaint
  319. //
  320. // Purpose: Paint the window. This routine is called whenever Windows
  321. // issues a WM_PAINT message for the Whiteboard window.
  322. //
  323. //
  324. void WbDrawingArea::OnPaint(void)
  325. {
  326. RECT rcUpdate;
  327. RECT rcTmp;
  328. RECT rcBounds;
  329. HDC hSavedDC;
  330. HPEN hSavedPen;
  331. HBRUSH hSavedBrush;
  332. HPALETTE hSavedPalette;
  333. HPALETTE hPalette;
  334. HFONT hSavedFont;
  335. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::OnPaint");
  336. // Get the update rectangle
  337. ::GetUpdateRect(m_hwnd, &rcUpdate, FALSE);
  338. if (Zoomed())
  339. {
  340. ::InflateRect(&rcUpdate, 1, 1);
  341. InvalidateSurfaceRect(&rcUpdate, TRUE);
  342. }
  343. // Start painting
  344. PAINTSTRUCT ps;
  345. ::BeginPaint(m_hwnd, &ps);
  346. hSavedDC = m_hDCCached;
  347. hSavedFont = m_hOldFont;
  348. hSavedPen = m_hOldPen;
  349. hSavedBrush = m_hOldBrush;
  350. hSavedPalette = m_hOldPalette;
  351. TRACE_MSG(("Flipping cache to paint DC"));
  352. m_hDCCached = ps.hdc;
  353. PrimeDC(m_hDCCached);
  354. // Only draw anything if we have a valid page attached
  355. if (g_pCurrentWorkspace != NULL )
  356. {
  357. // set palette
  358. hPalette = PG_GetPalette();
  359. if (hPalette != NULL)
  360. {
  361. m_hOldPalette = ::SelectPalette(m_hDCCached, hPalette, FALSE );
  362. ::RealizePalette(m_hDCCached);
  363. }
  364. T126Obj * pObj = NULL;
  365. WBPOSITION pos;
  366. pObj = PG_First(g_pCurrentWorkspace, &rcUpdate, FALSE);
  367. if(pObj)
  368. {
  369. pos = pObj->GetMyPosition();
  370. if(pos)
  371. {
  372. g_pCurrentWorkspace->GetNextObject(pos);
  373. }
  374. }
  375. while (pObj != NULL)
  376. {
  377. pObj->Draw(NULL, TRUE);
  378. // Get the next one
  379. if(pos)
  380. {
  381. pObj = PG_Next(g_pCurrentWorkspace, pos, &rcUpdate, FALSE);
  382. }
  383. else
  384. {
  385. break;
  386. }
  387. }
  388. if (hPalette != NULL)
  389. {
  390. ::SelectPalette(m_hDCCached, m_hOldPalette, TRUE);
  391. }
  392. // fixes painting problems for bug 2185
  393. if( TextEditActive() )
  394. {
  395. RedrawTextEditbox();
  396. }
  397. //
  398. // Draw the tracking graphic
  399. //
  400. if ((m_pGraphicTracker != NULL) && !EqualPoint(m_ptStart, m_ptEnd))
  401. {
  402. TRACE_MSG(("Drawing the tracking graphic"));
  403. m_pGraphicTracker->Draw(NULL, FALSE);
  404. }
  405. }
  406. //
  407. // Restore the DC to its original state
  408. //
  409. UnPrimeDC(m_hDCCached);
  410. m_hOldFont = hSavedFont;
  411. m_hOldPen = hSavedPen;
  412. m_hOldBrush = hSavedBrush;
  413. m_hOldPalette = hSavedPalette;
  414. m_hDCCached = hSavedDC;
  415. // Finish painting
  416. ::EndPaint(m_hwnd, &ps);
  417. }
  418. //
  419. // Selects all graphic objs contained in rectSelect. If rectSelect is
  420. // NULL then ALL objs are selected
  421. //
  422. void WbDrawingArea::SelectMarkerFromRect(LPCRECT lprcSelect)
  423. {
  424. T126Obj* pGraphic;
  425. RECT rc;
  426. ::SetRectEmpty(&rc);
  427. m_HourGlass = TRUE;
  428. SetCursorForState();
  429. WBPOSITION pos;
  430. pGraphic = NULL;
  431. pGraphic = PG_First(g_pCurrentWorkspace, lprcSelect, TRUE);
  432. if(pGraphic)
  433. {
  434. pos = pGraphic->GetMyPosition();
  435. if(pos)
  436. {
  437. g_pCurrentWorkspace->GetNextObject(pos);
  438. }
  439. }
  440. while (pGraphic != NULL)
  441. {
  442. if(pGraphic->GraphicTool() == TOOLTYPE_REMOTEPOINTER && // if it is a pointer and it is not local
  443. (!pGraphic->IAmTheOwner() || // we can't select it. Or this was a select all
  444. (pGraphic->IAmTheOwner() && lprcSelect == NULL)))
  445. {
  446. ; // don't select it
  447. }
  448. else
  449. {
  450. SelectGraphic(pGraphic, TRUE, TRUE);
  451. //
  452. // Calculate de size of the total selection
  453. //
  454. RECT selctRect;
  455. pGraphic->GetBoundsRect(&selctRect);
  456. ::UnionRect(&rc,&selctRect,&rc);
  457. }
  458. // Get the next one
  459. pGraphic = PG_Next(g_pCurrentWorkspace, pos, lprcSelect, TRUE );
  460. }
  461. m_pMarker->SetRect(&rc);
  462. m_HourGlass = FALSE;
  463. SetCursorForState();
  464. g_pMain->OnUpdateAttributes();
  465. }
  466. //
  467. //
  468. // Function: OnTimer
  469. //
  470. // Purpose: Process a timer event. These are used to update freehand and
  471. // text objects while they are being drawn/edited and to
  472. // update the remote pointer position when the mouse stops.
  473. //
  474. //
  475. void WbDrawingArea::OnTimer(UINT idTimer)
  476. {
  477. TRACE_TIMER(("WbDrawingArea::OnTimer"));
  478. // We are only interested if the user is drawing something or editing
  479. if (m_bLButtonDown == TRUE)
  480. {
  481. if(idTimer == TIMER_REMOTE_POINTER_UPDATE)
  482. {
  483. ASSERT(g_pMain->m_pLocalRemotePointer);
  484. if(g_pMain->m_pLocalRemotePointer)
  485. {
  486. if(g_pMain->m_pLocalRemotePointer->HasAnchorPointChanged())
  487. {
  488. g_pMain->m_pLocalRemotePointer->OnObjectEdit();
  489. g_pMain->m_pLocalRemotePointer->ResetAttrib();
  490. }
  491. }
  492. return;
  493. }
  494. // If the user is dragging an object or drawing a freehand line
  495. if (m_pGraphicTracker != NULL)
  496. {
  497. if(m_pGraphicTracker->HasAnchorPointChanged() || m_pGraphicTracker->HasPointListChanged())
  498. {
  499. //
  500. // If we are not added to the workspace
  501. //
  502. if(!m_pGraphicTracker->GetMyWorkspace())
  503. {
  504. m_pGraphicTracker->AddToWorkspace();
  505. }
  506. else
  507. {
  508. m_pGraphicTracker->OnObjectEdit();
  509. }
  510. }
  511. }
  512. }
  513. }
  514. //
  515. //
  516. // Function: OnSize
  517. //
  518. // Purpose: The window has been resized.
  519. //
  520. //
  521. void WbDrawingArea::OnSize(UINT nType, int cx, int cy)
  522. {
  523. // Only process this message if the window is not minimized
  524. if ( (nType == SIZEFULLSCREEN)
  525. || (nType == SIZENORMAL))
  526. {
  527. if (TextEditActive())
  528. {
  529. TextEditParentResize();
  530. }
  531. // Set the new scroll range (based on the new client area)
  532. SetScrollRange(cx, cy);
  533. // Ensure that the scroll position lies in the new scroll range
  534. ValidateScrollPos();
  535. // make page move if needed
  536. ScrollWorkspace();
  537. // Update the scroll bars
  538. ::SetScrollPos(m_hwnd, SB_HORZ, m_posScroll.x, TRUE);
  539. ::SetScrollPos(m_hwnd, SB_VERT, m_posScroll.y, TRUE);
  540. }
  541. }
  542. //
  543. //
  544. // Function: SetScrollRange
  545. //
  546. // Purpose: Set the current scroll range. The range is based on the
  547. // work surface size and the size of the client area.
  548. //
  549. //
  550. void WbDrawingArea::SetScrollRange(int cx, int cy)
  551. {
  552. SCROLLINFO scinfo;
  553. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::SetScrollRange");
  554. // If we are in zoom mode, then allow for the magnification
  555. ASSERT(m_iZoomFactor != 0);
  556. cx /= m_iZoomFactor;
  557. cy /= m_iZoomFactor;
  558. ZeroMemory( &scinfo, sizeof (SCROLLINFO) );
  559. scinfo.cbSize = sizeof (SCROLLINFO);
  560. scinfo.fMask = SIF_PAGE | SIF_RANGE|
  561. SIF_DISABLENOSCROLL;
  562. // Set the horizontal scroll range and proportional thumb size
  563. scinfo.nMin = 0;
  564. scinfo.nMax = DRAW_WIDTH - 1;
  565. scinfo.nPage = cx;
  566. ::SetScrollInfo(m_hwnd, SB_HORZ, &scinfo, FALSE);
  567. // Set the vertical scroll range and proportional thumb size
  568. scinfo.nMin = 0;
  569. scinfo.nMax = DRAW_HEIGHT - 1;
  570. scinfo.nPage = cy;
  571. ::SetScrollInfo(m_hwnd, SB_VERT, &scinfo, FALSE);
  572. }
  573. //
  574. //
  575. // Function: ValidateScrollPos
  576. //
  577. // Purpose: Ensure that the current scroll position is within the bounds
  578. // of the current scroll range. The scroll range is set to
  579. // ensure that the window on the worksurface never extends
  580. // beyond the surface boundaries.
  581. //
  582. //
  583. void WbDrawingArea::ValidateScrollPos()
  584. {
  585. int iMax;
  586. SCROLLINFO scinfo;
  587. // Validate the horixontal scroll position using proportional settings
  588. scinfo.cbSize = sizeof(scinfo);
  589. scinfo.fMask = SIF_ALL;
  590. ::GetScrollInfo(m_hwnd, SB_HORZ, &scinfo);
  591. iMax = scinfo.nMax - scinfo.nPage;
  592. m_posScroll.x = max(m_posScroll.x, 0);
  593. m_posScroll.x = min(m_posScroll.x, iMax);
  594. // Validate the vertical scroll position using proportional settings
  595. scinfo.cbSize = sizeof(scinfo);
  596. scinfo.fMask = SIF_ALL;
  597. ::GetScrollInfo(m_hwnd, SB_VERT, &scinfo);
  598. iMax = scinfo.nMax - scinfo.nPage;
  599. m_posScroll.y = max(m_posScroll.y, 0);
  600. m_posScroll.y = min(m_posScroll.y, iMax);
  601. }
  602. //
  603. //
  604. // Function: ScrollWorkspace
  605. //
  606. // Purpose: Scroll the workspace to the position set in the member
  607. // variable m_posScroll.
  608. //
  609. //
  610. void WbDrawingArea::ScrollWorkspace(void)
  611. {
  612. RECT rc;
  613. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::ScrollWorkspace");
  614. // Do the scroll
  615. DoScrollWorkspace();
  616. if(Zoomed())
  617. {
  618. // Tell the parent that the scroll position has changed
  619. HWND hwndParent;
  620. hwndParent = ::GetParent(m_hwnd);
  621. if (hwndParent != NULL)
  622. {
  623. ::PostMessage(hwndParent, WM_USER_PRIVATE_PARENTNOTIFY, WM_VSCROLL, 0L);
  624. }
  625. }
  626. }
  627. //
  628. //
  629. // Function: DoScrollWorkspace
  630. //
  631. // Purpose: Scroll the workspace to the position set in the member
  632. // variable m_posScroll.
  633. //
  634. //
  635. void WbDrawingArea::DoScrollWorkspace()
  636. {
  637. // Validate the scroll position
  638. ValidateScrollPos();
  639. // Set the scroll box position
  640. ::SetScrollPos(m_hwnd, SB_HORZ, m_posScroll.x, TRUE);
  641. ::SetScrollPos(m_hwnd, SB_VERT, m_posScroll.y, TRUE);
  642. // Only update the screen if the scroll position has changed
  643. if ( (m_originOffset.cy != m_posScroll.y)
  644. || (m_originOffset.cx != m_posScroll.x) )
  645. {
  646. // Calculate the amount to scroll
  647. INT iVScrollAmount = m_originOffset.cy - m_posScroll.y;
  648. INT iHScrollAmount = m_originOffset.cx - m_posScroll.x;
  649. // Save the new position (for UpdateWindow)
  650. m_originOffset.cx = m_posScroll.x;
  651. m_originOffset.cy = m_posScroll.y;
  652. ::SetWindowOrgEx(m_hDCCached, m_originOffset.cx, m_originOffset.cy, NULL);
  653. // Scroll and redraw the newly invalidated portion of the window
  654. ::ScrollWindow(m_hwnd, iHScrollAmount, iVScrollAmount, NULL, NULL);
  655. ::UpdateWindow(m_hwnd);
  656. }
  657. }
  658. //
  659. //
  660. // Function: GotoPosition
  661. //
  662. // Purpose: Move the top-left corner of the workspace to the specified
  663. // position in the workspace.
  664. //
  665. //
  666. void WbDrawingArea::GotoPosition(int x, int y)
  667. {
  668. // Set the new scroll position
  669. m_posScroll.x = x;
  670. m_posScroll.y = y;
  671. // Scroll to the new position
  672. DoScrollWorkspace();
  673. // Invalidate the zoom scroll cache if we scroll when unzoomed.
  674. if (!Zoomed())
  675. {
  676. m_zoomRestoreScroll = FALSE;
  677. }
  678. }
  679. //
  680. //
  681. // Function: OnVScroll
  682. //
  683. // Purpose: Process a WM_VSCROLL messages.
  684. //
  685. //
  686. void WbDrawingArea::OnVScroll(UINT nSBCode, UINT nPos)
  687. {
  688. RECT rcClient;
  689. // Get the current client rectangle HEIGHT
  690. ::GetClientRect(m_hwnd, &rcClient);
  691. ASSERT(rcClient.top == 0);
  692. rcClient.bottom -= rcClient.top;
  693. // Act on the scroll code
  694. switch(nSBCode)
  695. {
  696. // Scroll to bottom
  697. case SB_BOTTOM:
  698. m_posScroll.y = DRAW_HEIGHT - rcClient.bottom;
  699. break;
  700. // Scroll down a line
  701. case SB_LINEDOWN:
  702. m_posScroll.y += DRAW_LINEVSCROLL;
  703. break;
  704. // Scroll up a line
  705. case SB_LINEUP:
  706. m_posScroll.y -= DRAW_LINEVSCROLL;
  707. break;
  708. // Scroll down a page
  709. case SB_PAGEDOWN:
  710. m_posScroll.y += rcClient.bottom / m_iZoomFactor;
  711. break;
  712. // Scroll up a page
  713. case SB_PAGEUP:
  714. m_posScroll.y -= rcClient.bottom / m_iZoomFactor;
  715. break;
  716. // Scroll to the top
  717. case SB_TOP:
  718. m_posScroll.y = 0;
  719. break;
  720. // Track the scroll box
  721. case SB_THUMBPOSITION:
  722. case SB_THUMBTRACK:
  723. m_posScroll.y = nPos; // don't round
  724. break;
  725. default:
  726. break;
  727. }
  728. // Validate the scroll position
  729. ValidateScrollPos();
  730. ::SetScrollPos(m_hwnd, SB_VERT, m_posScroll.y, TRUE);
  731. // If this message is informing us of the end of scrolling,
  732. // update the window
  733. if (nSBCode == SB_ENDSCROLL)
  734. {
  735. // Scroll the window
  736. ScrollWorkspace();
  737. }
  738. // Invalidate the zoom scroll cache if we scroll when unzoomed.
  739. if (!Zoomed())
  740. {
  741. m_zoomRestoreScroll = FALSE;
  742. }
  743. }
  744. //
  745. //
  746. // Function: OnHScroll
  747. //
  748. // Purpose: Process a WM_HSCROLL messages.
  749. //
  750. //
  751. void WbDrawingArea::OnHScroll(UINT nSBCode, UINT nPos)
  752. {
  753. RECT rcClient;
  754. // Get the current client rectangle WIDTH
  755. ::GetClientRect(m_hwnd, &rcClient);
  756. ASSERT(rcClient.left == 0);
  757. rcClient.right -= rcClient.left;
  758. switch(nSBCode)
  759. {
  760. // Scroll to the far right
  761. case SB_BOTTOM:
  762. m_posScroll.x = DRAW_WIDTH - rcClient.right;
  763. break;
  764. // Scroll right a line
  765. case SB_LINEDOWN:
  766. m_posScroll.x += DRAW_LINEHSCROLL;
  767. break;
  768. // Scroll left a line
  769. case SB_LINEUP:
  770. m_posScroll.x -= DRAW_LINEHSCROLL;
  771. break;
  772. // Scroll right a page
  773. case SB_PAGEDOWN:
  774. m_posScroll.x += rcClient.right / m_iZoomFactor;
  775. break;
  776. // Scroll left a page
  777. case SB_PAGEUP:
  778. m_posScroll.x -= rcClient.right / m_iZoomFactor;
  779. break;
  780. // Scroll to the far left
  781. case SB_TOP:
  782. m_posScroll.x = 0;
  783. break;
  784. // Track the scroll box
  785. case SB_THUMBPOSITION:
  786. case SB_THUMBTRACK:
  787. m_posScroll.x = nPos; // don't round
  788. break;
  789. default:
  790. break;
  791. }
  792. // Validate the scroll position
  793. ValidateScrollPos();
  794. ::SetScrollPos(m_hwnd, SB_HORZ, m_posScroll.x, TRUE);
  795. // If this message is informing us of the end of scrolling,
  796. // update the window
  797. if (nSBCode == SB_ENDSCROLL)
  798. {
  799. // Scroll the window
  800. ScrollWorkspace();
  801. }
  802. // Invalidate the zoom scroll cache if we scroll when unzoomed.
  803. if (!Zoomed())
  804. {
  805. m_zoomRestoreScroll = FALSE;
  806. }
  807. }
  808. //
  809. //
  810. // Function: AutoScroll
  811. //
  812. // Purpose: Auto-scroll the window to bring the position passed as
  813. // parameter into view.
  814. //
  815. //
  816. BOOL WbDrawingArea::AutoScroll
  817. (
  818. int xSurface,
  819. int ySurface,
  820. BOOL bMoveCursor,
  821. int xCaret,
  822. int yCaret
  823. )
  824. {
  825. int nXPSlop, nYPSlop;
  826. int nXMSlop, nYMSlop;
  827. int nDeltaHScroll, nDeltaVScroll;
  828. BOOL bDoScroll = FALSE;
  829. nXPSlop = 0;
  830. nYPSlop = 0;
  831. nXMSlop = 0;
  832. nYMSlop = 0;
  833. if( TextEditActive() )
  834. {
  835. POINT ptDirTest;
  836. ptDirTest.x = xSurface - xCaret;
  837. ptDirTest.y = ySurface - yCaret;
  838. // set up for text editbox
  839. if( ptDirTest.x > 0 )
  840. nXPSlop = m_pTextEditor->m_textMetrics.tmMaxCharWidth;
  841. else
  842. if( ptDirTest.x < 0 )
  843. nXMSlop = -m_pTextEditor->m_textMetrics.tmMaxCharWidth;
  844. if( ptDirTest.y > 0 )
  845. nYPSlop = m_pTextEditor->m_textMetrics.tmHeight;
  846. else
  847. if( ptDirTest.y < 0 )
  848. nYMSlop = -m_pTextEditor->m_textMetrics.tmHeight;
  849. nDeltaHScroll = m_pTextEditor->m_textMetrics.tmMaxCharWidth;
  850. nDeltaVScroll = m_pTextEditor->m_textMetrics.tmHeight;
  851. }
  852. else
  853. {
  854. // set up for all other objects
  855. nDeltaHScroll = DRAW_LINEHSCROLL;
  856. nDeltaVScroll = DRAW_LINEVSCROLL;
  857. }
  858. // Get the current visible surface rectangle
  859. RECT visibleRect;
  860. GetVisibleRect(&visibleRect);
  861. // Check for pos + slop being outside visible area
  862. if( (xSurface + nXPSlop) >= visibleRect.right )
  863. {
  864. bDoScroll = TRUE;
  865. m_posScroll.x +=
  866. (((xSurface + nXPSlop) - visibleRect.right) + nDeltaHScroll);
  867. }
  868. if( (xSurface + nXMSlop) <= visibleRect.left )
  869. {
  870. bDoScroll = TRUE;
  871. m_posScroll.x -=
  872. ((visibleRect.left - (xSurface + nXMSlop)) + nDeltaHScroll);
  873. }
  874. if( (ySurface + nYPSlop) >= visibleRect.bottom)
  875. {
  876. bDoScroll = TRUE;
  877. m_posScroll.y +=
  878. (((ySurface + nYPSlop) - visibleRect.bottom) + nDeltaVScroll);
  879. }
  880. if( (ySurface + nYMSlop) <= visibleRect.top)
  881. {
  882. bDoScroll = TRUE;
  883. m_posScroll.y -=
  884. ((visibleRect.top - (ySurface + nYMSlop)) + nDeltaVScroll);
  885. }
  886. if( !bDoScroll )
  887. return( FALSE );
  888. // Indicate that scrolling has completed (in both directions)
  889. ScrollWorkspace();
  890. // Update the mouse position (if required)
  891. if (bMoveCursor)
  892. {
  893. POINT screenPos;
  894. screenPos.x = xSurface;
  895. screenPos.y = ySurface;
  896. SurfaceToClient(&screenPos);
  897. ::ClientToScreen(m_hwnd, &screenPos);
  898. ::SetCursorPos(screenPos.x, screenPos.y);
  899. }
  900. return( TRUE );
  901. }
  902. //
  903. //
  904. // Function: OnCursor
  905. //
  906. // Purpose: Process a WM_SETCURSOR messages.
  907. //
  908. //
  909. LRESULT WbDrawingArea::OnCursor(HWND hwnd, UINT uiHit, UINT uMsg)
  910. {
  911. BOOL bResult = FALSE;
  912. // Check that this message is for the main window
  913. if (hwnd == m_hwnd)
  914. {
  915. // If the cursor is now in the client area, set the cursor
  916. if (uiHit == HTCLIENT)
  917. {
  918. bResult = SetCursorForState();
  919. }
  920. else
  921. {
  922. // Restore the cursor to the standard arrow. Set m_hCursor to NULL
  923. // to indicate that we have not set a special cursor.
  924. m_hCursor = NULL;
  925. ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
  926. bResult = TRUE;
  927. }
  928. }
  929. // Return result indicating whether we processed the message or not
  930. return bResult;
  931. }
  932. //
  933. //
  934. // Function: SetCursorForState
  935. //
  936. // Purpose: Set the cursor for the current state
  937. //
  938. //
  939. BOOL WbDrawingArea::SetCursorForState(void)
  940. {
  941. BOOL bResult = FALSE;
  942. m_hCursor = NULL;
  943. // If the drawing area is locked, use the "locked" cursor
  944. if (m_HourGlass)
  945. {
  946. m_hCursor = ::LoadCursor( NULL, IDC_WAIT );
  947. }
  948. else if (m_bLocked && g_pNMWBOBJ->m_LockerID != g_MyMemberID)
  949. {
  950. // Return the cursor for the tool
  951. m_hCursor = ::LoadCursor(g_hInstance, MAKEINTRESOURCE( LOCKCURSOR ));
  952. }
  953. else if (m_pToolCur != NULL)
  954. {
  955. // Get the cursor for the tool currently in use
  956. m_hCursor = m_pToolCur->GetCursorForTool();
  957. }
  958. if (m_hCursor != NULL)
  959. {
  960. ::SetCursor(m_hCursor);
  961. bResult = TRUE;
  962. }
  963. // Return result indicating whether we set the cursor or not
  964. return bResult;
  965. }
  966. //
  967. //
  968. // Function: Lock
  969. //
  970. // Purpose: Lock the drawing area, preventing further updates
  971. //
  972. //
  973. void WbDrawingArea::Lock(void)
  974. {
  975. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::Lock");
  976. // Check whether the drawing area is busy - this is not allowed
  977. ASSERT(!m_bBusy);
  978. // Stop any drawing we are doing.
  979. CancelDrawingMode();
  980. // Deselect any selected graphic
  981. ClearSelection();
  982. // Show that we are now locked
  983. m_bLocked = TRUE;
  984. TRACE_MSG(("Drawing area is now locked"));
  985. // Set the cursor for the drawing mode, but only if we should be drawing
  986. // a special cursor (if m_hCursor != the current cursor, then the cursor
  987. // is out of the client area).
  988. if (::GetCursor() == m_hCursor)
  989. {
  990. SetCursorForState();
  991. }
  992. }
  993. //
  994. //
  995. // Function: Unlock
  996. //
  997. // Purpose: Unlock the drawing area, preventing further updates
  998. //
  999. //
  1000. void WbDrawingArea::Unlock(void)
  1001. {
  1002. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::Unlock");
  1003. // Check whether the drawing area is busy - this is not allowed
  1004. ASSERT(!m_bBusy);
  1005. // Show that we are now unlocked
  1006. m_bLocked = FALSE;
  1007. TRACE_MSG(("Drawing area is now UNlocked"));
  1008. // Set the cursor for the drawing mode, but only if we should be drawing
  1009. // a special cursor (if m_hCursor != the current cursor, then the cursor
  1010. // is out of the client area).
  1011. if (::GetCursor() == m_hCursor)
  1012. {
  1013. SetCursorForState();
  1014. }
  1015. }
  1016. //
  1017. //
  1018. // Function: PageCleared
  1019. //
  1020. // Purpose: The page has been cleared
  1021. //
  1022. //
  1023. void WbDrawingArea::PageCleared(void)
  1024. {
  1025. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::PageCleared");
  1026. // Check whether the drawing area is busy - this is not allowed
  1027. ASSERT(!m_bBusy);
  1028. // Discard any text being edited
  1029. if (m_bTextEditorActive)
  1030. {
  1031. if (m_bLocked && g_pNMWBOBJ->m_LockerID != g_MyMemberID)
  1032. {
  1033. DeactivateTextEditor();
  1034. }
  1035. else
  1036. {
  1037. EndTextEntry(FALSE);
  1038. }
  1039. }
  1040. // Remove the copy of the marked graphic and the marker
  1041. ClearSelection();
  1042. // Invalidate the whole window
  1043. ::InvalidateRect(m_hwnd, NULL, TRUE);
  1044. }
  1045. //
  1046. //
  1047. // Function: InvalidateSurfaceRect
  1048. //
  1049. // Purpose: Invalidate the window rectangle corresponding to the given
  1050. // drawing surface rectangle.
  1051. //
  1052. //
  1053. void WbDrawingArea::InvalidateSurfaceRect(LPCRECT lprc, BOOL bErase)
  1054. {
  1055. RECT rc;
  1056. // Convert the surface co-ordinates to client window and invalidate
  1057. // the rectangle.
  1058. rc = *lprc;
  1059. SurfaceToClient(&rc);
  1060. ::InvalidateRect(m_hwnd, &rc, bErase);
  1061. }
  1062. //
  1063. //
  1064. // Function: PrimeFont
  1065. //
  1066. // Purpose: Insert the supplied font into our DC and return the
  1067. // text metrics
  1068. //
  1069. //
  1070. void WbDrawingArea::PrimeFont(HDC hDC, HFONT hFont, TEXTMETRIC* pTextMetrics)
  1071. {
  1072. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::PrimeFont");
  1073. //
  1074. // temporarily unzoom to get the font that we want
  1075. //
  1076. if (Zoomed())
  1077. {
  1078. ::ScaleViewportExtEx(m_hDCCached, 1, m_iZoomFactor, 1, m_iZoomFactor, NULL);
  1079. }
  1080. HFONT hOldFont = SelectFont(hDC, hFont);
  1081. if (hOldFont == NULL)
  1082. {
  1083. WARNING_OUT(("Failed to select font into DC"));
  1084. }
  1085. if (pTextMetrics != NULL)
  1086. {
  1087. ::GetTextMetrics(hDC, pTextMetrics);
  1088. }
  1089. //
  1090. // restore the zoom state
  1091. //
  1092. if (Zoomed())
  1093. {
  1094. ::ScaleViewportExtEx(m_hDCCached, m_iZoomFactor, 1, m_iZoomFactor, 1, NULL);
  1095. }
  1096. }
  1097. //
  1098. //
  1099. // Function: UnPrimeFont
  1100. //
  1101. // Purpose: Remove the specified font from the DC and clear cache
  1102. // variable
  1103. //
  1104. //
  1105. void WbDrawingArea::UnPrimeFont(HDC hDC)
  1106. {
  1107. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::UnPrimeFont");
  1108. if (hDC != NULL)
  1109. {
  1110. SelectFont(hDC, ::GetStockObject(SYSTEM_FONT));
  1111. }
  1112. }
  1113. //
  1114. //
  1115. // Function: PrimeDC
  1116. //
  1117. // Purpose: Set up a DC for drawing
  1118. //
  1119. //
  1120. void WbDrawingArea::PrimeDC(HDC hDC)
  1121. {
  1122. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::PrimeDC");
  1123. ::SetMapMode(hDC, MM_ANISOTROPIC);
  1124. ::SetBkMode(hDC, TRANSPARENT);
  1125. ::SetTextAlign(hDC, TA_LEFT | TA_TOP);
  1126. }
  1127. //
  1128. //
  1129. // Function: UnPrimeDC
  1130. //
  1131. // Purpose: Reset the DC to default state
  1132. //
  1133. //
  1134. void WbDrawingArea::UnPrimeDC(HDC hDC)
  1135. {
  1136. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::UnPrimeDC");
  1137. SelectPen(hDC, (HPEN)::GetStockObject(BLACK_PEN));
  1138. SelectBrush(hDC, (HBRUSH)::GetStockObject(BLACK_BRUSH));
  1139. UnPrimeFont(hDC);
  1140. }
  1141. //
  1142. // WbDrawingArea::OnContextMenu()
  1143. //
  1144. void WbDrawingArea::OnContextMenu(int xScreen, int yScreen)
  1145. {
  1146. POINT pt;
  1147. RECT rc;
  1148. pt.x = xScreen;
  1149. pt.y = yScreen;
  1150. ::ScreenToClient(m_hwnd, &pt);
  1151. ::GetClientRect(m_hwnd, &rc);
  1152. if (::PtInRect(&rc, pt))
  1153. {
  1154. // Complete drawing action, if any
  1155. OnLButtonUp(0, pt.x, pt.y);
  1156. // Ask main window to put up context menu
  1157. g_pMain->PopupContextMenu(pt.x, pt.y);
  1158. }
  1159. }
  1160. //
  1161. // WbDrawingArea::OnLButtonDown()
  1162. //
  1163. void WbDrawingArea::OnLButtonDown(UINT flags, int x, int y)
  1164. {
  1165. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::OnLButtonDown");
  1166. if( m_bIgnoreNextLClick )
  1167. {
  1168. TRACE_MSG( ("Ignoring WM_LBUTTONDOWN") );
  1169. return;
  1170. }
  1171. // Set the focus to this window. This is done to ensure that we trap
  1172. // the text edit keys and the delete key when they are used.
  1173. ::SetFocus(m_hwnd);
  1174. // Save the operation start point (and current end point)
  1175. // Adjust the mouse position to allow for the zoom factor
  1176. m_ptStart.x = x;
  1177. m_ptStart.y = y;
  1178. ClientToSurface(&m_ptStart);
  1179. m_ptEnd = m_ptStart;
  1180. // Show that the mouse button is now down
  1181. m_bLButtonDown = TRUE;
  1182. // Show that the drawing area is now busy
  1183. m_bBusy = TRUE;
  1184. // Only allow the action to take place if the drawing area is unlocked,
  1185. // and we have a valid tool
  1186. if ((m_bLocked && g_pNMWBOBJ->m_LockerID != g_MyMemberID) || (m_pToolCur == NULL))
  1187. {
  1188. // Tidy up the state and leave now
  1189. m_bLButtonDown = FALSE;
  1190. m_bBusy = FALSE;
  1191. return;
  1192. }
  1193. // Call the relevant initialization routine
  1194. if (m_pToolCur->ToolType() != TOOLTYPE_SELECT)
  1195. {
  1196. // dump selection if not select tool
  1197. ClearSelection();
  1198. }
  1199. INT border = 1;
  1200. switch (m_pToolCur->ToolType())
  1201. {
  1202. case TOOLTYPE_TEXT:
  1203. break;
  1204. case TOOLTYPE_HIGHLIGHT:
  1205. case TOOLTYPE_PEN:
  1206. case TOOLTYPE_LINE:
  1207. case TOOLTYPE_BOX:
  1208. case TOOLTYPE_FILLEDBOX:
  1209. case TOOLTYPE_ELLIPSE:
  1210. case TOOLTYPE_FILLEDELLIPSE:
  1211. BeginDrawingMode(m_ptStart);
  1212. break;
  1213. case TOOLTYPE_ERASER:
  1214. BeginSelectMode(m_ptStart, TRUE);
  1215. break;
  1216. case TOOLTYPE_SELECT:
  1217. border = -2;
  1218. BeginSelectMode(m_ptStart, FALSE);
  1219. break;
  1220. // Do nothing if we do not recognise the pen type
  1221. default:
  1222. ERROR_OUT(("Bad tool type"));
  1223. break;
  1224. }
  1225. // Clamp the cursor to the drawing window
  1226. RECT rcClient;
  1227. ::GetClientRect(m_hwnd, &rcClient);
  1228. ::MapWindowPoints(m_hwnd, NULL, (LPPOINT)&rcClient.left, 2);
  1229. ::InflateRect(&rcClient, border, border);
  1230. ::ClipCursor(&rcClient);
  1231. }
  1232. //
  1233. //
  1234. // Function: SelectPreviousGraphicAt
  1235. //
  1236. // Purpose: Select the previous graphic (in the Z-order) at the position
  1237. // specified, and starting at a specified graphic. If the
  1238. // graphic pointer given is NULL the search starts from the
  1239. // top. If the point specified is outside the bounding
  1240. // rectangle of the specified graphic the search starts at the
  1241. // top and chooses the first graphic which contains the point.
  1242. //
  1243. // The search process will loop back to the top of the Z-order
  1244. // if it gets to the bottom having failed to find a graphic.
  1245. //
  1246. // Graphics which are locked are ignored by the search.
  1247. //
  1248. //
  1249. T126Obj* WbDrawingArea::SelectPreviousGraphicAt
  1250. (
  1251. T126Obj* pStartGraphic,
  1252. POINT point
  1253. )
  1254. {
  1255. // Set the result to "none found" initially
  1256. T126Obj* pResultGraphic = NULL;
  1257. // If a starting point has been specified
  1258. if (pStartGraphic != NULL)
  1259. {
  1260. RECT rectHit;
  1261. MAKE_HIT_RECT(rectHit, point);
  1262. // If the reference point is within the start graphic
  1263. if ( pStartGraphic->PointInBounds(point) &&
  1264. pStartGraphic->CheckReallyHit( &rectHit ) )
  1265. {
  1266. WBPOSITION pos = pStartGraphic->GetMyPosition();
  1267. g_pCurrentWorkspace->GetPreviousObject(pos);
  1268. while (pos)
  1269. {
  1270. pResultGraphic = g_pCurrentWorkspace->GetPreviousObject(pos);
  1271. if( pResultGraphic && pResultGraphic->CheckReallyHit( &rectHit ) )
  1272. {
  1273. if(m_pMarker)
  1274. {
  1275. RECT rect;
  1276. pResultGraphic->GetRect(&rect);
  1277. m_pMarker->SetRect(&rect);
  1278. }
  1279. break;
  1280. }
  1281. pResultGraphic = NULL;
  1282. }
  1283. }
  1284. }
  1285. // If we have not got a result graphic yet. (This catches two cases:
  1286. // - where no start graphic has been given so that we want to start
  1287. // from the top,
  1288. // - where we have searched back from the start graphic and reached
  1289. // the bottom of the Z-order without finding a suitable graphic.
  1290. if (pResultGraphic == NULL)
  1291. {
  1292. // Get the topmost graphic that contains the point specified
  1293. pResultGraphic = PG_SelectLast(g_pCurrentWorkspace, point);
  1294. }
  1295. // If we have found an object, draw the marker
  1296. if (pResultGraphic != NULL)
  1297. {
  1298. //
  1299. // If we are already selected and we didn't select it
  1300. // some other node has the control over this graphic don't select it
  1301. // in this case
  1302. // Or if we are trying to select a remote pointer that is not ours
  1303. //
  1304. if(pResultGraphic->IsSelected() && pResultGraphic->WasSelectedRemotely()
  1305. || (pResultGraphic->GraphicTool() == TOOLTYPE_REMOTEPOINTER && !pResultGraphic->IAmTheOwner()))
  1306. {
  1307. pResultGraphic = NULL;
  1308. }
  1309. else
  1310. {
  1311. // Select the new one
  1312. SelectGraphic(pResultGraphic);
  1313. }
  1314. }
  1315. return pResultGraphic;
  1316. }
  1317. //
  1318. //
  1319. // Function: BeginSelectMode
  1320. //
  1321. // Purpose: Process a mouse button down in select mode
  1322. //
  1323. //
  1324. void WbDrawingArea::BeginSelectMode(POINT surfacePos, BOOL bDontDrag )
  1325. {
  1326. RECT rc;
  1327. // Assume we do not start dragging a graphic
  1328. m_pGraphicTracker = NULL;
  1329. // Assume that we do not mark a new graphic
  1330. m_bNewMarkedGraphic = FALSE;
  1331. // turn off TRACK-SELECT-RECT
  1332. m_bTrackingSelectRect = FALSE;
  1333. // Check whether there is currently an object marked, and
  1334. // whether we are clicking inside the same object. If we are then
  1335. // we do nothing here - the click will be handled by the tracking or
  1336. // completion routines for select mode.
  1337. if ( (GraphicSelected() == FALSE)
  1338. || (m_pMarker->PointInBounds(surfacePos) == FALSE))
  1339. {
  1340. ::SetRectEmpty(&g_pDraw->m_selectorRect);
  1341. // We are selecting a new object if bDontDrag == FALSE, find it.
  1342. // otherwise just turn on the select rect
  1343. T126Obj* pGraphic;
  1344. if( bDontDrag )
  1345. pGraphic = NULL;
  1346. else
  1347. pGraphic = SelectPreviousGraphicAt(NULL, surfacePos);
  1348. // If we have found an object, draw the marker
  1349. if (pGraphic != NULL)
  1350. {
  1351. if(pGraphic->IsSelected() && pGraphic->WasSelectedRemotely())
  1352. {
  1353. return;
  1354. }
  1355. // Show that a new graphic has now been marked.
  1356. m_bNewMarkedGraphic = TRUE;
  1357. }
  1358. else
  1359. {
  1360. if( (GetAsyncKeyState( VK_SHIFT ) >= 0) &&
  1361. (GetAsyncKeyState( VK_CONTROL ) >= 0) )
  1362. {
  1363. // clicked on dead air, remove all selections
  1364. ClearSelection();
  1365. }
  1366. //TRACK-SELECT-RECT
  1367. m_bTrackingSelectRect = TRUE;
  1368. BeginDrawingMode(surfacePos);
  1369. return;
  1370. }
  1371. }
  1372. if(GraphicSelected())
  1373. {
  1374. m_pMarker->SetRect(&m_selectorRect);
  1375. m_pMarker->SetBoundsRect(&m_selectorRect);
  1376. m_pGraphicTracker = m_pMarker;
  1377. }
  1378. // Get all mouse input directed to the this window
  1379. ::SetCapture(m_hwnd);
  1380. }
  1381. //
  1382. //
  1383. // Function: TrackSelectMode
  1384. //
  1385. // Purpose: Process a mouse move event in select mode
  1386. //
  1387. //
  1388. void WbDrawingArea::TrackSelectMode(POINT surfacePos)
  1389. {
  1390. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::TrackSelectMode");
  1391. if( m_bTrackingSelectRect )
  1392. TrackDrawingMode(surfacePos);
  1393. else
  1394. {
  1395. // In this case we must be dragging a marked object
  1396. if(!EqualPoint(surfacePos, m_ptEnd))
  1397. {
  1398. MoveSelectedGraphicBy(surfacePos.x - m_ptEnd.x, surfacePos.y - m_ptEnd.y);
  1399. }
  1400. m_ptEnd = surfacePos;
  1401. }
  1402. }
  1403. void WbDrawingArea::BeginDeleteMode(POINT mousePos )
  1404. {
  1405. // turn off object dragging
  1406. BeginSelectMode( mousePos, TRUE );
  1407. }
  1408. void WbDrawingArea::TrackDeleteMode( POINT mousePos )
  1409. {
  1410. TrackSelectMode( mousePos );
  1411. }
  1412. //
  1413. //
  1414. // Function: BeginTextMode
  1415. //
  1416. // Purpose: Process a mouse button down in text mode
  1417. //
  1418. //
  1419. void WbDrawingArea::BeginTextMode(POINT surfacePos)
  1420. {
  1421. RECT rc;
  1422. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::BeginTextMode");
  1423. //
  1424. // Get a DC for passing into the text editor
  1425. //
  1426. HDC hDC = m_hDCCached;
  1427. // If we are already editing a text object, we just move the text cursor
  1428. if (m_bTextEditorActive)
  1429. {
  1430. // If the mouse has been clicked in the currently active object
  1431. // we just move the cursor within the object, otherwise we end the
  1432. // edit for the current object and move to a new one.
  1433. m_pTextEditor->GetRect(&rc);
  1434. if (::PtInRect(&rc, surfacePos))
  1435. {
  1436. // Set the new position for the cursor
  1437. m_pTextEditor->SetCursorPosFromPoint(surfacePos);
  1438. }
  1439. else
  1440. {
  1441. // Complete the text entry accepting the changes
  1442. EndTextEntry(TRUE);
  1443. // LAURABU BOGUS:
  1444. // It would be cooler to now return, that way you don't get
  1445. // another text object just cuz you ended the current editing
  1446. // session.
  1447. }
  1448. }
  1449. // If we are not editing an object we check to see whether there is
  1450. // a text object under the cursor or whether we must start a new one.
  1451. if (!m_bTextEditorActive)
  1452. {
  1453. // Check whether we are clicking over a text object. If we are
  1454. // start editing the object, otherwise we start a new text object.
  1455. // Look back through the Z-order for a text object
  1456. T126Obj* pGraphic = PG_SelectLast(g_pCurrentWorkspace, surfacePos);
  1457. T126Obj* pNextGraphic = NULL;
  1458. WBPOSITION pos;
  1459. if(pGraphic)
  1460. {
  1461. pos = pGraphic->GetMyPosition();
  1462. }
  1463. while ( (pGraphic != NULL) && pGraphic->GraphicTool() != TOOLTYPE_TEXT)
  1464. {
  1465. // Get the next one
  1466. pNextGraphic = PG_SelectPrevious(g_pCurrentWorkspace, pos, surfacePos);
  1467. // Use the next one
  1468. pGraphic = pNextGraphic;
  1469. }
  1470. // Check whether this graphic object is already being edited by
  1471. // another user in the call.
  1472. if (pGraphic != NULL && !pGraphic->WasSelectedRemotely() && pGraphic->GraphicTool() == TOOLTYPE_TEXT)
  1473. {
  1474. // We found a text object under the mouse pointer...
  1475. // ...edit it
  1476. m_pTextEditor = (WbTextEditor*)pGraphic;
  1477. m_pTextEditor->SetTextObject(m_pTextEditor);
  1478. // Make sure the tool reflects the new information
  1479. if (m_pToolCur != NULL)
  1480. {
  1481. m_pToolCur->SelectGraphic(pGraphic);
  1482. }
  1483. HWND hwndParent = ::GetParent(m_hwnd);
  1484. if (hwndParent != NULL)
  1485. {
  1486. ASSERT(g_pMain);
  1487. ASSERT(g_pMain->m_hwnd == hwndParent);
  1488. ::PostMessage(hwndParent, WM_USER_UPDATE_ATTRIBUTES, 0, 0);
  1489. }
  1490. // Show that we are now gathering text but dont put up cursor
  1491. // yet. Causes cursor droppings later (bug 2505)
  1492. //ActivateTextEditor( FALSE );
  1493. RECT rect;
  1494. m_pTextEditor->GetRect(&rect);
  1495. m_pTextEditor->Create();
  1496. // init editbox size
  1497. m_pTextEditor->GetText();
  1498. //
  1499. // Tell the other nodes they can't edit this object now
  1500. //
  1501. m_pTextEditor->SetViewState(selected_chosen);
  1502. m_pTextEditor->OnObjectEdit();
  1503. ActivateTextEditor( TRUE );
  1504. ::BringWindowToTop(m_pTextEditor->m_pEditBox->m_hwnd);
  1505. //
  1506. // Account for scrolling
  1507. //
  1508. SurfaceToClient(&rect);
  1509. ::MoveWindow(m_pTextEditor->m_pEditBox->m_hwnd, rect.left, rect.top,
  1510. rect.right - rect.left, rect.bottom - rect.top, TRUE);
  1511. // Set the initial cursor position for the edit
  1512. m_pTextEditor->SetCursorPosFromPoint(surfacePos);
  1513. }
  1514. else
  1515. {
  1516. RECT rect;
  1517. rect.top = m_ptEnd.y;
  1518. rect.left = m_ptEnd.x;
  1519. rect.bottom = m_ptEnd.y;
  1520. rect.right = m_ptEnd.x;
  1521. DBG_SAVE_FILE_LINE
  1522. m_pTextEditor = new WbTextEditor();
  1523. m_pTextEditor->SetRect(&rect);
  1524. m_pTextEditor->SetAnchorPoint(m_ptEnd.x, m_ptEnd.y);
  1525. m_pTextEditor->SetViewState(selected_chosen);
  1526. // There are no text objects under the mouse pointer...
  1527. // ...start a new one
  1528. // Clear any old text out of the editor, and reset its graphic
  1529. // handle. This prevents us from replacing an old text object when
  1530. // we next save the text editor contents.
  1531. if (!m_pTextEditor->New())
  1532. {
  1533. DefaultExceptionHandler(WBFE_RC_WINDOWS, 0);
  1534. return;
  1535. }
  1536. // Set the attributes of the text
  1537. m_pTextEditor->SetFont(m_pToolCur->GetFont());
  1538. m_pTextEditor->SetPenColor(m_pToolCur->GetColor(), TRUE);
  1539. // We need to reselect a font now into our DC
  1540. SelectFont(hDC, m_pTextEditor->GetFont());
  1541. // Set the position of the new object
  1542. SIZE sizeCursor;
  1543. m_pTextEditor->GetCursorSize(&sizeCursor);
  1544. m_pTextEditor->CalculateBoundsRect();
  1545. m_pTextEditor->MoveTo(m_ptEnd.x, m_ptEnd.y - sizeCursor.cy);
  1546. // Show that we are now gathering text
  1547. ActivateTextEditor( TRUE );
  1548. }
  1549. }
  1550. }
  1551. void WbDrawingArea::BeginDrawingMode(POINT surfacePos)
  1552. {
  1553. if(!g_pCurrentWorkspace)
  1554. {
  1555. TRACE_DEBUG(("Can't draw without a workspace"));
  1556. return;
  1557. }
  1558. //
  1559. // Get all mouse input directed to the this window
  1560. //
  1561. ::SetCapture(m_hwnd);
  1562. //
  1563. // We shouldn't be using the tracker
  1564. //
  1565. ASSERT(!m_pGraphicTracker);
  1566. UINT drawingType;
  1567. BOOL sendBeforefinished = FALSE;
  1568. BOOL highlight = FALSE;
  1569. UINT lineStyle = PS_SOLID;
  1570. UINT toolType = m_pToolCur->ToolType();
  1571. switch (toolType)
  1572. {
  1573. case TOOLTYPE_HIGHLIGHT:
  1574. highlight = TRUE;
  1575. case TOOLTYPE_PEN:
  1576. sendBeforefinished = TRUE;
  1577. case TOOLTYPE_LINE:
  1578. drawingType = openPolyLine_chosen;
  1579. break;
  1580. case TOOLTYPE_SELECT:
  1581. case TOOLTYPE_ERASER:
  1582. m_pGraphicTracker = m_pMarker;
  1583. return;
  1584. break;
  1585. case TOOLTYPE_FILLEDBOX:
  1586. case TOOLTYPE_BOX:
  1587. drawingType = rectangle_chosen;
  1588. break;
  1589. case TOOLTYPE_FILLEDELLIPSE:
  1590. case TOOLTYPE_ELLIPSE:
  1591. drawingType = ellipse_chosen;
  1592. break;
  1593. }
  1594. DBG_SAVE_FILE_LINE
  1595. m_pGraphicTracker = new DrawObj(drawingType, toolType);
  1596. if(NULL == m_pGraphicTracker)
  1597. {
  1598. ERROR_OUT(("Failed to allocate new DrawObj"));
  1599. return;
  1600. }
  1601. //
  1602. // Use black for the tracking rectangle unless it is pen or highlighter
  1603. //
  1604. if(m_pToolCur->ToolType() == TOOLTYPE_PEN || m_pToolCur->ToolType() == TOOLTYPE_HIGHLIGHT)
  1605. {
  1606. m_pGraphicTracker->SetPenColor(m_pToolCur->GetColor(), TRUE);
  1607. }
  1608. else
  1609. {
  1610. m_pGraphicTracker->SetPenColor(RGB(0,0,0), TRUE);
  1611. }
  1612. m_pGraphicTracker->SetFillColor(RGB(255,255,255), FALSE);
  1613. m_pGraphicTracker->SetLineStyle(lineStyle);
  1614. m_pGraphicTracker->SetAnchorPoint(surfacePos.x, surfacePos.y);
  1615. m_pGraphicTracker->SetHighlight(highlight);
  1616. m_pGraphicTracker->SetViewState(unselected_chosen);
  1617. m_pGraphicTracker->SetZOrder(front);
  1618. //
  1619. // Start a timer if we want it to send intermidiate drawings
  1620. //
  1621. if(sendBeforefinished)
  1622. {
  1623. RECT rect;
  1624. rect.left = surfacePos.x;
  1625. rect.top = surfacePos.y;
  1626. rect.right = surfacePos.x;
  1627. rect.bottom = surfacePos.y;
  1628. m_pGraphicTracker->SetRect(&rect);
  1629. m_pGraphicTracker->SetBoundsRect(&rect);
  1630. surfacePos.x = 0;
  1631. surfacePos.y = 0;
  1632. m_pGraphicTracker->AddPoint(surfacePos);
  1633. //
  1634. // Select the final ROP
  1635. //
  1636. if (highlight)
  1637. {
  1638. m_pGraphicTracker->SetROP(R2_MASKPEN);
  1639. }
  1640. else
  1641. {
  1642. m_pGraphicTracker->SetROP(R2_COPYPEN);
  1643. }
  1644. //
  1645. // Use the tools width for pen or highlight
  1646. //
  1647. m_pGraphicTracker->SetPenThickness(m_pToolCur->GetWidth());
  1648. // Start the timer for updating the graphic (this is only for updating
  1649. // the graphic when the user stops moving the pointer but keeps the
  1650. // mouse button down).
  1651. ::SetTimer(m_hwnd, TIMER_GRAPHIC_UPDATE, DRAW_GRAPHICUPDATEDELAY, NULL);
  1652. // Save the current time (used to determine when to update
  1653. // the external graphic pointer information while the mouse is
  1654. // being moved).
  1655. m_dwTickCount = ::GetTickCount();
  1656. m_pGraphicTracker->SetViewState(selected_chosen);
  1657. }
  1658. else
  1659. {
  1660. m_pGraphicTracker->SetPenThickness(1);
  1661. }
  1662. }
  1663. //
  1664. //
  1665. // Function: TrackDrawingMode
  1666. //
  1667. // Purpose: Process a mouse move event in drawing mode
  1668. //
  1669. //
  1670. void WbDrawingArea::TrackDrawingMode(POINT surfacePos)
  1671. {
  1672. HPALETTE hPal;
  1673. HPALETTE hOldPal = NULL;
  1674. if(!m_pGraphicTracker)
  1675. {
  1676. return;
  1677. }
  1678. if(EqualPoint(surfacePos, m_ptEnd))
  1679. {
  1680. return;
  1681. }
  1682. // Get a device context for tracking
  1683. HDC hDC = m_hDCCached;
  1684. // set up palette
  1685. if ((g_pCurrentWorkspace != NULL) && ((hPal = PG_GetPalette()) != NULL) )
  1686. {
  1687. hOldPal = ::SelectPalette(hDC, hPal, FALSE );
  1688. ::RealizePalette(hDC);
  1689. }
  1690. // Erase the last ellipse (using XOR property)
  1691. if (!EqualPoint(m_ptStart, m_ptEnd))
  1692. {
  1693. // Draw the rectangle
  1694. m_pGraphicTracker->Draw();
  1695. }
  1696. // Draw the new rectangle (XORing it onto the display)
  1697. if (!EqualPoint(m_ptStart, surfacePos))
  1698. {
  1699. //
  1700. // If we are using a pen or highlighter
  1701. // Tracking in draw mode is a special case. We draw directly to the client
  1702. // area of the window and to the recording device context.
  1703. if( m_pToolCur->ToolType() == TOOLTYPE_HIGHLIGHT || m_pToolCur->ToolType() == TOOLTYPE_PEN)
  1704. {
  1705. POINT deltaPoint;
  1706. deltaPoint.x = surfacePos.x - m_ptEnd.x;
  1707. deltaPoint.y = surfacePos.y - m_ptEnd.y;
  1708. // Save the point, checking there aren't too many points
  1709. if (m_pGraphicTracker->AddPoint(deltaPoint) == FALSE)
  1710. {
  1711. // too many points so end the freehand object
  1712. OnLButtonUp(0, surfacePos.x, surfacePos.y);
  1713. goto cleanUp;
  1714. }
  1715. m_pGraphicTracker->SetRectPts(m_ptEnd, surfacePos);
  1716. m_pGraphicTracker->AddPointToBounds(surfacePos.x, surfacePos.y);
  1717. m_ptEnd = surfacePos;
  1718. }
  1719. else
  1720. {
  1721. // Save the new box end point
  1722. m_ptEnd = surfacePos;
  1723. // Draw the rectangle
  1724. m_pGraphicTracker->SetRectPts(m_ptStart, m_ptEnd);
  1725. }
  1726. m_pGraphicTracker->Draw();
  1727. }
  1728. cleanUp:
  1729. if (hOldPal != NULL)
  1730. {
  1731. ::SelectPalette(hDC, hOldPal, TRUE);
  1732. }
  1733. }
  1734. //
  1735. // WbDrawingArea::OnMouseMove
  1736. //
  1737. void WbDrawingArea::OnMouseMove(UINT flags, int x, int y)
  1738. {
  1739. if(!g_pCurrentWorkspace)
  1740. {
  1741. return;
  1742. }
  1743. POINT surfacePos;
  1744. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::OnMouseMove");
  1745. surfacePos.x = x;
  1746. surfacePos.y = y;
  1747. // Check if the left mouse button is down
  1748. if (m_bLButtonDown)
  1749. {
  1750. // Calculate the worksurface position
  1751. // Adjust the mouse position to allow for the zoom factor
  1752. ClientToSurface(&surfacePos);
  1753. // Make sure the point is a valid surface position
  1754. MoveOntoSurface(&surfacePos);
  1755. // Check whether the window needs to be scrolled to get the
  1756. // current position into view.
  1757. AutoScroll(surfacePos.x, surfacePos.y, FALSE, 0, 0);
  1758. // Action taken depends on the tool type
  1759. switch(m_pToolCur->ToolType())
  1760. {
  1761. case TOOLTYPE_HIGHLIGHT:
  1762. case TOOLTYPE_PEN:
  1763. case TOOLTYPE_LINE:
  1764. case TOOLTYPE_BOX:
  1765. case TOOLTYPE_FILLEDBOX:
  1766. case TOOLTYPE_ELLIPSE:
  1767. case TOOLTYPE_FILLEDELLIPSE:
  1768. TrackDrawingMode(surfacePos);
  1769. break;
  1770. case TOOLTYPE_ERASER:
  1771. case TOOLTYPE_SELECT:
  1772. TrackSelectMode(surfacePos);
  1773. break;
  1774. case TOOLTYPE_TEXT:
  1775. // JOSEF add functionality
  1776. break;
  1777. default:
  1778. ERROR_OUT(("Unknown tool type"));
  1779. break;
  1780. }
  1781. }
  1782. }
  1783. //
  1784. //
  1785. // Function: CancelDrawingMode
  1786. //
  1787. // Purpose: Cancels a drawing operation after an error.
  1788. //
  1789. //
  1790. void WbDrawingArea::CancelDrawingMode(void)
  1791. {
  1792. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::CancelDrawingMode");
  1793. //
  1794. // Quit if there's nothing to cancel.
  1795. //
  1796. if (!m_bBusy && !m_bTextEditorActive)
  1797. {
  1798. TRACE_DEBUG(("Drawing area not busy and text editor not active..."));
  1799. return;
  1800. }
  1801. // The drawing area is no longer busy
  1802. m_bBusy = FALSE;
  1803. //
  1804. // Redraw the object - we need to discard any local updates which we
  1805. // weren't able to write to the object we are editing. Ideally we should
  1806. // just invalidate the object itself but because some of the co-ordinates
  1807. // we have already drawn on the page may have been lost, we dont know
  1808. // exactly how big the object is.
  1809. //
  1810. ::InvalidateRect(m_hwnd, NULL, TRUE);
  1811. m_bLButtonDown = FALSE;
  1812. // Release the mouse capture
  1813. if (::GetCapture() == m_hwnd)
  1814. {
  1815. ::ReleaseCapture();
  1816. }
  1817. //
  1818. // Perform any tool specific processing.
  1819. //
  1820. switch(m_pToolCur->ToolType())
  1821. {
  1822. case TOOLTYPE_HIGHLIGHT:
  1823. case TOOLTYPE_PEN:
  1824. CompleteDrawingMode();
  1825. break;
  1826. case TOOLTYPE_SELECT:
  1827. // Stop the pointer update timer
  1828. ::KillTimer(m_hwnd, TIMER_GRAPHIC_UPDATE);
  1829. break;
  1830. case TOOLTYPE_TEXT:
  1831. if (m_bTextEditorActive)
  1832. {
  1833. m_pTextEditor->AbortEditGently();
  1834. }
  1835. break;
  1836. default:
  1837. break;
  1838. }
  1839. // Show that we are no longer tracking an object
  1840. if (m_pGraphicTracker != NULL)
  1841. {
  1842. m_pGraphicTracker = NULL; // We don't delete the tracker, because it is also the drawing
  1843. }
  1844. }
  1845. //
  1846. // WbDrawingArea::OnLButtonUp()
  1847. //
  1848. void WbDrawingArea::OnLButtonUp(UINT flags, int x, int y)
  1849. {
  1850. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::OnLButtonUp");
  1851. if (m_bIgnoreNextLClick)
  1852. {
  1853. TRACE_MSG( ("Ignoring WM_LBUTTONUP") );
  1854. m_bIgnoreNextLClick = FALSE;
  1855. return;
  1856. }
  1857. // Only process the event if we saw the button down event
  1858. if (m_bLButtonDown)
  1859. {
  1860. TRACE_MSG(("End of drawing operation"));
  1861. m_bLButtonDown = FALSE;
  1862. // The drawing area is no longer busy
  1863. m_bBusy = FALSE;
  1864. if (m_pGraphicTracker == NULL)
  1865. {
  1866. // Calculate the work surface position
  1867. // Adjust the mouse position to allow for the zoom factor
  1868. POINT surfacePos;
  1869. surfacePos.x = x;
  1870. surfacePos.y = y;
  1871. ClientToSurface(&surfacePos);
  1872. MoveOntoSurface(&surfacePos);
  1873. m_ptEnd = surfacePos;
  1874. }
  1875. // Release the mouse capture
  1876. if (::GetCapture() == m_hwnd)
  1877. {
  1878. ::ReleaseCapture();
  1879. }
  1880. // Check the page is valid - might not be if it has been deleted
  1881. // while the object was being drawn - we would not have been
  1882. // alerted to this because m_bBusy was true.
  1883. if (g_pCurrentWorkspace != NULL)
  1884. {
  1885. // surround in an exception handler in case of lock errors, etc -
  1886. // we need to remove the graphic tracker
  1887. // Action taken depends on the current tool type
  1888. switch(m_pToolCur->ToolType())
  1889. {
  1890. case TOOLTYPE_HIGHLIGHT:
  1891. case TOOLTYPE_PEN:
  1892. case TOOLTYPE_LINE:
  1893. case TOOLTYPE_BOX:
  1894. case TOOLTYPE_FILLEDBOX:
  1895. case TOOLTYPE_ELLIPSE:
  1896. case TOOLTYPE_FILLEDELLIPSE:
  1897. CompleteDrawingMode();
  1898. break;
  1899. case TOOLTYPE_SELECT:
  1900. CompleteSelectMode();
  1901. break;
  1902. case TOOLTYPE_ERASER:
  1903. CompleteDeleteMode();
  1904. break;
  1905. case TOOLTYPE_TEXT:
  1906. m_ptStart.x = x;
  1907. m_ptStart.y = y;
  1908. ClientToSurface(&m_ptStart);
  1909. BeginTextMode(m_ptStart);
  1910. break;
  1911. default:
  1912. ERROR_OUT(("Unknown pen type"));
  1913. break;
  1914. }
  1915. }
  1916. // Show that we are no longer tracking an object
  1917. if (m_pGraphicTracker != NULL)
  1918. {
  1919. m_pGraphicTracker = NULL; // Don't delete the tracker since it is the drawing object
  1920. }
  1921. }
  1922. // unclamp cursor (bug 589)
  1923. ClipCursor(NULL);
  1924. }
  1925. //
  1926. //
  1927. // Function: CompleteSelectMode
  1928. //
  1929. // Purpose: Complete a select mode operation
  1930. //
  1931. //
  1932. void WbDrawingArea::CompleteSelectMode()
  1933. {
  1934. // If an object is being dragged
  1935. //if (m_pGraphicTracker != NULL)
  1936. {
  1937. // Check if we were dragging a pointer. Pointers track
  1938. // themselves i.e. the original copy of the pointer is not
  1939. // left on the page. We want to leave the last drawn image on
  1940. // the page as this is the new pointer position.
  1941. if( m_bTrackingSelectRect && (!EqualPoint(m_ptStart, m_ptEnd)))
  1942. {
  1943. CompleteMarkAreaMode();
  1944. SelectMarkerFromRect( &m_rcMarkedArea );
  1945. }
  1946. else
  1947. {
  1948. // If we need to remove the rubber band box
  1949. if (!EqualPoint(m_ptStart, m_ptEnd))
  1950. {
  1951. EraseInitialDrawFinal(m_ptStart.x - m_ptEnd.x , m_ptStart.y - m_ptEnd.y, TRUE);
  1952. InvalidateSurfaceRect(&g_pDraw->m_selectorRect,TRUE);
  1953. }
  1954. else
  1955. {
  1956. // Start and end points were the same, in this case the object has
  1957. // not been moved. We treat this as a request to move the marker
  1958. // back through the stack of objects.
  1959. if (m_bNewMarkedGraphic == FALSE)
  1960. {
  1961. SelectPreviousGraphicAt(m_pSelectedGraphic, m_ptEnd);
  1962. }
  1963. }
  1964. m_bTrackingSelectRect = TRUE;
  1965. }
  1966. //
  1967. // Make sure to delete the saved bitmap
  1968. //
  1969. if(m_pSelectedGraphic && m_pSelectedGraphic->GraphicTool() == TOOLTYPE_REMOTEPOINTER)
  1970. {
  1971. ((BitmapObj*)m_pSelectedGraphic)->DeleteSavedBitmap();
  1972. }
  1973. }
  1974. }
  1975. void WbDrawingArea::CompleteDeleteMode()
  1976. {
  1977. // select object(s)
  1978. CompleteSelectMode();
  1979. //
  1980. // If we are draging the remote pointer do nothing
  1981. //
  1982. if(m_pSelectedGraphic && m_pSelectedGraphic->GraphicTool() == TOOLTYPE_REMOTEPOINTER)
  1983. {
  1984. return;
  1985. }
  1986. // nuke 'em
  1987. ::PostMessage(g_pMain->m_hwnd, WM_COMMAND, MAKELONG(IDM_DELETE, BN_CLICKED), 0);
  1988. }
  1989. //
  1990. //
  1991. // Function: CompleteMarkAreaMode
  1992. //
  1993. // Purpose: Process a mouse button up event in mark area mode
  1994. //
  1995. //
  1996. void WbDrawingArea::CompleteMarkAreaMode(void)
  1997. {
  1998. // Get a device context for tracking
  1999. HDC hDC = m_hDCCached;
  2000. // Erase the last ellipse (using XOR property)
  2001. if (!EqualPoint(m_ptStart, m_ptEnd))
  2002. {
  2003. // Draw the rectangle
  2004. m_pGraphicTracker->Draw();
  2005. // Use normalized coords
  2006. if (m_ptEnd.x < m_ptStart.x)
  2007. {
  2008. m_rcMarkedArea.left = m_ptEnd.x;
  2009. m_rcMarkedArea.right = m_ptStart.x;
  2010. }
  2011. else
  2012. {
  2013. m_rcMarkedArea.left = m_ptStart.x;
  2014. m_rcMarkedArea.right = m_ptEnd.x;
  2015. }
  2016. if (m_ptEnd.y < m_ptStart.y)
  2017. {
  2018. m_rcMarkedArea.top = m_ptEnd.y;
  2019. m_rcMarkedArea.bottom = m_ptStart.y;
  2020. }
  2021. else
  2022. {
  2023. m_rcMarkedArea.top = m_ptStart.y;
  2024. m_rcMarkedArea.bottom = m_ptEnd.y;
  2025. }
  2026. }
  2027. }
  2028. //
  2029. //
  2030. // Function: CompleteTextMode
  2031. //
  2032. // Purpose: Complete a text mode operation
  2033. //
  2034. //
  2035. void WbDrawingArea::CompleteTextMode()
  2036. {
  2037. // Not much to for text mode. Main text mode actions are taken
  2038. // as a result of a WM_CHAR message and not on mouse events.
  2039. // Just deselect our font if it is still selected
  2040. UnPrimeFont(m_hDCCached);
  2041. }
  2042. //
  2043. //
  2044. // Function: CompleteDrawingMode
  2045. //
  2046. // Purpose: Complete a draw mode operation
  2047. //
  2048. //
  2049. void WbDrawingArea::CompleteDrawingMode()
  2050. {
  2051. // Only draw the line if it has non-zero length
  2052. if (!EqualPoint(m_ptStart, m_ptEnd))
  2053. {
  2054. DrawObj *pObj;
  2055. pObj = m_pGraphicTracker;
  2056. //
  2057. // Erase the last traking
  2058. //
  2059. pObj->Draw();
  2060. if(m_pToolCur->ToolType() == TOOLTYPE_PEN || m_pToolCur->ToolType() == TOOLTYPE_HIGHLIGHT)
  2061. {
  2062. // DO nothing because we drew it already and all the attributes are also already set
  2063. // Stop the update timer
  2064. ::KillTimer(m_hwnd, TIMER_GRAPHIC_UPDATE);
  2065. }
  2066. else
  2067. {
  2068. RECT rect;
  2069. rect.left = m_ptStart.x;
  2070. rect.top = m_ptStart.y;
  2071. rect.right = m_ptEnd.x;
  2072. rect.bottom = m_ptEnd.y;
  2073. pObj->SetRect(&rect);
  2074. pObj->SetPenThickness(m_pToolCur->GetWidth());
  2075. ::InflateRect(&rect, m_pToolCur->GetWidth()/2, m_pToolCur->GetWidth()/2);
  2076. pObj->SetBoundsRect(&rect);
  2077. pObj->SetPenColor(m_pToolCur->GetColor(), TRUE);
  2078. pObj->SetFillColor(m_pToolCur->GetColor(), (m_pToolCur->ToolType() == TOOLTYPE_FILLEDELLIPSE || m_pToolCur->ToolType() == TOOLTYPE_FILLEDBOX));
  2079. pObj->SetROP(m_pToolCur->GetROP());
  2080. POINT deltaPoint;
  2081. deltaPoint.x = m_ptEnd.x - m_ptStart.x;
  2082. deltaPoint.y = m_ptEnd.y - m_ptStart.y;
  2083. pObj->AddPoint(deltaPoint);
  2084. //
  2085. // Draw the object
  2086. //
  2087. pObj->Draw();
  2088. }
  2089. //
  2090. // We are done with this drawing
  2091. //
  2092. pObj->SetIsCompleted(TRUE);
  2093. pObj->SetViewState(unselected_chosen);
  2094. //
  2095. // If the object was alredy added just send an edit
  2096. //
  2097. if(pObj->GetMyWorkspace())
  2098. {
  2099. pObj->OnObjectEdit();
  2100. }
  2101. else
  2102. {
  2103. // Add the object to the list of objects
  2104. pObj->AddToWorkspace();
  2105. }
  2106. }
  2107. else
  2108. {
  2109. delete m_pGraphicTracker;
  2110. }
  2111. m_pGraphicTracker =NULL;
  2112. }
  2113. //
  2114. //
  2115. // Function: EndTextEntry
  2116. //
  2117. // Purpose: The user has finished entering a text object. The parameter
  2118. // indicates whether the changes are to be accepted or
  2119. // discarded.
  2120. //
  2121. //
  2122. void WbDrawingArea::EndTextEntry(BOOL bAccept)
  2123. {
  2124. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::EndTextEntry");
  2125. WorkspaceObj * pWorkspace = m_pTextEditor->GetMyWorkspace();
  2126. // Deactivate the text editor
  2127. DeactivateTextEditor();
  2128. if(bAccept &&( m_pTextEditor->strTextArray.GetSize()) )
  2129. {
  2130. if(!pWorkspace && m_pTextEditor->strTextArray.GetSize())
  2131. {
  2132. m_pTextEditor->AddToWorkspace();
  2133. }
  2134. else
  2135. {
  2136. if(m_pTextEditor->HasTextChanged())
  2137. {
  2138. m_pTextEditor->OnObjectEdit();
  2139. }
  2140. }
  2141. //
  2142. // Tell the other nodes they can edit this object now
  2143. //
  2144. m_pTextEditor->SetViewState(unselected_chosen);
  2145. m_pTextEditor->OnObjectEdit();
  2146. }
  2147. else
  2148. {
  2149. //
  2150. // if we were already added by a WM_TIMER message
  2151. //
  2152. if(pWorkspace)
  2153. {
  2154. //
  2155. // Tell the other nodes we deleted this text.
  2156. //
  2157. m_pTextEditor->OnObjectDelete();
  2158. //
  2159. // If we delete localy we add this object to the trash can, but we really want to delete it
  2160. //
  2161. m_pTextEditor->ClearDeletionFlags();
  2162. pWorkspace->RemoveT126Object(m_pTextEditor);
  2163. }
  2164. else
  2165. {
  2166. delete m_pTextEditor;
  2167. }
  2168. }
  2169. m_pTextEditor = NULL;
  2170. }
  2171. //
  2172. //
  2173. // Function: Zoom
  2174. //
  2175. // Purpose: Toggle the zoom state of the drawing area
  2176. //
  2177. //
  2178. void WbDrawingArea::Zoom(void)
  2179. {
  2180. RECT rcClient;
  2181. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::Zoom");
  2182. // We zoom focusing on the centre of the window
  2183. ::GetClientRect(m_hwnd, &rcClient);
  2184. long xOffset = (rcClient.right - (rcClient.right / m_iZoomOption)) / 2;
  2185. long yOffset = (rcClient.bottom - (rcClient.bottom / m_iZoomOption)) / 2;
  2186. if (m_iZoomFactor != 1)
  2187. {
  2188. // We are already zoomed move back to unzoomed state
  2189. // First save the scroll position in case we return to zoom immediately
  2190. m_posZoomScroll = m_posScroll;
  2191. m_zoomRestoreScroll = TRUE;
  2192. m_posScroll.x -= xOffset;
  2193. m_posScroll.y -= yOffset;
  2194. ::ScaleViewportExtEx(m_hDCCached, 1, m_iZoomFactor, 1, m_iZoomFactor, NULL);
  2195. m_iZoomFactor = 1;
  2196. }
  2197. else
  2198. {
  2199. // We are not zoomed so do it
  2200. if (m_zoomRestoreScroll)
  2201. {
  2202. m_posScroll = m_posZoomScroll;
  2203. }
  2204. else
  2205. {
  2206. m_posScroll.x += xOffset;
  2207. m_posScroll.y += yOffset;
  2208. }
  2209. m_iZoomFactor = m_iZoomOption;
  2210. ::ScaleViewportExtEx(m_hDCCached, m_iZoomFactor, 1, m_iZoomFactor, 1, NULL);
  2211. // ADDED BY RAND - don't allow text editing in zoom mode
  2212. if( (m_pToolCur == NULL) || (m_pToolCur->ToolType() == TOOLTYPE_TEXT) )
  2213. ::SendMessage(g_pMain->m_hwnd, WM_COMMAND, IDM_TOOLS_START, 0 );
  2214. }
  2215. TRACE_MSG(("Set zoom factor to %d", m_iZoomFactor));
  2216. // Update the scroll information
  2217. SetScrollRange(rcClient.right, rcClient.bottom);
  2218. ValidateScrollPos();
  2219. ::SetScrollPos(m_hwnd, SB_HORZ, m_posScroll.x, TRUE);
  2220. ::SetScrollPos(m_hwnd, SB_VERT, m_posScroll.y, TRUE);
  2221. // Update the origin offset from the scroll position
  2222. m_originOffset.cx = m_posScroll.x;
  2223. m_originOffset.cy = m_posScroll.y;
  2224. ::SetWindowOrgEx(m_hDCCached, m_originOffset.cx, m_originOffset.cy, NULL);
  2225. // Tell the parent that the scroll position has changed
  2226. ::PostMessage(g_pMain->m_hwnd, WM_USER_PRIVATE_PARENTNOTIFY, WM_VSCROLL, 0L);
  2227. //
  2228. // Update the tool/menu item states, since our zoom state has changed
  2229. // and that will enable/disable some tools, etc.
  2230. //
  2231. g_pMain->SetMenuStates(::GetSubMenu(::GetMenu(g_pMain->m_hwnd), 3));
  2232. // Redraw the window
  2233. ::InvalidateRect(m_hwnd, NULL, TRUE);
  2234. }
  2235. //
  2236. //
  2237. // Function: SelectTool
  2238. //
  2239. // Purpose: Set the current tool
  2240. //
  2241. //
  2242. void WbDrawingArea::SelectTool(WbTool* pToolNew)
  2243. {
  2244. if(pToolNew == m_pToolCur)
  2245. {
  2246. return;
  2247. }
  2248. // If we are leaving text mode, complete the text entry
  2249. if (m_bTextEditorActive && (m_pToolCur->ToolType() == TOOLTYPE_TEXT)
  2250. && (pToolNew->ToolType() != TOOLTYPE_TEXT))
  2251. {
  2252. // End text entry accepting the changes
  2253. EndTextEntry(TRUE);
  2254. }
  2255. // If we are no longer in select mode, and the marker is present,
  2256. // then remove it and let the tool know it's no longer selected
  2257. if (m_pToolCur != NULL)
  2258. {
  2259. RemoveMarker();
  2260. m_pSelectedGraphic = NULL;
  2261. }
  2262. // Save the new tool
  2263. m_pToolCur = pToolNew;
  2264. }
  2265. //
  2266. //
  2267. // Function: SetSelectionColor
  2268. //
  2269. // Purpose: Set the color of the selected object
  2270. //
  2271. //
  2272. void WbDrawingArea::SetSelectionColor(COLORREF clr)
  2273. {
  2274. RECT rc;
  2275. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::SetSelectionColor");
  2276. if(g_pCurrentWorkspace)
  2277. {
  2278. RECT rect;
  2279. T126Obj* pObj;
  2280. WBPOSITION pos = g_pCurrentWorkspace->GetHeadPosition();
  2281. while(pos)
  2282. {
  2283. pObj = (T126Obj*)g_pCurrentWorkspace->GetNextObject(pos);
  2284. if(pObj && pObj->WasSelectedLocally())
  2285. {
  2286. //
  2287. // Set the new pen color
  2288. //
  2289. pObj->SetPenColor(clr, TRUE);
  2290. pObj->SetFillColor(clr, (pObj->GraphicTool() == TOOLTYPE_FILLEDELLIPSE || pObj->GraphicTool() == TOOLTYPE_FILLEDBOX));
  2291. pObj->UnDraw();
  2292. pObj->DrawRect();
  2293. //
  2294. // Send it to other nodes
  2295. //
  2296. pObj->OnObjectEdit();
  2297. //
  2298. // Draw it locally
  2299. //
  2300. pObj->Draw();
  2301. }
  2302. }
  2303. }
  2304. // If the text editor is active - redraw the text in the new color
  2305. if (m_bTextEditorActive)
  2306. {
  2307. // Change the color being used by the editor
  2308. m_pTextEditor->SetPenColor(clr, TRUE);
  2309. // Update the screen
  2310. m_pTextEditor->GetBoundsRect(&rc);
  2311. InvalidateSurfaceRect(&rc, TRUE);
  2312. }
  2313. }
  2314. //
  2315. //
  2316. // Function: SetSelectionWidth
  2317. //
  2318. // Purpose: Set the nib width used to draw the currently selected object
  2319. //
  2320. //
  2321. void WbDrawingArea::SetSelectionWidth(UINT uiWidth)
  2322. {
  2323. if(g_pCurrentWorkspace)
  2324. {
  2325. RECT rect;
  2326. T126Obj* pObj;
  2327. WBPOSITION pos = g_pCurrentWorkspace->GetHeadPosition();
  2328. while(pos)
  2329. {
  2330. pObj = (T126Obj*)g_pCurrentWorkspace->GetNextObject(pos);
  2331. if(pObj && pObj->WasSelectedLocally())
  2332. {
  2333. //
  2334. // Undraw the object
  2335. //
  2336. pObj->UnDraw();
  2337. pObj->DrawRect();
  2338. //
  2339. // Get the correct width for each object
  2340. //
  2341. WbTool* pSelectedTool = g_pMain->m_ToolArray[pObj->GraphicTool()];
  2342. pSelectedTool->SetWidthIndex(uiWidth);
  2343. pObj->SetPenThickness(pSelectedTool->GetWidth());
  2344. //
  2345. // Send it to other nodes
  2346. //
  2347. pObj->OnObjectEdit();
  2348. //
  2349. // Draw it locally
  2350. //
  2351. pObj->Draw();
  2352. }
  2353. }
  2354. }
  2355. }
  2356. //
  2357. //
  2358. // Function: SetSelectionFont
  2359. //
  2360. // Purpose: Set the font used by the currently selected object
  2361. //
  2362. //
  2363. void WbDrawingArea::SetSelectionFont(HFONT hFont)
  2364. {
  2365. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::SetSelectionFont");
  2366. // Define rectangles for redrawing
  2367. RECT rcOldBounds;
  2368. RECT rcNewBounds;
  2369. // Pass the font onto the text editor
  2370. // If the text editor is active - redraw the text in the new font
  2371. if (m_bTextEditorActive)
  2372. {
  2373. m_pTextEditor->GetBoundsRect(&rcOldBounds);
  2374. m_pTextEditor->SetFont(hFont);
  2375. // Get the new rectangle of the text
  2376. m_pTextEditor->GetBoundsRect(&rcNewBounds);
  2377. // Remove and destroy the text cursor to ensure that it
  2378. // gets re-drawn with the new size for the font
  2379. // Update the screen
  2380. InvalidateSurfaceRect(&rcOldBounds, TRUE);
  2381. InvalidateSurfaceRect(&rcNewBounds, TRUE);
  2382. // get the text cursor back
  2383. ActivateTextEditor( TRUE );
  2384. }
  2385. if(g_pCurrentWorkspace)
  2386. {
  2387. T126Obj* pObj;
  2388. WBPOSITION pos = g_pCurrentWorkspace->GetHeadPosition();
  2389. while(pos)
  2390. {
  2391. pObj = (T126Obj*)g_pCurrentWorkspace->GetNextObject(pos);
  2392. if(pObj && pObj->WasSelectedLocally() && pObj->GraphicTool() == TOOLTYPE_TEXT)
  2393. {
  2394. //
  2395. // Set the new pen color
  2396. //
  2397. ((TextObj*)pObj)->SetFont(hFont);
  2398. pObj->UnDraw();
  2399. pObj->DrawRect();
  2400. //
  2401. // Send it to other nodes
  2402. //
  2403. pObj->OnObjectEdit();
  2404. //
  2405. // Draw it locally
  2406. //
  2407. pObj->Draw();
  2408. }
  2409. }
  2410. }
  2411. }
  2412. //
  2413. //
  2414. // Function: OnSetFocus
  2415. //
  2416. // Purpose: The window is getting the focus
  2417. //
  2418. //
  2419. void WbDrawingArea::OnSetFocus(void)
  2420. {
  2421. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::OnSetFocus");
  2422. //
  2423. // If we are in text mode, we must make the text cursor visible.
  2424. //
  2425. if (m_bTextEditorActive && (m_pToolCur->ToolType() == TOOLTYPE_TEXT))
  2426. {
  2427. ActivateTextEditor(TRUE);
  2428. }
  2429. }
  2430. //
  2431. //
  2432. // Function: OnActivate
  2433. //
  2434. // Purpose: The window is being activated or deactivated
  2435. //
  2436. //
  2437. void WbDrawingArea::OnActivate(UINT uiState)
  2438. {
  2439. // Check if we are being activated or deactivated
  2440. if (uiState)
  2441. {
  2442. // We are being activated, get the focus as well
  2443. ::SetFocus(m_hwnd);
  2444. // If we are in text mode, we must make the text cursor visible
  2445. if (m_bTextEditorActive && (m_pToolCur->ToolType() == TOOLTYPE_TEXT))
  2446. {
  2447. ActivateTextEditor(TRUE);
  2448. }
  2449. }
  2450. else
  2451. {
  2452. // We are being deactivated
  2453. DeactivateTextEditor();
  2454. }
  2455. }
  2456. //
  2457. //
  2458. // Function: DeleteSelection
  2459. //
  2460. // Purpose: Delete the currently selected object
  2461. //
  2462. //
  2463. void WbDrawingArea::DeleteSelection()
  2464. {
  2465. m_pSelectedGraphic = NULL;
  2466. }
  2467. //
  2468. //
  2469. // Function: GetSelection
  2470. //
  2471. // Purpose: Return the currently selected graphic (or NULL if none).
  2472. //
  2473. //
  2474. T126Obj* WbDrawingArea::GetSelection()
  2475. {
  2476. T126Obj* pGraphic = NULL;
  2477. // If there is an object currently selected...
  2478. if (GraphicSelected())
  2479. {
  2480. // ...return it
  2481. pGraphic = m_pSelectedGraphic;
  2482. }
  2483. return pGraphic;
  2484. }
  2485. //
  2486. //
  2487. // Function: BringToTopSelection
  2488. //
  2489. // Purpose: Bring the currently selected object to the top
  2490. //
  2491. //
  2492. LRESULT WbDrawingArea::BringToTopSelection(BOOL editedLocally, T126Obj * pT126Obj)
  2493. {
  2494. T126Obj* pObj;
  2495. WBPOSITION posTail;
  2496. WBPOSITION pos;
  2497. WBPOSITION myPos;
  2498. WorkspaceObj *pWorkspace;
  2499. if(pT126Obj)
  2500. {
  2501. pos = pT126Obj->GetMyPosition();
  2502. pWorkspace = pT126Obj->GetMyWorkspace();
  2503. }
  2504. else
  2505. {
  2506. pos = g_pCurrentWorkspace->GetHeadPosition();
  2507. pWorkspace = g_pCurrentWorkspace;
  2508. }
  2509. posTail = pWorkspace->GetTailPosition();
  2510. while(pos && pos != posTail)
  2511. {
  2512. pObj = pWorkspace->GetNextObject(pos);
  2513. //
  2514. // If the graphic is selected
  2515. //
  2516. if( pObj && (pObj->IsSelected() &&
  2517. //
  2518. // We were called locally and the graphic is selected locally
  2519. //
  2520. ((editedLocally && pObj->WasSelectedLocally()) ||
  2521. //
  2522. // We were called because the graphic got edited remotely
  2523. // and it is selected remotely
  2524. ((!editedLocally && pObj->WasSelectedRemotely())))))
  2525. {
  2526. myPos = pObj->GetMyPosition();
  2527. pObj = pWorkspace->RemoveAt(myPos);
  2528. pWorkspace->AddTail(pObj);
  2529. if(pT126Obj)
  2530. {
  2531. ::InvalidateRect(m_hwnd, NULL, TRUE);
  2532. return S_OK;
  2533. }
  2534. //
  2535. // send change of z order
  2536. //
  2537. pObj->ResetAttrib();
  2538. pObj->SetZOrder(front);
  2539. pObj->OnObjectEdit();
  2540. //
  2541. // Unselect it
  2542. //
  2543. pObj->UnselectDrawingObject();
  2544. RECT rect;
  2545. pObj->GetBoundsRect(&rect);
  2546. InvalidateSurfaceRect(&rect,TRUE);
  2547. }
  2548. }
  2549. return S_OK;
  2550. }
  2551. //
  2552. //
  2553. // Function: SendToBackSelection
  2554. //
  2555. // Purpose: Send the currently marked object to the back
  2556. //
  2557. //
  2558. LRESULT WbDrawingArea::SendToBackSelection(BOOL editedLocally, T126Obj * pT126Obj)
  2559. {
  2560. // If there is an object currently selected...
  2561. T126Obj* pObj;
  2562. WBPOSITION posHead;
  2563. WBPOSITION myPos;
  2564. WBPOSITION pos;
  2565. WorkspaceObj *pWorkspace;
  2566. if(pT126Obj)
  2567. {
  2568. pos = pT126Obj->GetMyPosition();
  2569. pWorkspace = pT126Obj->GetMyWorkspace();
  2570. }
  2571. else
  2572. {
  2573. pos = g_pCurrentWorkspace->GetTailPosition();
  2574. pWorkspace = g_pCurrentWorkspace;
  2575. }
  2576. posHead = pWorkspace->GetHeadPosition();
  2577. while(pos && pos != posHead)
  2578. {
  2579. pObj = pWorkspace->GetPreviousObject(pos);
  2580. //
  2581. // If the graphic is selected
  2582. //
  2583. if( (pObj->IsSelected() &&
  2584. //
  2585. // We were called locally and the graphic is selected locally
  2586. //
  2587. ((editedLocally && pObj->WasSelectedLocally()) ||
  2588. //
  2589. // We were called because the graphic got edited remotely
  2590. // and it is selected remotely
  2591. ((!editedLocally && pObj->WasSelectedRemotely())))))
  2592. {
  2593. myPos = pObj->GetMyPosition();
  2594. pObj = pWorkspace->RemoveAt(myPos);
  2595. pWorkspace->AddHead(pObj);
  2596. if(pT126Obj)
  2597. {
  2598. ::InvalidateRect(m_hwnd, NULL, TRUE);
  2599. return S_OK;
  2600. }
  2601. //
  2602. // send change of z order
  2603. //
  2604. pObj->ResetAttrib();
  2605. pObj->SetZOrder(back);
  2606. pObj->OnObjectEdit();
  2607. //
  2608. // Unselect it
  2609. //
  2610. pObj->UnselectDrawingObject();
  2611. RECT rect;
  2612. pObj->GetBoundsRect(&rect);
  2613. ::InvalidateRect(m_hwnd, NULL , TRUE);
  2614. }
  2615. }
  2616. return S_OK;
  2617. }
  2618. //
  2619. //
  2620. // Function: Clear
  2621. //
  2622. // Purpose: Clear the drawing area.
  2623. //
  2624. //
  2625. void WbDrawingArea::Clear()
  2626. {
  2627. // Remove the recorded objects
  2628. // PG_Clear(m_hPage);
  2629. // The page will be redrawn after an event generated by the clear request
  2630. }
  2631. //
  2632. //
  2633. // Function: Attach
  2634. //
  2635. // Purpose: Change the page the window is displaying
  2636. //
  2637. //
  2638. void WbDrawingArea::Attach(WorkspaceObj* pNewWorkspace)
  2639. {
  2640. // Accept any text being edited
  2641. if (m_bTextEditorActive)
  2642. {
  2643. EndTextEntry(TRUE);
  2644. }
  2645. // finish any drawing operation now
  2646. if (m_bLButtonDown)
  2647. {
  2648. OnLButtonUp(0, m_ptStart.x, m_ptStart.y);
  2649. }
  2650. // Get rid of the selection
  2651. ClearSelection();
  2652. // Save the new page details
  2653. g_pCurrentWorkspace = pNewWorkspace;
  2654. if(IsSynced())
  2655. {
  2656. g_pConferenceWorkspace = g_pCurrentWorkspace;
  2657. }
  2658. // Force a redraw of the window to show the new contents
  2659. ::InvalidateRect(m_hwnd, NULL, TRUE);
  2660. }
  2661. //
  2662. //
  2663. // Function: DrawMarker
  2664. //
  2665. // Purpose: Draw the graphic object marker
  2666. //
  2667. //
  2668. void WbDrawingArea::DrawMarker(HDC hDC)
  2669. {
  2670. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::DrawMarker");
  2671. // Draw the marker
  2672. m_pMarker->Draw();
  2673. }
  2674. //
  2675. //
  2676. // Function: PutMarker
  2677. //
  2678. // Purpose: Draw the graphic object marker
  2679. //
  2680. //
  2681. void WbDrawingArea::PutMarker(HDC hDC, BOOL bDraw)
  2682. {
  2683. }
  2684. //
  2685. //
  2686. // Function: RemoveMarker
  2687. //
  2688. // Purpose: Remove the graphic object marker
  2689. //
  2690. //
  2691. void WbDrawingArea::RemoveMarker()
  2692. {
  2693. if(g_pCurrentWorkspace)
  2694. {
  2695. T126Obj* pObj;
  2696. WBPOSITION pos;
  2697. pos = g_pCurrentWorkspace->GetHeadPosition();
  2698. while(pos)
  2699. {
  2700. pObj = (T126Obj*)g_pCurrentWorkspace->GetNextObject(pos);
  2701. if(pObj && pObj->WasSelectedLocally())
  2702. {
  2703. pObj->UnselectDrawingObject();
  2704. }
  2705. }
  2706. }
  2707. }
  2708. //
  2709. //
  2710. // Function: ActivateTextEditor
  2711. //
  2712. // Purpose: Start a text editing session
  2713. //
  2714. //
  2715. void WbDrawingArea::ActivateTextEditor( BOOL bPutUpCusor )
  2716. {
  2717. // Record that the editor is now active
  2718. m_bTextEditorActive = TRUE;
  2719. // show editbox
  2720. m_pTextEditor->ShowBox( SW_SHOW );
  2721. // Start the timer for updating the text
  2722. m_pTextEditor->SetTimer( DRAW_GRAPHICUPDATEDELAY);
  2723. }
  2724. //
  2725. //
  2726. // Function: DeactivateTextEditor
  2727. //
  2728. // Purpose: End a text editing session
  2729. //
  2730. //
  2731. void WbDrawingArea::DeactivateTextEditor(void)
  2732. {
  2733. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::DeactivateTextEditor");
  2734. // Stop the update timer
  2735. m_pTextEditor->KillTimer();
  2736. // Show that we are not editing any text
  2737. m_bTextEditorActive = FALSE;
  2738. // hide editbox
  2739. m_pTextEditor->ShowBox( SW_HIDE );
  2740. }
  2741. //
  2742. //
  2743. // Function: SurfaceToClient
  2744. //
  2745. // Purpose: Convert a point in surface co-ordinates to client
  2746. // co-ordinates (taking account of the current zoom factor).
  2747. //
  2748. //
  2749. void WbDrawingArea::SurfaceToClient(LPPOINT lppoint)
  2750. {
  2751. lppoint->x -= m_originOffset.cx;
  2752. lppoint->x *= m_iZoomFactor;
  2753. lppoint->y -= m_originOffset.cy;
  2754. lppoint->y *= m_iZoomFactor;
  2755. }
  2756. //
  2757. //
  2758. // Function: ClientToSurface
  2759. //
  2760. // Purpose: Convert a point in client co-ordinates to surface
  2761. // co-ordinates (taking account of the current zoom factor).
  2762. //
  2763. //
  2764. void WbDrawingArea::ClientToSurface(LPPOINT lppoint)
  2765. {
  2766. ASSERT(m_iZoomFactor != 0);
  2767. lppoint->x /= m_iZoomFactor;
  2768. lppoint->x += m_originOffset.cx;
  2769. lppoint->y /= m_iZoomFactor;
  2770. lppoint->y += m_originOffset.cy;
  2771. }
  2772. //
  2773. //
  2774. // Function: SurfaceToClient
  2775. //
  2776. // Purpose: Convert a rectangle in surface co-ordinates to client
  2777. // co-ordinates (taking account of the current zoom factor).
  2778. //
  2779. //
  2780. void WbDrawingArea::SurfaceToClient(LPRECT lprc)
  2781. {
  2782. SurfaceToClient((LPPOINT)&lprc->left);
  2783. SurfaceToClient((LPPOINT)&lprc->right);
  2784. }
  2785. //
  2786. //
  2787. // Function: ClientToSurface
  2788. //
  2789. // Purpose: Convert a rectangle in client co-ordinates to surface
  2790. // co-ordinates (taking account of the current zoom factor).
  2791. //
  2792. //
  2793. void WbDrawingArea::ClientToSurface(LPRECT lprc)
  2794. {
  2795. ClientToSurface((LPPOINT)&lprc->left);
  2796. ClientToSurface((LPPOINT)&lprc->right);
  2797. }
  2798. //
  2799. //
  2800. // Function: GraphicSelected
  2801. //
  2802. // Purpose: Return TRUE if a graphic is currently selected
  2803. //
  2804. //
  2805. BOOL WbDrawingArea::GraphicSelected(void)
  2806. {
  2807. if(g_pCurrentWorkspace)
  2808. {
  2809. T126Obj* pObj;
  2810. WBPOSITION pos = g_pCurrentWorkspace->GetHeadPosition();
  2811. while(pos)
  2812. {
  2813. pObj = (T126Obj*)g_pCurrentWorkspace->GetNextObject(pos);
  2814. if(pObj && pObj->WasSelectedLocally())
  2815. {
  2816. m_pSelectedGraphic = pObj;
  2817. return TRUE;
  2818. }
  2819. }
  2820. }
  2821. return FALSE;
  2822. }
  2823. BOOL WbDrawingArea::MoveSelectedGraphicBy(LONG x, LONG y)
  2824. {
  2825. T126Obj* pObj;
  2826. WBPOSITION pos = g_pCurrentWorkspace->GetHeadPosition();
  2827. while(pos)
  2828. {
  2829. pObj = (T126Obj*)g_pCurrentWorkspace->GetNextObject(pos);
  2830. if(pObj && pObj->WasSelectedLocally())
  2831. {
  2832. pObj->MoveBy(x, y);
  2833. }
  2834. }
  2835. return FALSE;
  2836. }
  2837. void WbDrawingArea::EraseSelectedDrawings(void)
  2838. {
  2839. T126Obj* pObj;
  2840. //
  2841. // Burn trash
  2842. //
  2843. pObj = (T126Obj *)g_pTrash->RemoveTail();
  2844. while (pObj != NULL)
  2845. {
  2846. delete pObj;
  2847. pObj = (T126Obj *) g_pTrash->RemoveTail();
  2848. }
  2849. WBPOSITION pos = g_pCurrentWorkspace->GetHeadPosition();
  2850. while(pos)
  2851. {
  2852. pObj = (T126Obj*)g_pCurrentWorkspace->GetNextObject(pos);
  2853. if(pObj && pObj->WasSelectedLocally() && pObj->GraphicTool() != TOOLTYPE_REMOTEPOINTER)
  2854. {
  2855. pObj->DeletedLocally();
  2856. g_pCurrentWorkspace->RemoveT126Object(pObj);
  2857. }
  2858. }
  2859. }
  2860. void WbDrawingArea::EraseInitialDrawFinal(LONG x, LONG y, BOOL editedLocally, T126Obj* pObj)
  2861. {
  2862. T126Obj* pGraphic;
  2863. WorkspaceObj * pWorkspace; WBPOSITION pos;
  2864. if(pObj)
  2865. {
  2866. pWorkspace = pObj->GetMyWorkspace();
  2867. pGraphic = pObj;
  2868. }
  2869. else
  2870. {
  2871. pWorkspace = g_pCurrentWorkspace;
  2872. }
  2873. //
  2874. // Check if the objects workspace is valid or if there is a current workspace
  2875. //
  2876. if(pWorkspace == NULL)
  2877. {
  2878. return;
  2879. }
  2880. pos = pWorkspace->GetHeadPosition();
  2881. while(pos)
  2882. {
  2883. // if we are talking about an specifc object
  2884. if(!pObj)
  2885. {
  2886. pGraphic = (T126Obj*)pWorkspace->GetNextObject(pos);
  2887. }
  2888. //
  2889. // If the graphic is selected
  2890. //
  2891. if(pGraphic &&
  2892. //
  2893. // We were called locally and the graphic is selected locally
  2894. //
  2895. ((editedLocally && pGraphic->WasSelectedLocally()) ||
  2896. //
  2897. // We were called because the graphic got edited remotely
  2898. // and it is selected remotely
  2899. //
  2900. (!editedLocally)))
  2901. {
  2902. POINT finalAnchorPoint;
  2903. RECT initialRect;
  2904. RECT rect;
  2905. RECT initialBoundsRect;
  2906. RECT boundsRect;
  2907. //
  2908. // Get The final Rects
  2909. //
  2910. pGraphic->GetRect(&rect);
  2911. pGraphic->GetBoundsRect(&boundsRect);
  2912. initialRect = rect;
  2913. initialBoundsRect = boundsRect;
  2914. pGraphic->GetAnchorPoint(&finalAnchorPoint);
  2915. //
  2916. // Find out were the drawing was
  2917. //
  2918. ::OffsetRect(&initialRect, x, y);
  2919. ::OffsetRect(&initialBoundsRect, x, y);
  2920. pGraphic->SetRect(&initialRect);
  2921. pGraphic->SetBoundsRect(&initialBoundsRect);
  2922. pGraphic->SetAnchorPoint(finalAnchorPoint.x + x, finalAnchorPoint.y + y);
  2923. //
  2924. // Erase initial drawing
  2925. //
  2926. pGraphic->UnDraw();
  2927. //
  2928. //Erase the selection rectangle only if we selected locally
  2929. //
  2930. if(editedLocally)
  2931. {
  2932. pGraphic->DrawRect();
  2933. }
  2934. //
  2935. // The only attributes we want to send unselected and anchorpoint
  2936. //
  2937. pGraphic->ResetAttrib();
  2938. //
  2939. // Restore rectangles and draw the object in the final position
  2940. //
  2941. pGraphic->SetRect(&rect);
  2942. pGraphic->SetBoundsRect(&boundsRect);
  2943. pGraphic->SetAnchorPoint(finalAnchorPoint.x, finalAnchorPoint.y);
  2944. pGraphic->Draw(FALSE);
  2945. //
  2946. // Don't send it if it was not created locally
  2947. //
  2948. if(editedLocally)
  2949. {
  2950. pGraphic->EditedLocally();
  2951. //
  2952. // Sends the final drawing to the other nodes
  2953. //
  2954. pGraphic->OnObjectEdit();
  2955. //
  2956. // This will remove the selection box and send a
  2957. // edit PDU telling other nodes the object is not selected
  2958. //
  2959. pGraphic->UnselectDrawingObject();
  2960. }
  2961. }
  2962. //
  2963. // Just moved one specifc object
  2964. //
  2965. if(pObj != NULL)
  2966. {
  2967. return;
  2968. }
  2969. }
  2970. }
  2971. //
  2972. //
  2973. // Function: SelectGraphic
  2974. //
  2975. // Purpose: Select a graphic - save the pointer to the graphic and
  2976. // draw the marker on it.
  2977. //
  2978. //
  2979. void WbDrawingArea::SelectGraphic(T126Obj* pGraphic,
  2980. BOOL bEnableForceAdd,
  2981. BOOL bForceAdd )
  2982. {
  2983. BOOL bZapCurrentSelection;
  2984. RECT rc;
  2985. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::SelectGraphic");
  2986. if(pGraphic->IsSelected() && pGraphic->WasSelectedLocally())
  2987. {
  2988. pGraphic->UnselectDrawingObject();
  2989. return;
  2990. }
  2991. else if(pGraphic->IsSelected() && pGraphic->WasSelectedRemotely())
  2992. {
  2993. return;
  2994. }
  2995. else
  2996. {
  2997. // new selection, add to list or replace list?
  2998. if( bEnableForceAdd )
  2999. {
  3000. bZapCurrentSelection = !bForceAdd;
  3001. }
  3002. else
  3003. {
  3004. bZapCurrentSelection = ((GetAsyncKeyState( VK_SHIFT ) >= 0) && (GetAsyncKeyState( VK_CONTROL ) >= 0));
  3005. }
  3006. if( bZapCurrentSelection )
  3007. {
  3008. // replace list
  3009. RemoveMarker();
  3010. }
  3011. }
  3012. // Update the attributes window to show graphic is selected
  3013. m_pToolCur->SelectGraphic(pGraphic);
  3014. pGraphic->SelectDrawingObject();
  3015. HWND hwndParent = ::GetParent(m_hwnd);
  3016. if (hwndParent != NULL)
  3017. {
  3018. ::PostMessage(hwndParent, WM_USER_UPDATE_ATTRIBUTES, 0, 0);
  3019. }
  3020. }
  3021. //
  3022. //
  3023. // Function: DeselectGraphic
  3024. //
  3025. // Purpose: Deselect a graphic - remove the marker and delete the
  3026. // graphic object associated with it.
  3027. //
  3028. //
  3029. void WbDrawingArea::DeselectGraphic(void)
  3030. {
  3031. HWND hwndParent = ::GetParent(m_hwnd);
  3032. if (hwndParent != NULL)
  3033. {
  3034. ::PostMessage(hwndParent, WM_USER_UPDATE_ATTRIBUTES, 0, 0);
  3035. }
  3036. }
  3037. //
  3038. //
  3039. // Function: GetVisibleRect
  3040. //
  3041. // Purpose: Return the rectangle of the surface currently visible in the
  3042. // drawing area window.
  3043. //
  3044. //
  3045. void WbDrawingArea::GetVisibleRect(LPRECT lprc)
  3046. {
  3047. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::VisibleRect");
  3048. // Get the client rectangle
  3049. ::GetClientRect(m_hwnd, lprc);
  3050. // Convert to surface co-ordinates
  3051. ClientToSurface(lprc);
  3052. }
  3053. //
  3054. //
  3055. // Function: MoveOntoSurface
  3056. //
  3057. // Purpose: If a given point is outwith the surface rect, move it on
  3058. //
  3059. //
  3060. void WbDrawingArea::MoveOntoSurface(LPPOINT lppoint)
  3061. {
  3062. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::MoveOntoSurface");
  3063. //
  3064. // Make sure that the position is within the surface rect
  3065. //
  3066. if (lppoint->x < 0)
  3067. {
  3068. lppoint->x = 0;
  3069. }
  3070. else if (lppoint->x >= DRAW_WIDTH)
  3071. {
  3072. lppoint->x = DRAW_WIDTH - 1;
  3073. }
  3074. if (lppoint->y < 0)
  3075. {
  3076. lppoint->y = 0;
  3077. }
  3078. else if (lppoint->y >= DRAW_HEIGHT)
  3079. {
  3080. lppoint->y = DRAW_HEIGHT - 1;
  3081. }
  3082. }
  3083. //
  3084. //
  3085. // Function: GetOrigin
  3086. //
  3087. // Purpose: Provide current origin of display
  3088. //
  3089. //
  3090. void WbDrawingArea::GetOrigin(LPPOINT lppoint)
  3091. {
  3092. lppoint->x = m_originOffset.cx;
  3093. lppoint->y = m_originOffset.cy;
  3094. }
  3095. void WbDrawingArea::ShutDownDC(void)
  3096. {
  3097. UnPrimeDC(m_hDCCached);
  3098. if (m_hDCWindow != NULL)
  3099. {
  3100. ::ReleaseDC(m_hwnd, m_hDCWindow);
  3101. m_hDCWindow = NULL;
  3102. }
  3103. m_hDCCached = NULL;
  3104. }
  3105. void WbDrawingArea::ClearSelection( void )
  3106. {
  3107. MLZ_EntryOut(ZONE_FUNCTION, "WbDrawingArea::ClearSelection");
  3108. RemoveMarker();
  3109. g_pMain->OnUpdateAttributes();
  3110. }
  3111. void WbDrawingArea::OnCancelMode( void )
  3112. {
  3113. // We were dragging but lost mouse control, gracefully end the drag (NM4db:573)
  3114. POINT pt;
  3115. ::GetCursorPos(&pt);
  3116. ::ScreenToClient(m_hwnd, &pt);
  3117. OnLButtonUp(0, pt.x, pt.y);
  3118. m_bLButtonDown = FALSE;
  3119. }