dockcont.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_CORE3_SEG
  12. #pragma code_seg(AFX_CORE3_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. #define HORZF(dw) (dw & CBRS_ORIENT_HORZ)
  20. #define VERTF(dw) (dw & CBRS_ORIENT_VERT)
  21. AFX_STATIC void AFXAPI _AfxAdjustRectangle(CRect& rect, CPoint pt)
  22. {
  23. int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
  24. (pt.x > rect.right) ? (pt.x - rect.right) : 0;
  25. int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
  26. (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
  27. rect.OffsetRect(nXOffset, nYOffset);
  28. }
  29. /////////////////////////////////////////////////////////////////////////////
  30. // CDockContext
  31. CDockContext::CDockContext(CControlBar* pBar)
  32. {
  33. ASSERT(pBar != NULL);
  34. ASSERT(pBar->m_pDockSite != NULL);
  35. m_pBar = pBar;
  36. m_pDockSite = pBar->m_pDockSite;
  37. m_uMRUDockID = 0;
  38. m_rectMRUDockPos.left = 0;
  39. m_rectMRUDockPos.top = 0;
  40. if (pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
  41. m_dwMRUFloatStyle = pBar->m_dwStyle & (CBRS_ALIGN_TOP | CBRS_SIZE_DYNAMIC);
  42. else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ)
  43. m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (pBar->m_dwStyle & CBRS_FLOAT_MULTI);
  44. else
  45. m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (pBar->m_dwStyle & CBRS_FLOAT_MULTI);
  46. m_ptMRUFloatPos.x = CW_USEDEFAULT;
  47. ASSERT(m_pDockSite->IsFrameWnd());
  48. m_pDC = NULL;
  49. }
  50. CDockContext::~CDockContext()
  51. {
  52. ASSERT(m_pBar != NULL);
  53. if (m_pBar->m_pDockBar != NULL)
  54. m_pBar->m_pDockBar->RemoveControlBar(m_pBar, -1, FALSE);
  55. }
  56. /////////////////////////////////////////////////////////////////////////////
  57. // CDockContext Drag Operations
  58. void CDockContext::StartDrag(CPoint pt)
  59. {
  60. ASSERT_VALID(m_pBar);
  61. m_bDragging = TRUE;
  62. InitLoop();
  63. // GetWindowRect returns screen coordinates(not mirrored),
  64. // so if the desktop is mirrored then turn off mirroring
  65. // for the desktop dc so that we get correct focus rect drawn.
  66. // This layout change should be remembered, just in case ...
  67. if (m_pDC->GetLayout() & LAYOUT_RTL)
  68. m_pDC->SetLayout(LAYOUT_LTR);
  69. if (m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
  70. {
  71. // get true bar size (including borders)
  72. CRect rect;
  73. m_pBar->GetWindowRect(rect);
  74. m_ptLast = pt;
  75. CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK);
  76. CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK);
  77. CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
  78. m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
  79. m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
  80. // calculate frame dragging rectangle
  81. m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat);
  82. m_rectFrameDragVert = CRect(rect.TopLeft(), sizeFloat);
  83. CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  84. CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  85. m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  86. m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  87. }
  88. else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED)
  89. {
  90. // get true bar size (including borders)
  91. CRect rect;
  92. m_pBar->GetWindowRect(rect);
  93. m_ptLast = pt;
  94. CSize sizeHorz = m_pBar->CalcDynamicLayout(-1, LM_HORZ | LM_HORZDOCK);
  95. CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK);
  96. // calculate frame dragging rectangle
  97. m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
  98. m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
  99. CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  100. CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  101. m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  102. m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  103. }
  104. else
  105. {
  106. // get true bar size (including borders)
  107. CRect rect;
  108. m_pBar->GetWindowRect(rect);
  109. m_ptLast = pt;
  110. BOOL bHorz = HORZF(m_dwStyle);
  111. DWORD dwMode = !bHorz ? (LM_HORZ | LM_HORZDOCK) : LM_VERTDOCK;
  112. CSize size = m_pBar->CalcDynamicLayout(-1, dwMode);
  113. // calculate inverted dragging rect
  114. if (bHorz)
  115. {
  116. m_rectDragHorz = rect;
  117. m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size);
  118. }
  119. else // vertical orientation
  120. {
  121. m_rectDragVert = rect;
  122. m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size);
  123. }
  124. // calculate frame dragging rectangle
  125. m_rectFrameDragHorz = m_rectDragHorz;
  126. m_rectFrameDragVert = m_rectDragVert;
  127. CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
  128. CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
  129. m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  130. m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  131. }
  132. // adjust rectangles so that point is inside
  133. _AfxAdjustRectangle(m_rectDragHorz, pt);
  134. _AfxAdjustRectangle(m_rectDragVert, pt);
  135. _AfxAdjustRectangle(m_rectFrameDragHorz, pt);
  136. _AfxAdjustRectangle(m_rectFrameDragVert, pt);
  137. // initialize tracking state and enter tracking loop
  138. m_dwOverDockStyle = CanDock();
  139. Move(pt); // call it here to handle special keys
  140. Track();
  141. }
  142. void CDockContext::Move(CPoint pt)
  143. {
  144. CPoint ptOffset = pt - m_ptLast;
  145. // offset all drag rects to new position
  146. m_rectDragHorz.OffsetRect(ptOffset);
  147. m_rectFrameDragHorz.OffsetRect(ptOffset);
  148. m_rectDragVert.OffsetRect(ptOffset);
  149. m_rectFrameDragVert.OffsetRect(ptOffset);
  150. m_ptLast = pt;
  151. // if control key is down don't dock
  152. m_dwOverDockStyle = m_bForceFrame ? 0 : CanDock();
  153. // update feedback
  154. DrawFocusRect();
  155. }
  156. void CDockContext::OnKey(int nChar, BOOL bDown)
  157. {
  158. if (nChar == VK_CONTROL)
  159. UpdateState(&m_bForceFrame, bDown);
  160. if (nChar == VK_SHIFT)
  161. UpdateState(&m_bFlip, bDown);
  162. }
  163. void CDockContext::EndDrag()
  164. {
  165. CancelLoop();
  166. if (m_dwOverDockStyle != 0)
  167. {
  168. CDockBar* pDockBar = GetDockBar(m_dwOverDockStyle);
  169. ASSERT(pDockBar != NULL);
  170. CRect rect = (m_dwOverDockStyle & CBRS_ORIENT_VERT) ?
  171. m_rectDragVert : m_rectDragHorz;
  172. UINT uID = _AfxGetDlgCtrlID(pDockBar->m_hWnd);
  173. if (uID >= AFX_IDW_DOCKBAR_TOP &&
  174. uID <= AFX_IDW_DOCKBAR_BOTTOM)
  175. {
  176. m_uMRUDockID = uID;
  177. m_rectMRUDockPos = rect;
  178. pDockBar->ScreenToClient(&m_rectMRUDockPos);
  179. }
  180. // dock it at the specified position, RecalcLayout will snap
  181. m_pDockSite->DockControlBar(m_pBar, pDockBar, &rect);
  182. m_pDockSite->RecalcLayout();
  183. }
  184. else if ((m_dwStyle & CBRS_SIZE_DYNAMIC) || (HORZF(m_dwStyle) && !m_bFlip) ||
  185. (VERTF(m_dwStyle) && m_bFlip))
  186. {
  187. m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI);
  188. m_ptMRUFloatPos = m_rectFrameDragHorz.TopLeft();
  189. m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
  190. }
  191. else // vertical float
  192. {
  193. m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (m_dwDockStyle & CBRS_FLOAT_MULTI);
  194. m_ptMRUFloatPos = m_rectFrameDragVert.TopLeft();
  195. m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
  196. }
  197. }
  198. /////////////////////////////////////////////////////////////////////////////
  199. // CDockContext Resize Operations
  200. #define m_rectRequestedSize m_rectDragHorz
  201. #define m_rectActualSize m_rectDragVert
  202. #define m_rectActualFrameSize m_rectFrameDragHorz
  203. #define m_rectFrameBorders m_rectFrameDragVert
  204. void CDockContext::StartResize(int nHitTest, CPoint pt)
  205. {
  206. ASSERT_VALID(m_pBar);
  207. ASSERT(m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC);
  208. m_bDragging = FALSE;
  209. InitLoop();
  210. // GetWindowRect returns screen coordinates(not mirrored)
  211. // So if the desktop is mirrored then turn off mirroring
  212. // for the desktop dc so that we draw correct focus rect
  213. if (m_pDC->GetLayout() & LAYOUT_RTL)
  214. m_pDC->SetLayout(LAYOUT_LTR);
  215. // get true bar size (including borders)
  216. CRect rect;
  217. m_pBar->GetWindowRect(rect);
  218. m_ptLast = pt;
  219. m_nHitTest = nHitTest;
  220. CSize size = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
  221. m_rectRequestedSize = CRect(rect.TopLeft(), size);
  222. m_rectActualSize = CRect(rect.TopLeft(), size);
  223. m_rectActualFrameSize = CRect(rect.TopLeft(), size);
  224. // calculate frame rectangle
  225. CMiniFrameWnd::CalcBorders(&m_rectActualFrameSize);
  226. m_rectActualFrameSize.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2);
  227. m_rectFrameBorders = CRect(CPoint(0,0),
  228. m_rectActualFrameSize.Size() - m_rectActualSize.Size());
  229. // initialize tracking state and enter tracking loop
  230. m_dwOverDockStyle = 0;
  231. Stretch(pt); // call it here to handle special keys
  232. Track();
  233. }
  234. void CDockContext::Stretch(CPoint pt)
  235. {
  236. CPoint ptOffset = pt - m_ptLast;
  237. // offset all drag rects to new position
  238. int nLength = 0;
  239. DWORD dwMode = LM_HORZ;
  240. if (m_nHitTest == HTLEFT || m_nHitTest == HTRIGHT)
  241. {
  242. if (m_nHitTest == HTLEFT)
  243. m_rectRequestedSize.left += ptOffset.x;
  244. else
  245. m_rectRequestedSize.right += ptOffset.x;
  246. nLength = m_rectRequestedSize.Width();
  247. }
  248. else
  249. {
  250. dwMode |= LM_LENGTHY;
  251. if (m_nHitTest == HTTOP)
  252. m_rectRequestedSize.top += ptOffset.y;
  253. else
  254. m_rectRequestedSize.bottom += ptOffset.y;
  255. nLength = m_rectRequestedSize.Height();
  256. }
  257. nLength = (nLength >= 0) ? nLength : 0;
  258. CSize size = m_pBar->CalcDynamicLayout(nLength, dwMode);
  259. CRect rectDesk;
  260. HWND hWndDesk = ::GetDesktopWindow();
  261. ::GetWindowRect(hWndDesk, &rectDesk);
  262. CRect rectTemp = m_rectActualFrameSize;
  263. if (m_nHitTest == HTLEFT || m_nHitTest == HTTOP)
  264. {
  265. rectTemp.left = rectTemp.right -
  266. (size.cx + m_rectFrameBorders.Width());
  267. rectTemp.top = rectTemp.bottom -
  268. (size.cy + m_rectFrameBorders.Height());
  269. CRect rect;
  270. if (rect.IntersectRect(rectDesk, rectTemp))
  271. {
  272. m_rectActualSize.left = m_rectActualSize.right - size.cx;
  273. m_rectActualSize.top = m_rectActualSize.bottom - size.cy;
  274. m_rectActualFrameSize.left = rectTemp.left;
  275. m_rectActualFrameSize.top = rectTemp.top;
  276. }
  277. }
  278. else
  279. {
  280. rectTemp.right = rectTemp.left +
  281. (size.cx + m_rectFrameBorders.Width());
  282. rectTemp.bottom = rectTemp.top +
  283. (size.cy + m_rectFrameBorders.Height());
  284. CRect rect;
  285. if (rect.IntersectRect(rectDesk, rectTemp))
  286. {
  287. m_rectActualSize.right = m_rectActualSize.left + size.cx;
  288. m_rectActualSize.bottom = m_rectActualSize.top + size.cy;
  289. m_rectActualFrameSize.right = rectTemp.right;
  290. m_rectActualFrameSize.bottom = rectTemp.bottom;
  291. }
  292. }
  293. m_ptLast = pt;
  294. // update feedback
  295. DrawFocusRect();
  296. }
  297. void CDockContext::EndResize()
  298. {
  299. CancelLoop();
  300. m_pBar->CalcDynamicLayout(m_rectActualSize.Width(), LM_HORZ | LM_COMMIT);
  301. m_pDockSite->FloatControlBar(m_pBar, m_rectActualFrameSize.TopLeft(),
  302. CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI) | CBRS_SIZE_DYNAMIC);
  303. }
  304. /////////////////////////////////////////////////////////////////////////////
  305. // CDockContext Double Click Operations
  306. void CDockContext::ToggleDocking()
  307. {
  308. if (m_pBar->IsFloating())
  309. {
  310. // Dock it only if is allowed to be docked
  311. if (m_pBar->m_dwDockStyle & CBRS_ALIGN_ANY)
  312. {
  313. ASSERT((m_uMRUDockID >= AFX_IDW_DOCKBAR_TOP &&
  314. m_uMRUDockID <= AFX_IDW_DOCKBAR_BOTTOM) ||
  315. m_uMRUDockID == 0);
  316. CRect rect = m_rectMRUDockPos;
  317. CDockBar* pDockBar = NULL;
  318. if (m_uMRUDockID != 0)
  319. {
  320. pDockBar = (CDockBar*)m_pDockSite->GetControlBar(m_uMRUDockID);
  321. pDockBar->ClientToScreen(&rect);
  322. }
  323. // dock it at the specified position, RecalcLayout will snap
  324. m_pDockSite->ReDockControlBar(m_pBar, pDockBar, &rect);
  325. m_pDockSite->RecalcLayout();
  326. }
  327. }
  328. else
  329. {
  330. CPoint ptFloat = m_ptMRUFloatPos;
  331. if (ptFloat.x < 0 || ptFloat.y < 0)
  332. {
  333. ptFloat = m_rectMRUDockPos.TopLeft();
  334. m_pBar->GetParent()->ClientToScreen(&ptFloat);
  335. }
  336. m_pDockSite->FloatControlBar(m_pBar, ptFloat, m_dwMRUFloatStyle);
  337. }
  338. }
  339. /////////////////////////////////////////////////////////////////////////////
  340. // CDockContext Operations
  341. void CDockContext::InitLoop()
  342. {
  343. // handle pending WM_PAINT messages
  344. MSG msg;
  345. while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  346. {
  347. if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  348. return;
  349. DispatchMessage(&msg);
  350. }
  351. // get styles from bar
  352. m_dwDockStyle = m_pBar->m_dwDockStyle;
  353. m_dwStyle = m_pBar->m_dwStyle & CBRS_ALIGN_ANY;
  354. ASSERT(m_dwStyle != 0);
  355. // initialize state
  356. m_rectLast.SetRectEmpty();
  357. m_sizeLast.cx = m_sizeLast.cy = 0;
  358. m_bForceFrame = m_bFlip = m_bDitherLast = FALSE;
  359. // lock window update while dragging
  360. ASSERT(m_pDC == NULL);
  361. CWnd* pWnd = CWnd::GetDesktopWindow();
  362. if (pWnd->LockWindowUpdate())
  363. m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
  364. else
  365. m_pDC = pWnd->GetDCEx(NULL, DCX_WINDOW|DCX_CACHE);
  366. ASSERT(m_pDC != NULL);
  367. }
  368. void CDockContext::CancelLoop()
  369. {
  370. DrawFocusRect(TRUE); // gets rid of focus rect
  371. ReleaseCapture();
  372. CWnd* pWnd = CWnd::GetDesktopWindow();
  373. pWnd->UnlockWindowUpdate();
  374. if (m_pDC != NULL)
  375. {
  376. pWnd->ReleaseDC(m_pDC);
  377. m_pDC = NULL;
  378. }
  379. }
  380. /////////////////////////////////////////////////////////////////////////////
  381. // Implementation
  382. void CDockContext::DrawFocusRect(BOOL bRemoveRect)
  383. {
  384. ASSERT(m_pDC != NULL);
  385. // default to thin frame
  386. CSize size(CX_BORDER, CY_BORDER);
  387. // determine new rect and size
  388. CRect rect;
  389. CBrush* pWhiteBrush = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
  390. CBrush* pDitherBrush = CDC::GetHalftoneBrush();
  391. CBrush* pBrush = pWhiteBrush;
  392. if (HORZF(m_dwOverDockStyle))
  393. rect = m_rectDragHorz;
  394. else if (VERTF(m_dwOverDockStyle))
  395. rect = m_rectDragVert;
  396. else
  397. {
  398. // use thick frame instead
  399. size.cx = GetSystemMetrics(SM_CXFRAME) - CX_BORDER;
  400. size.cy = GetSystemMetrics(SM_CYFRAME) - CY_BORDER;
  401. if ((HORZF(m_dwStyle) && !m_bFlip) || (VERTF(m_dwStyle) && m_bFlip))
  402. rect = m_rectFrameDragHorz;
  403. else
  404. rect = m_rectFrameDragVert;
  405. pBrush = pDitherBrush;
  406. }
  407. if (bRemoveRect)
  408. size.cx = size.cy = 0;
  409. if (afxData.bWin4 &&
  410. (HORZF(m_dwOverDockStyle) || VERTF(m_dwOverDockStyle)))
  411. {
  412. // looks better one pixel in (makes the bar look pushed down)
  413. rect.InflateRect(-CX_BORDER, -CY_BORDER);
  414. }
  415. // draw it and remember last size
  416. m_pDC->DrawDragRect(&rect, size, &m_rectLast, m_sizeLast,
  417. pBrush, m_bDitherLast ? pDitherBrush : pWhiteBrush);
  418. m_rectLast = rect;
  419. m_sizeLast = size;
  420. m_bDitherLast = (pBrush == pDitherBrush);
  421. }
  422. void CDockContext::UpdateState(BOOL* pFlag, BOOL bNewValue)
  423. {
  424. if (*pFlag != bNewValue)
  425. {
  426. *pFlag = bNewValue;
  427. m_bFlip = (HORZF(m_dwDockStyle) && VERTF(m_dwDockStyle) && m_bFlip); // shift key
  428. m_dwOverDockStyle = (m_bForceFrame) ? 0 : CanDock();
  429. DrawFocusRect();
  430. }
  431. }
  432. DWORD CDockContext::CanDock()
  433. {
  434. BOOL bStyleHorz;
  435. DWORD dwDock = 0; // Dock Canidate
  436. DWORD dwCurr = 0; // Current Orientation
  437. // let's check for something in our current orientation first
  438. // then if the shift key is not forcing our orientation then
  439. // check for horizontal or vertical orientations as long
  440. // as we are close enough
  441. ASSERT(m_dwStyle != 0);
  442. bStyleHorz = HORZF(m_dwStyle);
  443. bStyleHorz = m_bFlip ? !bStyleHorz : bStyleHorz;
  444. if (bStyleHorz && HORZF(m_dwDockStyle))
  445. dwDock = m_pDockSite->CanDock(m_rectDragHorz,
  446. m_dwDockStyle & ~CBRS_ORIENT_VERT);
  447. else if (VERTF(m_dwDockStyle))
  448. dwDock = m_pDockSite->CanDock(m_rectDragVert,
  449. m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  450. if (!m_bFlip)
  451. {
  452. if (dwDock == 0 && HORZF(m_dwDockStyle))
  453. {
  454. dwCurr = m_pDockSite->CanDock(m_rectDragVert,
  455. m_dwDockStyle & ~CBRS_ORIENT_VERT);
  456. dwDock = m_pDockSite->CanDock(m_rectDragHorz,
  457. m_dwDockStyle & ~CBRS_ORIENT_VERT);
  458. dwDock = (dwDock == dwCurr) ? dwDock : 0;
  459. }
  460. if (dwDock == 0 && VERTF(m_dwDockStyle))
  461. {
  462. dwCurr = m_pDockSite->CanDock(m_rectDragHorz,
  463. m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  464. dwDock = m_pDockSite->CanDock(m_rectDragVert,
  465. m_dwDockStyle & ~CBRS_ORIENT_HORZ);
  466. dwDock = (dwDock == dwCurr) ? dwDock : 0;
  467. }
  468. }
  469. return dwDock;
  470. }
  471. CDockBar* CDockContext::GetDockBar(DWORD dwOverDockStyle)
  472. {
  473. DWORD dw = 0;
  474. CDockBar* pBar;
  475. if (HORZF(dwOverDockStyle))
  476. {
  477. dw = m_pDockSite->CanDock(m_rectDragHorz,
  478. dwOverDockStyle & ~CBRS_ORIENT_VERT, &pBar);
  479. ASSERT(dw != 0);
  480. ASSERT(pBar != NULL);
  481. return pBar;
  482. }
  483. if (VERTF(dwOverDockStyle))
  484. {
  485. dw = m_pDockSite->CanDock(m_rectDragVert,
  486. dwOverDockStyle & ~CBRS_ORIENT_HORZ, &pBar);
  487. ASSERT(dw != 0);
  488. ASSERT(pBar != NULL);
  489. return pBar;
  490. }
  491. return NULL;
  492. }
  493. BOOL CDockContext::Track()
  494. {
  495. // don't handle if capture already set
  496. if (::GetCapture() != NULL)
  497. return FALSE;
  498. // set capture to the window which received this message
  499. m_pBar->SetCapture();
  500. ASSERT(m_pBar == CWnd::GetCapture());
  501. // get messages until capture lost or cancelled/accepted
  502. while (CWnd::GetCapture() == m_pBar)
  503. {
  504. MSG msg;
  505. if (!::GetMessage(&msg, NULL, 0, 0))
  506. {
  507. AfxPostQuitMessage(msg.wParam);
  508. break;
  509. }
  510. switch (msg.message)
  511. {
  512. case WM_LBUTTONUP:
  513. if (m_bDragging)
  514. EndDrag();
  515. else
  516. EndResize();
  517. return TRUE;
  518. case WM_MOUSEMOVE:
  519. if (m_bDragging)
  520. Move(msg.pt);
  521. else
  522. Stretch(msg.pt);
  523. break;
  524. case WM_KEYUP:
  525. if (m_bDragging)
  526. OnKey((int)msg.wParam, FALSE);
  527. break;
  528. case WM_KEYDOWN:
  529. if (m_bDragging)
  530. OnKey((int)msg.wParam, TRUE);
  531. if (msg.wParam == VK_ESCAPE)
  532. {
  533. CancelLoop();
  534. return FALSE;
  535. }
  536. break;
  537. case WM_RBUTTONDOWN:
  538. CancelLoop();
  539. return FALSE;
  540. // just dispatch rest of the messages
  541. default:
  542. DispatchMessage(&msg);
  543. break;
  544. }
  545. }
  546. CancelLoop();
  547. return FALSE;
  548. }
  549. /////////////////////////////////////////////////////////////////////////////