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.

1023 lines
26 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) 2002 Microsoft Corporation. All rights reserved.
  3. // Copyright (c) 2002 OSR Open Systems Resources, Inc.
  4. //
  5. // DockDialogBar.cpp - implementation of the CDockDialogBar class
  6. //////////////////////////////////////////////////////////////////////////////
  7. #include "stdafx.h"
  8. #include "DockDialogBar.h"
  9. #ifdef _DEBUG
  10. #define new DEBUG_NEW
  11. #undef THIS_FILE
  12. static char THIS_FILE[] = __FILE__;
  13. #endif
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CDockDialogBar
  16. IMPLEMENT_DYNAMIC(CDockDialogBar, CControlBar);
  17. CDockDialogBar::CDockDialogBar() :
  18. m_clrBtnHilight(::GetSysColor(COLOR_BTNHILIGHT)),
  19. m_clrBtnShadow(::GetSysColor(COLOR_BTNSHADOW))
  20. {
  21. m_sizeMin = CSize(32, 32);
  22. m_sizeHorz = CSize(200, 200);
  23. m_sizeVert = CSize(200, 200);
  24. m_sizeFloat = CSize(200, 200);
  25. m_bTracking = FALSE;
  26. m_bInRecalcNC = FALSE;
  27. m_cxEdge = 6;
  28. m_cxBorder = 3;
  29. m_cxGripper = 15;
  30. m_pDialog = NULL;
  31. m_brushBkgd.CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  32. m_cyBorder = 3;
  33. m_cCaptionSize = GetSystemMetrics(SM_CYSMCAPTION);
  34. m_cMinWidth = GetSystemMetrics(SM_CXMIN);
  35. m_cMinHeight = GetSystemMetrics(SM_CYMIN);
  36. m_bKeepSize = TRUE;
  37. m_bShowTitleInGripper = FALSE;
  38. }
  39. CDockDialogBar::~CDockDialogBar()
  40. {
  41. }
  42. BEGIN_MESSAGE_MAP(CDockDialogBar, CControlBar)
  43. //{{AFX_MSG_MAP(CDockDialogBar)
  44. ON_WM_LBUTTONUP()
  45. ON_WM_MOUSEMOVE()
  46. ON_WM_SETCURSOR()
  47. ON_WM_WINDOWPOSCHANGING()
  48. ON_WM_WINDOWPOSCHANGED()
  49. ON_WM_NCPAINT()
  50. ON_WM_NCLBUTTONDOWN()
  51. ON_WM_NCHITTEST()
  52. ON_WM_NCCALCSIZE()
  53. ON_WM_LBUTTONDOWN()
  54. ON_WM_CAPTURECHANGED()
  55. ON_WM_LBUTTONDBLCLK()
  56. ON_WM_NCLBUTTONDBLCLK()
  57. ON_WM_SIZE()
  58. //}}AFX_MSG_MAP
  59. END_MESSAGE_MAP()
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CDockDialogBar message handlers
  62. void CDockDialogBar::OnUpdateCmdUI(class CFrameWnd *pTarget, int bDisableIfNoHndler)
  63. {
  64. UpdateDialogControls(pTarget, bDisableIfNoHndler);
  65. }
  66. BOOL CDockDialogBar::Create(CWnd *pParentWnd,
  67. CDialog *pDialog,
  68. CString &pTitle,
  69. UINT nID,
  70. DWORD dwStyle,
  71. BOOL bShowTitleInGripper)
  72. {
  73. ASSERT_VALID(pParentWnd); // must have a parent
  74. ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC)));
  75. //
  76. // save the style
  77. //
  78. m_dwStyle = dwStyle & CBRS_ALL;
  79. //
  80. // Determine whether or not to display the title
  81. // in the gripper bar
  82. //
  83. m_bShowTitleInGripper = bShowTitleInGripper;
  84. //
  85. // Adjust the gripper width if necessary
  86. //
  87. if(m_bShowTitleInGripper) {
  88. m_cxGripper = 25;
  89. }
  90. //
  91. // create the base window
  92. //
  93. CString wndclass = AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(NULL, IDC_ARROW),
  94. m_brushBkgd, 0);
  95. if (!CWnd::Create(wndclass, pTitle, dwStyle, CRect(0,0,0,0),
  96. pParentWnd, 0)) {
  97. return FALSE;
  98. }
  99. m_pTitle = (LPCTSTR)pTitle;
  100. //
  101. // create the child dialog
  102. //
  103. m_pDialog = pDialog;
  104. m_pDialog->Create(nID, this);
  105. //
  106. // use the dialog dimensions as default base dimensions
  107. //
  108. CRect rc;
  109. m_pDialog->GetWindowRect(rc);
  110. m_sizeHorz = m_sizeVert = m_sizeFloat = rc.Size();
  111. m_sizeHorz.cy += m_cxEdge + m_cxBorder;
  112. m_sizeVert.cx += m_cxEdge + m_cxBorder;
  113. return TRUE;
  114. }
  115. CSize CDockDialogBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  116. {
  117. CRect rc;
  118. LONG availableHeight;
  119. LONG actualHeight;
  120. LONG rowHeight;
  121. LONG diff;
  122. LONG oldDiff;
  123. LONG adjustment;
  124. CString str;
  125. LONG ii;
  126. BOOL bFound;
  127. BOOL bIsMinimum;
  128. CDockBar *pDockBar;
  129. CDockDialogBar *pBar;
  130. CPtrArray barArray;
  131. m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP)->GetWindowRect(rc);
  132. int nHorzDockBarWidth = bStretch ? 32767 : rc.Width() + 4;
  133. m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_LEFT)->GetWindowRect(rc);
  134. int nVertDockBarHeight = bStretch ? 32767 : rc.Height() + 4;
  135. if(IsFloating()) {
  136. return m_sizeFloat;
  137. }
  138. CFrameWnd *pFrame = GetParentFrame();
  139. if(pFrame == NULL) {
  140. if (bHorz)
  141. return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  142. else
  143. return CSize(m_sizeVert.cx, nVertDockBarHeight);
  144. }
  145. //
  146. // Get the available screen height
  147. //
  148. pFrame->GetClientRect(rc);
  149. ScreenToClient(rc);
  150. //
  151. // Client rect height minus the status bar height
  152. //
  153. availableHeight = rc.Height() - 18;
  154. actualHeight = 0;
  155. pDockBar = (CDockBar *)m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP);
  156. if(pDockBar == NULL) {
  157. if (bHorz)
  158. return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  159. else
  160. return CSize(m_sizeVert.cx, nVertDockBarHeight);
  161. }
  162. bFound = FALSE;
  163. rowHeight = 0;
  164. //
  165. // Walk the top rows
  166. //
  167. for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
  168. pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
  169. if(pBar == NULL) {
  170. if(!bFound) {
  171. availableHeight -= rowHeight;
  172. }
  173. rowHeight = 0;
  174. continue;
  175. }
  176. if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
  177. if(!bFound && pBar != this) {
  178. if (bHorz)
  179. return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  180. else
  181. return CSize(m_sizeVert.cx, nVertDockBarHeight);
  182. }
  183. bFound = TRUE;
  184. barArray.Add(pBar);
  185. //
  186. // We position these with one border overlapping
  187. // so subtract one part of a border width from the size
  188. //
  189. actualHeight += (pBar->m_sizeHorz.cy - 2);
  190. continue;
  191. }
  192. pBar->GetWindowRect(rc);
  193. rowHeight = max(rowHeight, rc.Height());
  194. }
  195. pDockBar = (CDockBar *)m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_BOTTOM);
  196. if(pDockBar == NULL) {
  197. if (bHorz)
  198. return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  199. else
  200. return CSize(m_sizeVert.cx, nVertDockBarHeight);
  201. }
  202. bFound = FALSE;
  203. rowHeight = 0;
  204. //
  205. // Walk the bottom rows
  206. //
  207. for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
  208. pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
  209. if(pBar == NULL) {
  210. if(!bFound) {
  211. availableHeight -= rowHeight;
  212. }
  213. rowHeight = 0;
  214. continue;
  215. }
  216. if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
  217. bFound = TRUE;
  218. barArray.Add(pBar);
  219. //
  220. // We position these with one border overlapping
  221. // so subtract one part of a border width from the size
  222. //
  223. actualHeight += (pBar->m_sizeHorz.cy - 2);
  224. continue;
  225. }
  226. pBar->GetWindowRect(rc);
  227. rowHeight = max(rowHeight, rc.Height());
  228. }
  229. diff = availableHeight - actualHeight;
  230. if(diff == 0) {
  231. if (bHorz)
  232. return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  233. else
  234. return CSize(m_sizeVert.cx, nVertDockBarHeight);
  235. }
  236. adjustment = (diff > 0) ? 1 : -1;
  237. //
  238. // walk through our array and adjust the heights
  239. //
  240. while(diff != 0) {
  241. oldDiff = diff;
  242. for(ii = 0; ii < barArray.GetSize(); ii++) {
  243. pBar = (CDockDialogBar *)barArray[ii];
  244. if(pBar->m_bKeepSize) {
  245. continue;
  246. }
  247. if((pBar->m_sizeHorz.cy + adjustment) >= pBar->m_sizeMin.cy) {
  248. pBar->m_sizeHorz.cy += adjustment;
  249. diff -= adjustment;
  250. if(diff == 0) {
  251. break;
  252. }
  253. }
  254. }
  255. if(oldDiff == diff) {
  256. bIsMinimum = TRUE;
  257. for(ii = 0; ii < barArray.GetSize(); ii++) {
  258. pBar = (CDockDialogBar *)barArray[ii];
  259. if(pBar->m_bKeepSize == TRUE) {
  260. bIsMinimum = FALSE;
  261. }
  262. pBar->m_bKeepSize = FALSE;
  263. }
  264. if(bIsMinimum) {
  265. break;
  266. }
  267. }
  268. }
  269. for(ii = 0; ii < barArray.GetSize(); ii++) {
  270. pBar = (CDockDialogBar *)barArray[ii];
  271. pBar->m_bKeepSize = FALSE;
  272. }
  273. if (bHorz)
  274. return CSize(nHorzDockBarWidth, m_sizeHorz.cy);
  275. else
  276. return CSize(m_sizeVert.cx, nVertDockBarHeight);
  277. }
  278. CSize CDockDialogBar::CalcDynamicLayout(int nLength, DWORD dwMode)
  279. {
  280. if (IsFloating())
  281. {
  282. //
  283. // Get the frame window for this dock dialog bar
  284. // It better not be the main window
  285. //
  286. CFrameWnd* pFrameWnd = GetParentFrame();
  287. if ( pFrameWnd != AfxGetMainWnd() )
  288. {
  289. //
  290. // Disable the SC_CLOSE Control for floating window
  291. //
  292. EnableMenuItem(::GetSystemMenu(pFrameWnd->m_hWnd, FALSE),
  293. SC_CLOSE,
  294. MF_BYCOMMAND | MF_GRAYED);
  295. }
  296. //
  297. // Enable diagonal arrow cursor for resizing
  298. //
  299. GetParent()->GetParent()->ModifyStyle(0, MFS_4THICKFRAME);
  300. }
  301. if (dwMode & (LM_HORZDOCK | LM_VERTDOCK))
  302. {
  303. SetWindowPos(NULL, 0, 0, 0, 0,
  304. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER |
  305. SWP_NOACTIVATE | SWP_FRAMECHANGED);
  306. m_pDockSite->RecalcLayout();
  307. return CControlBar::CalcDynamicLayout(nLength,dwMode);
  308. }
  309. if (dwMode & LM_MRUWIDTH)
  310. return m_sizeFloat;
  311. if (dwMode & LM_COMMIT)
  312. {
  313. m_sizeFloat.cx = nLength;
  314. return m_sizeFloat;
  315. }
  316. if (IsFloating())
  317. {
  318. RECT window_rect;
  319. POINT cursor_pt;
  320. GetCursorPos(&cursor_pt);
  321. GetParent()->GetParent()->GetWindowRect(&window_rect);
  322. switch (m_pDockContext->m_nHitTest)
  323. {
  324. case HTTOPLEFT:
  325. m_sizeFloat.cx = max(window_rect.right - cursor_pt.x,
  326. m_cMinWidth) - m_cxBorder;
  327. m_sizeFloat.cy = max(window_rect.bottom - m_cCaptionSize -
  328. cursor_pt.y,m_cMinHeight) - 1;
  329. m_pDockContext->m_rectFrameDragHorz.top = min(cursor_pt.y,
  330. window_rect.bottom - m_cCaptionSize - m_cMinHeight) -
  331. m_cyBorder;
  332. m_pDockContext->m_rectFrameDragHorz.left = min(cursor_pt.x,
  333. window_rect.right - m_cMinWidth) - 1;
  334. return m_sizeFloat;
  335. case HTTOPRIGHT:
  336. m_sizeFloat.cx = max(cursor_pt.x - window_rect.left,
  337. m_cMinWidth);
  338. m_sizeFloat.cy = max(window_rect.bottom - m_cCaptionSize -
  339. cursor_pt.y,m_cMinHeight) - 1;
  340. m_pDockContext->m_rectFrameDragHorz.top = min(cursor_pt.y,
  341. window_rect.bottom - m_cCaptionSize - m_cMinHeight) -
  342. m_cyBorder;
  343. return m_sizeFloat;
  344. case HTBOTTOMLEFT:
  345. m_sizeFloat.cx = max(window_rect.right - cursor_pt.x,
  346. m_cMinWidth) - m_cxBorder;
  347. m_sizeFloat.cy = max(cursor_pt.y - window_rect.top -
  348. m_cCaptionSize,m_cMinHeight);
  349. m_pDockContext->m_rectFrameDragHorz.left = min(cursor_pt.x,
  350. window_rect.right - m_cMinWidth) - 1;
  351. return m_sizeFloat;
  352. case HTBOTTOMRIGHT:
  353. m_sizeFloat.cx = max(cursor_pt.x - window_rect.left,
  354. m_cMinWidth);
  355. m_sizeFloat.cy = max(cursor_pt.y - window_rect.top -
  356. m_cCaptionSize,m_cMinHeight);
  357. return m_sizeFloat;
  358. }
  359. }
  360. if (dwMode & LM_LENGTHY)
  361. return CSize(m_sizeFloat.cx,
  362. m_sizeFloat.cy = max(m_sizeMin.cy, nLength));
  363. else
  364. return CSize(max(m_sizeMin.cx, nLength), m_sizeFloat.cy);
  365. }
  366. void CDockDialogBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  367. {
  368. CControlBar::OnWindowPosChanging(lpwndpos);
  369. }
  370. void CDockDialogBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos)
  371. {
  372. CControlBar::OnWindowPosChanged(lpwndpos);
  373. if(!::IsWindow(m_hWnd) || m_pDialog==NULL)
  374. return;
  375. if(!::IsWindow(m_pDialog->m_hWnd))
  376. return;
  377. if (m_bInRecalcNC)
  378. {
  379. CRect rc;
  380. GetClientRect(rc);
  381. m_pDialog->MoveWindow(rc);
  382. return;
  383. }
  384. //
  385. // Find on which side are we docked
  386. //
  387. UINT nDockBarID = GetParent()->GetDlgCtrlID();
  388. //
  389. // Return if dropped at same location
  390. //
  391. if (nDockBarID == m_nDockBarID // no docking side change
  392. && (lpwndpos->flags & SWP_NOSIZE) // no size change
  393. && ((m_dwStyle & CBRS_BORDER_ANY) != CBRS_BORDER_ANY))
  394. return;
  395. m_nDockBarID = nDockBarID;
  396. //
  397. // Force recalc the non-client area
  398. //
  399. m_bInRecalcNC = TRUE;
  400. SetWindowPos(NULL, 0,0,0,0,
  401. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
  402. m_bInRecalcNC = FALSE;
  403. }
  404. BOOL CDockDialogBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  405. {
  406. if ((nHitTest != HTSIZE) || m_bTracking)
  407. return CControlBar::OnSetCursor(pWnd, nHitTest, message);
  408. if (IsHorz())
  409. SetCursor(LoadCursor(NULL, IDC_SIZENS));
  410. else
  411. SetCursor(LoadCursor(NULL, IDC_SIZEWE));
  412. return TRUE;
  413. }
  414. /////////////////////////////////////////////////////////////////////////
  415. // Mouse Handling
  416. //
  417. void CDockDialogBar::OnLButtonUp(UINT nFlags, CPoint point)
  418. {
  419. if (!m_bTracking)
  420. CControlBar::OnLButtonUp(nFlags, point);
  421. else
  422. {
  423. ClientToWnd(point);
  424. StopTracking(TRUE);
  425. }
  426. }
  427. void CDockDialogBar::OnMouseMove(UINT nFlags, CPoint point)
  428. {
  429. if (IsFloating() || !m_bTracking)
  430. {
  431. CControlBar::OnMouseMove(nFlags, point);
  432. return;
  433. }
  434. CPoint cpt = m_rectTracker.CenterPoint();
  435. ClientToWnd(point);
  436. if (IsHorz())
  437. {
  438. if (cpt.y != point.y)
  439. {
  440. OnInvertTracker(m_rectTracker);
  441. m_rectTracker.OffsetRect(0, point.y - cpt.y);
  442. OnInvertTracker(m_rectTracker);
  443. }
  444. }
  445. else
  446. {
  447. if (cpt.x != point.x)
  448. {
  449. OnInvertTracker(m_rectTracker);
  450. m_rectTracker.OffsetRect(point.x - cpt.x, 0);
  451. OnInvertTracker(m_rectTracker);
  452. }
  453. }
  454. }
  455. void CDockDialogBar::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
  456. {
  457. //
  458. // Compute the rectangle of the mobile edge
  459. //
  460. GetWindowRect(m_rectBorder);
  461. m_rectBorder = CRect(0, 0, m_rectBorder.Width(), m_rectBorder.Height());
  462. DWORD dwBorderStyle = m_dwStyle | CBRS_BORDER_ANY;
  463. switch(m_nDockBarID)
  464. {
  465. case AFX_IDW_DOCKBAR_TOP:
  466. dwBorderStyle &= ~CBRS_BORDER_BOTTOM;
  467. lpncsp->rgrc[0].left += m_cxGripper;
  468. lpncsp->rgrc[0].bottom += -m_cxEdge;
  469. lpncsp->rgrc[0].top += m_cxBorder;
  470. lpncsp->rgrc[0].right += -m_cxBorder;
  471. m_rectBorder.top = m_rectBorder.bottom - m_cxEdge;
  472. break;
  473. case AFX_IDW_DOCKBAR_BOTTOM:
  474. dwBorderStyle &= ~CBRS_BORDER_TOP;
  475. lpncsp->rgrc[0].left += m_cxGripper;
  476. lpncsp->rgrc[0].top += m_cxEdge;
  477. lpncsp->rgrc[0].bottom += -m_cxBorder;
  478. lpncsp->rgrc[0].right += -m_cxBorder;
  479. m_rectBorder.bottom = m_rectBorder.top + m_cxEdge;
  480. break;
  481. case AFX_IDW_DOCKBAR_LEFT:
  482. dwBorderStyle &= ~CBRS_BORDER_RIGHT;
  483. lpncsp->rgrc[0].right += -m_cxEdge;
  484. lpncsp->rgrc[0].left += m_cxBorder;
  485. lpncsp->rgrc[0].bottom += -m_cxBorder;
  486. lpncsp->rgrc[0].top += m_cxGripper;
  487. m_rectBorder.left = m_rectBorder.right - m_cxEdge;
  488. break;
  489. case AFX_IDW_DOCKBAR_RIGHT:
  490. dwBorderStyle &= ~CBRS_BORDER_LEFT;
  491. lpncsp->rgrc[0].left += m_cxEdge;
  492. lpncsp->rgrc[0].right += -m_cxBorder;
  493. lpncsp->rgrc[0].bottom += -m_cxBorder;
  494. lpncsp->rgrc[0].top += m_cxGripper;
  495. m_rectBorder.right = m_rectBorder.left + m_cxEdge;
  496. break;
  497. default:
  498. m_rectBorder.SetRectEmpty();
  499. break;
  500. }
  501. SetBarStyle(dwBorderStyle);
  502. }
  503. void CDockDialogBar::OnNcPaint()
  504. {
  505. EraseNonClient();
  506. CWindowDC dc(this);
  507. dc.Draw3dRect(m_rectBorder, GetSysColor(COLOR_BTNHIGHLIGHT),
  508. GetSysColor(COLOR_BTNSHADOW));
  509. DrawGripper(dc);
  510. CRect pRect;
  511. GetClientRect( &pRect );
  512. InvalidateRect( &pRect, TRUE );
  513. }
  514. void CDockDialogBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
  515. {
  516. if (m_bTracking) return;
  517. if((nHitTest == HTSYSMENU) && !IsFloating())
  518. GetDockingFrame()->ShowControlBar(this, FALSE, FALSE);
  519. else if ((nHitTest == HTMINBUTTON) && !IsFloating())
  520. m_pDockContext->ToggleDocking();
  521. else if ((nHitTest == HTCAPTION) && !IsFloating() && (m_pDockBar != NULL))
  522. {
  523. // start the drag
  524. ASSERT(m_pDockContext != NULL);
  525. m_pDockContext->StartDrag(point);
  526. }
  527. else if ((nHitTest == HTSIZE) && !IsFloating()) {
  528. m_bKeepSize = TRUE;
  529. StartTracking();
  530. } else {
  531. CControlBar::OnNcLButtonDown(nHitTest, point);
  532. }
  533. }
  534. UINT CDockDialogBar::OnNcHitTest(CPoint point)
  535. {
  536. if (IsFloating())
  537. return CControlBar::OnNcHitTest(point);
  538. CRect rc;
  539. GetWindowRect(rc);
  540. point.Offset(-rc.left, -rc.top);
  541. if(m_rectClose.PtInRect(point))
  542. return HTSYSMENU;
  543. else if (m_rectUndock.PtInRect(point))
  544. return HTMINBUTTON;
  545. else if (m_rectGripper.PtInRect(point))
  546. return HTCAPTION;
  547. else if (m_rectBorder.PtInRect(point))
  548. return HTSIZE;
  549. else
  550. return CControlBar::OnNcHitTest(point);
  551. }
  552. void CDockDialogBar::OnLButtonDown(UINT nFlags, CPoint point)
  553. {
  554. //
  555. // only start dragging if clicked in "void" space
  556. //
  557. if (m_pDockBar != NULL)
  558. {
  559. //
  560. // start the drag
  561. //
  562. ASSERT(m_pDockContext != NULL);
  563. ClientToScreen(&point);
  564. m_pDockContext->StartDrag(point);
  565. }
  566. else
  567. {
  568. CWnd::OnLButtonDown(nFlags, point);
  569. }
  570. }
  571. void CDockDialogBar::OnLButtonDblClk(UINT nFlags, CPoint point)
  572. {
  573. //
  574. // only toggle docking if clicked in "void" space
  575. //
  576. if (m_pDockBar != NULL)
  577. {
  578. //
  579. // toggle docking
  580. //
  581. ASSERT(m_pDockContext != NULL);
  582. m_pDockContext->ToggleDocking();
  583. }
  584. else
  585. {
  586. CWnd::OnLButtonDblClk(nFlags, point);
  587. }
  588. }
  589. void CDockDialogBar::StartTracking()
  590. {
  591. SetCapture();
  592. //
  593. // make sure no updates are pending
  594. //
  595. RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
  596. m_pDockSite->LockWindowUpdate();
  597. m_ptOld = m_rectBorder.CenterPoint();
  598. m_bTracking = TRUE;
  599. m_rectTracker = m_rectBorder;
  600. if (!IsHorz()) m_rectTracker.bottom -= 4;
  601. OnInvertTracker(m_rectTracker);
  602. }
  603. void CDockDialogBar::OnCaptureChanged(CWnd *pWnd)
  604. {
  605. if (m_bTracking && pWnd != this)
  606. //
  607. // cancel tracking
  608. //
  609. StopTracking(FALSE);
  610. CControlBar::OnCaptureChanged(pWnd);
  611. }
  612. void CDockDialogBar::StopTracking(BOOL bAccept)
  613. {
  614. CDockDialogBar *pBar;
  615. CDockBar *pDockBar;
  616. LONG beforeIndex;
  617. LONG afterIndex;
  618. LONG ii;
  619. BOOL bFound = FALSE;
  620. OnInvertTracker(m_rectTracker);
  621. m_pDockSite->UnlockWindowUpdate();
  622. m_bTracking = FALSE;
  623. ReleaseCapture();
  624. if (!bAccept) return;
  625. int maxsize, minsize, newsize;
  626. CRect rcc;
  627. m_pDockSite->GetWindowRect(rcc);
  628. newsize = IsHorz() ? m_sizeHorz.cy : m_sizeVert.cx;
  629. maxsize = newsize + (IsHorz() ? rcc.Height() : rcc.Width());
  630. minsize = IsHorz() ? m_sizeMin.cy : m_sizeMin.cx;
  631. CPoint point = m_rectTracker.CenterPoint();
  632. switch (m_nDockBarID)
  633. {
  634. case AFX_IDW_DOCKBAR_TOP:
  635. newsize += point.y - m_ptOld.y; break;
  636. case AFX_IDW_DOCKBAR_BOTTOM:
  637. newsize += -point.y + m_ptOld.y; break;
  638. case AFX_IDW_DOCKBAR_LEFT:
  639. newsize += point.x - m_ptOld.x; break;
  640. case AFX_IDW_DOCKBAR_RIGHT:
  641. newsize += -point.x + m_ptOld.x; break;
  642. }
  643. pDockBar = (CDockBar *)m_pDockSite->GetControlBar(AFX_IDW_DOCKBAR_TOP);
  644. //
  645. // Mark all bars to keep their size
  646. //
  647. for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
  648. pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
  649. if(pBar == NULL) {
  650. continue;
  651. }
  652. if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
  653. //
  654. // Mark all bars to keep their size for now
  655. //
  656. pBar->m_bKeepSize = TRUE;
  657. }
  658. }
  659. //
  660. // Have all windows keep there size except those directly next
  661. // to the window changing size if possible. Normally only the
  662. // window below, or after, the window changing size will need
  663. // to change size as well, unless the user attempted to resize
  664. // the window to smaller than its minimum. Then both the window
  665. // above and below will need to change size.
  666. //
  667. for(ii = 0; ii < pDockBar->m_arrBars.GetSize(); ii++) {
  668. pBar = (CDockDialogBar *)pDockBar->m_arrBars[ii];
  669. if(pBar == NULL) {
  670. continue;
  671. }
  672. if(pBar->IsKindOf(RUNTIME_CLASS(CDockDialogBar))) {
  673. //
  674. // Mark all bars to keep their size for now
  675. //
  676. pBar->m_bKeepSize = TRUE;
  677. if(pBar == this) {
  678. bFound = TRUE;
  679. continue;
  680. }
  681. if(bFound) {
  682. afterIndex = ii;
  683. break;
  684. }
  685. if(!bFound) {
  686. beforeIndex = ii;
  687. }
  688. }
  689. }
  690. //
  691. // The window below, or after the one being modified will
  692. // alway need to change size
  693. //
  694. pBar = (CDockDialogBar *)pDockBar->m_arrBars[afterIndex];
  695. pBar->m_bKeepSize = FALSE;
  696. //
  697. // If the modified window is being shrunk past its minimum
  698. // then the window above, or before this one needs to change
  699. // as well
  700. //
  701. if(newsize < minsize) {
  702. pBar = (CDockDialogBar *)pDockBar->m_arrBars[beforeIndex];
  703. pBar->m_bKeepSize = FALSE;
  704. }
  705. newsize = max(minsize, min(maxsize, newsize));
  706. if (IsHorz())
  707. m_sizeHorz.cy = newsize;
  708. else
  709. m_sizeVert.cx = newsize;
  710. m_pDockSite->RecalcLayout();
  711. }
  712. void CDockDialogBar::OnInvertTracker(const CRect& rect)
  713. {
  714. ASSERT_VALID(this);
  715. ASSERT(!rect.IsRectEmpty());
  716. ASSERT(m_bTracking);
  717. CRect rct = rect, rcc, rcf;
  718. GetWindowRect(rcc);
  719. m_pDockSite->GetWindowRect(rcf);
  720. rct.OffsetRect(rcc.left - rcf.left, rcc.top - rcf.top);
  721. rct.DeflateRect(1, 1);
  722. CDC *pDC = m_pDockSite->GetDCEx(NULL,
  723. DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  724. CBrush* pBrush = CDC::GetHalftoneBrush();
  725. HBRUSH hOldBrush = NULL;
  726. if (pBrush != NULL)
  727. hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);
  728. pDC->PatBlt(rct.left, rct.top, rct.Width(), rct.Height(), PATINVERT);
  729. if (hOldBrush != NULL)
  730. SelectObject(pDC->m_hDC, hOldBrush);
  731. m_pDockSite->ReleaseDC(pDC);
  732. }
  733. BOOL CDockDialogBar::IsHorz() const
  734. {
  735. return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
  736. m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
  737. }
  738. CPoint& CDockDialogBar::ClientToWnd(CPoint& point)
  739. {
  740. if (m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM)
  741. point.y += m_cxEdge;
  742. else if (m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT)
  743. point.x += m_cxEdge;
  744. return point;
  745. }
  746. void CDockDialogBar::DrawGripper(CDC & dc)
  747. {
  748. CString groupNumber;
  749. //
  750. // no gripper if floating
  751. //
  752. if( m_dwStyle & CBRS_FLOATING ) {
  753. return;
  754. }
  755. m_pDockSite->RecalcLayout();
  756. CRect gripper;
  757. GetWindowRect( gripper );
  758. ScreenToClient( gripper );
  759. gripper.OffsetRect( -gripper.left, -gripper.top );
  760. if( m_dwStyle & CBRS_ORIENT_HORZ ) {
  761. //
  762. // gripper at left
  763. //
  764. m_rectGripper.top = gripper.top;
  765. m_rectGripper.bottom = gripper.bottom;
  766. m_rectGripper.left = gripper.left;
  767. m_rectGripper.right = gripper.left + 15;
  768. gripper.top += 10;
  769. gripper.bottom -= 10;
  770. gripper.left += 5;
  771. gripper.right = gripper.left + 3;
  772. //
  773. // Draw first bar
  774. //
  775. dc.Draw3dRect(gripper, m_clrBtnHilight, m_clrBtnShadow);
  776. gripper.OffsetRect(4, 0);
  777. //
  778. // Draw second bar
  779. //
  780. dc.Draw3dRect(gripper, m_clrBtnHilight, m_clrBtnShadow);
  781. //
  782. // Display title if requested
  783. //
  784. if(m_bShowTitleInGripper) {
  785. gripper.OffsetRect(8, 0);
  786. gripper.DeflateRect(-4, 0);
  787. dc.SelectStockObject(SYSTEM_FONT);
  788. dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
  789. dc.SetTextColor(GetSysColor(COLOR_3DSHADOW));
  790. //
  791. // Gripper title format -- ID #
  792. //
  793. dc.DrawText('I', gripper, DT_CENTER);
  794. gripper.OffsetRect(0, 8);
  795. gripper.DeflateRect(0, 8);
  796. dc.DrawText('D', gripper, DT_CENTER);
  797. gripper.OffsetRect(0, 8);
  798. gripper.DeflateRect(0, 8);
  799. dc.DrawText(' ', gripper, DT_CENTER);
  800. gripper.OffsetRect(0, 4);
  801. gripper.DeflateRect(0, 4);
  802. groupNumber = m_pTitle.Right(m_pTitle.GetLength() - m_pTitle.ReverseFind(' ') - 1);
  803. for(int ii = 0; ii < groupNumber.GetLength(); ii++) {
  804. dc.DrawText(groupNumber[ii], gripper, DT_CENTER);
  805. gripper.OffsetRect(0, 8);
  806. gripper.DeflateRect(0, 8);
  807. }
  808. }
  809. }
  810. else {
  811. //
  812. // gripper at top
  813. //
  814. m_rectGripper.top = gripper.top;
  815. m_rectGripper.bottom = gripper.top + 20;
  816. m_rectGripper.left = gripper.left;
  817. m_rectGripper.right = gripper.right - 10;
  818. gripper.right -= 38;
  819. gripper.left += 5;
  820. gripper.top += 10;
  821. gripper.bottom = gripper.top + 3;
  822. dc.Draw3dRect( gripper, RGB(0, 255, 0), RGB(0, 255, 255));
  823. gripper.OffsetRect(0, 4);
  824. dc.Draw3dRect( gripper, RGB(255, 255, 0), RGB(255, 0, 0));
  825. }
  826. }
  827. void CDockDialogBar::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
  828. {
  829. if ((m_pDockBar != NULL) && (nHitTest == HTCAPTION))
  830. {
  831. //
  832. // toggle docking
  833. //
  834. ASSERT(m_pDockContext != NULL);
  835. m_pDockContext->ToggleDocking();
  836. }
  837. else
  838. {
  839. CWnd::OnNcLButtonDblClk(nHitTest, point);
  840. }
  841. }