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.

395 lines
8.8 KiB

  1. #include "precomp.h"
  2. #include "splitbar2.h"
  3. #include "resource.h"
  4. /* static */ int CSplitBar2::ms_dxpSplitBar = 0; // width of a standard split bar window // GetSystemMetrics(SM_CXSIZEFRAME);
  5. /* static */ void CSplitBar2::_UpdateSplitBar(void)
  6. {
  7. ms_dxpSplitBar = GetSystemMetrics(SM_CXSIZEFRAME);
  8. }
  9. /* C S P L I T B A R */
  10. /*-------------------------------------------------------------------------
  11. %%Function: CSplitBar2
  12. -------------------------------------------------------------------------*/
  13. CSplitBar2::CSplitBar2(void)
  14. : m_hwndBuddy (NULL)
  15. , m_hwndParent(NULL)
  16. , m_pfnAdjust(NULL)
  17. , m_Context(NULL)
  18. , m_hdcDrag(NULL)
  19. , m_fCaptured(FALSE)
  20. {
  21. DBGENTRY(CSplitBar2::CSplitBar2);
  22. _UpdateSplitBar();
  23. DBGEXIT(CSplitBar2::CSplitBar2);
  24. }
  25. CSplitBar2::~CSplitBar2()
  26. {
  27. DBGENTRY(CSplitBar2::~CSplitBar2);
  28. if( ::IsWindow( m_hWnd ) )
  29. {
  30. DestroyWindow();
  31. }
  32. DBGEXIT(CSplitBar2::~CSplitBar2);
  33. }
  34. HRESULT CSplitBar2::Create(HWND hwndBuddy, PFN_ADJUST pfnAdjust, LPARAM Context)
  35. {
  36. DBGENTRY(CSplitBar2::Create);
  37. HRESULT hr = S_OK;
  38. if( hwndBuddy && pfnAdjust )
  39. {
  40. m_hwndBuddy = hwndBuddy;
  41. m_hwndParent = ::GetParent(hwndBuddy);
  42. m_pfnAdjust = pfnAdjust;
  43. m_Context = Context;
  44. RECT rc;
  45. SetRect( &rc, 0, 0, ms_dxpSplitBar, 0 );
  46. if( !CWindowImpl<CSplitBar2>::Create( m_hwndParent, rc ) )
  47. {
  48. hr = HRESULT_FROM_WIN32(GetLastError());
  49. }
  50. }
  51. else
  52. {
  53. hr = E_INVALIDARG;
  54. }
  55. DBGEXIT_HR(CSplitBar2::Create,hr);
  56. return hr;
  57. }
  58. LRESULT CSplitBar2::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  59. {
  60. DBGENTRY(CSplitBar2::OnLButtonDown);
  61. POINT pt;
  62. pt.x = LOWORD(lParam);
  63. pt.y = HIWORD(lParam);
  64. _TrackDrag(pt);
  65. DBGEXIT(CSplitBar2::OnLButtonDown);
  66. return 0;
  67. }
  68. /* C O N S T R A I N D R A G P O I N T */
  69. /*-------------------------------------------------------------------------
  70. %%Function: _ConstrainDragPoint
  71. -------------------------------------------------------------------------*/
  72. int CSplitBar2::_ConstrainDragPoint(short x)
  73. {
  74. DBGENTRY(CSplitBar2::_ConstrainDragPoint);
  75. // Factor out the drag offset (to make calculations easier)
  76. int dx = x - m_dxDragOffset;
  77. // Don't allow the panes to go below their minimum size
  78. if (dx < m_dxMin)
  79. {
  80. dx = m_dxMin;
  81. }
  82. else if (dx > m_dxMax)
  83. {
  84. dx = m_dxMax;
  85. }
  86. DBGEXIT(CSplitBar2::_ConstrainDragPoint);
  87. // Factor the drag offset back in
  88. return (m_dxDragOffset + dx);
  89. }
  90. /* D R A W B A R */
  91. /*-------------------------------------------------------------------------
  92. %%Function: _DrawBar
  93. -------------------------------------------------------------------------*/
  94. void CSplitBar2::_DrawBar(void)
  95. {
  96. DBGENTRY(CSplitBar2::_DrawBar);
  97. RECT rc;
  98. RECT ClientRect;
  99. GetClientRect( &ClientRect );
  100. // Rectangle is a larger to make it easier to see.
  101. rc.top = ClientRect.top;
  102. rc.bottom = ClientRect.bottom;
  103. rc.left = m_xCurr - (m_dxDragOffset + 1); //ClientRect.left +
  104. rc.right = rc.left + ms_dxpSplitBar + 1;
  105. ::MapWindowPoints(m_hwndParent, GetDesktopWindow(), (POINT *) &rc, 2);
  106. ::InvertRect(m_hdcDrag, &rc);
  107. DBGEXIT(CSplitBar2::_DrawBar);
  108. }
  109. /* F I N I T D R A G L O O P */
  110. /*-------------------------------------------------------------------------
  111. %%Function: FInitDragLoop
  112. Initialize the mouse down drag loop.
  113. Return FALSE if there was a problem.
  114. -------------------------------------------------------------------------*/
  115. BOOL CSplitBar2::FInitDragLoop(POINT pt)
  116. {
  117. DBGENTRY(CSplitBar2::FInitDragLoop);
  118. if (NULL != ::GetCapture())
  119. {
  120. ERROR_OUT(("InitDragLoop: Unable to capture"));
  121. return FALSE;
  122. }
  123. // handle pending WM_PAINT messages
  124. MSG msg;
  125. while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  126. {
  127. if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  128. return FALSE;
  129. DispatchMessage(&msg);
  130. }
  131. HWND hwndDesktop = GetDesktopWindow();
  132. DWORD dwFlags = ::LockWindowUpdate(hwndDesktop) ? DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE : DCX_WINDOW|DCX_CACHE;
  133. ASSERT(m_hdcDrag == NULL);
  134. m_hdcDrag = ::GetDCEx(hwndDesktop, NULL, dwFlags);
  135. ASSERT(m_hdcDrag != NULL);
  136. ASSERT(!m_fCaptured);
  137. SetCapture();
  138. ASSERT(m_hWnd == GetCapture());
  139. m_fCaptured = TRUE;
  140. m_dxDragOffset = pt.x;
  141. m_xCurr = pt.x;
  142. _DrawBar();
  143. RECT rc;
  144. // determine the drag extent
  145. ::GetClientRect(m_hwndBuddy, &rc);
  146. ::MapWindowPoints(m_hwndBuddy, m_hwndParent, (POINT *) &rc, 1);
  147. m_dxMin = rc.left + (32 + (3*2));
  148. ::GetClientRect( ::GetParent( m_hwndParent ) , &rc);
  149. m_dxMax = RectWidth(rc) - (ms_dxpSplitBar + 176);
  150. if (m_dxMax < m_dxMin)
  151. m_dxMax = m_dxMin;
  152. TRACE_OUT(("captured mouse at (%d,%d) (min=%d, max=%d)", pt.x, pt.y, m_dxMin, m_dxMax));
  153. DBGEXIT(CSplitBar2::FInitDragLoop);
  154. return TRUE;
  155. }
  156. /* O N D R A G M O V E */
  157. /*-------------------------------------------------------------------------
  158. %%Function: OnDragMove
  159. -------------------------------------------------------------------------*/
  160. void CSplitBar2::OnDragMove(POINT pt)
  161. {
  162. DBGENTRY(CSplitBar2::OnDragMove);
  163. ASSERT(m_fCaptured);
  164. ::ScreenToClient(m_hwndParent, &pt);
  165. int x = _ConstrainDragPoint((short)pt.x);
  166. if (x != m_xCurr)
  167. {
  168. _DrawBar();
  169. m_xCurr = x;
  170. _DrawBar();
  171. }
  172. DBGEXIT(CSplitBar2::OnDragMove);
  173. }
  174. /* O N D R A G E N D */
  175. /*-------------------------------------------------------------------------
  176. %%Function: OnDragEnd
  177. -------------------------------------------------------------------------*/
  178. void CSplitBar2::OnDragEnd(POINT pt)
  179. {
  180. DBGENTRY(CSplitBar2::OnDragEnd);
  181. CancelDragLoop();
  182. RECT ClientRect;
  183. GetClientRect( &ClientRect );
  184. ::ScreenToClient(m_hwndParent, &pt);
  185. int x = _ConstrainDragPoint((short)pt.x);
  186. if (0 != x)
  187. {
  188. // Call the adjustment function
  189. if(m_pfnAdjust)
  190. {
  191. m_pfnAdjust(x - (ClientRect.left + m_dxDragOffset), m_Context);
  192. }
  193. // ForceWindowResize();
  194. }
  195. DBGEXIT(CSplitBar2::OnDragEnd);
  196. }
  197. /* C A N C E L D R A G L O O P */
  198. /*-------------------------------------------------------------------------
  199. %%Function: CancelDragLoop
  200. -------------------------------------------------------------------------*/
  201. void CSplitBar2::CancelDragLoop(void)
  202. {
  203. DBGENTRY(CSplitBar2::CancelDragLoop);
  204. if (m_fCaptured)
  205. {
  206. TRACE_OUT(("Canceling drag loop..."));
  207. // Release the capture
  208. ReleaseCapture();
  209. m_fCaptured = FALSE;
  210. // Erase the bar
  211. _DrawBar();
  212. // unlock window updates
  213. LockWindowUpdate(NULL);
  214. if (m_hdcDrag != NULL)
  215. {
  216. ::ReleaseDC(GetDesktopWindow(), m_hdcDrag);
  217. m_hdcDrag = NULL;
  218. }
  219. }
  220. DBGEXIT(CSplitBar2::CancelDragLoop);
  221. }
  222. void CSplitBar2::_TrackDrag(POINT pt)
  223. {
  224. DBGENTRY(CSplitBar2::_TrackDrag);
  225. // set capture to the window which received this message
  226. if (FInitDragLoop(pt))
  227. {
  228. // get messages until capture lost or cancelled/accepted
  229. while (GetCapture() == m_hWnd)
  230. {
  231. MSG msg;
  232. if (!::GetMessage(&msg, NULL, 0, 0))
  233. {
  234. PostQuitMessage(msg.wParam);
  235. break;
  236. }
  237. if (WM_MOUSEMOVE == msg.message)
  238. {
  239. OnDragMove(msg.pt);
  240. continue;
  241. }
  242. if (WM_LBUTTONUP == msg.message)
  243. {
  244. OnDragEnd(msg.pt);
  245. break;
  246. }
  247. if ((WM_KEYDOWN == msg.message) ||
  248. (WM_RBUTTONDOWN == msg.message))
  249. {
  250. break;
  251. }
  252. // dispatch all other messages
  253. DispatchMessage(&msg);
  254. }
  255. CancelDragLoop();
  256. }
  257. else
  258. {
  259. WARNING_OUT(("Unable to Initialize drag loop?"));
  260. }
  261. DBGEXIT(CSplitBar2::_TrackDrag);
  262. }
  263. /* static */ CWndClassInfo& CSplitBar2::GetWndClassInfo()
  264. {
  265. DBGENTRY(CSplitBar2::GetWndClassInfo);
  266. static CWndClassInfo wc =
  267. {
  268. {
  269. sizeof(WNDCLASSEX), // cbSize
  270. NULL, // style
  271. StartWindowProc, // WndProc
  272. 0, // cbClsExtra
  273. 0, // cbWndExtra
  274. 0, // hInstance
  275. 0, // hIcon
  276. NULL, // hCursor
  277. reinterpret_cast<HBRUSH>(COLOR_3DFACE + 1), // hBackground
  278. 0, // lpszMenuName
  279. _T("ConfSplitBarClass2"), // lpszClassName
  280. 0 // hIconSm
  281. },
  282. NULL,
  283. NULL,
  284. MAKEINTRESOURCE(IDC_SPLITV), // hCursor,
  285. FALSE,
  286. 0,
  287. _T("")
  288. };
  289. DBGEXIT(CSplitBar2::GetWndClassInfo);
  290. return wc;
  291. }