ctltrack.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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 AFXCTL_CORE2_SEG
  12. #pragma code_seg(AFXCTL_CORE2_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. AFX_STATIC_DATA const int _afxResizeStyle =
  20. CRectTracker::resizeInside | CRectTracker::resizeOutside;
  21. AFX_STATIC void AFXAPI _AfxOffsetTrackerRect(CRect& rect, CWnd* pWnd)
  22. {
  23. DWORD dwStyle = pWnd->GetStyle();
  24. DWORD dwExStyle = pWnd->GetExStyle();
  25. int nBorders = ((dwStyle & WS_BORDER) != 0) +
  26. ((dwExStyle & WS_EX_CLIENTEDGE) != 0) * 2;
  27. int dx = -nBorders * GetSystemMetrics(SM_CXBORDER);
  28. int dy = -nBorders * GetSystemMetrics(SM_CYBORDER);
  29. if (dwExStyle & WS_EX_LEFTSCROLLBAR)
  30. dx -= GetSystemMetrics(SM_CXVSCROLL);
  31. rect.OffsetRect(dx - rect.left, dy - rect.top);
  32. }
  33. /////////////////////////////////////////////////////////////////////////////
  34. // COleControl::CreateTracker - Creates tracker for UIActive control
  35. void COleControl::CreateTracker(BOOL bHandles, BOOL bHatching)
  36. {
  37. CreateTracker(bHandles, bHatching, NULL);
  38. }
  39. void COleControl::CreateTracker(BOOL bHandles, BOOL bHatching, LPCRECT prcClip)
  40. {
  41. ASSERT(bHandles || bHatching);
  42. #ifdef _AFXDLL
  43. ASSERT(!m_bOpen);
  44. #endif
  45. ASSERT(m_bUIActive);
  46. ASSERT(m_pRectTracker == NULL);
  47. UINT nStyle = 0;
  48. if (bHandles)
  49. nStyle |= CRectTracker::resizeOutside;
  50. if (bHatching)
  51. nStyle |= CRectTracker::hatchedBorder;
  52. ASSERT(nStyle != 0);
  53. TRY
  54. {
  55. // Create the tracker.
  56. CRect rectTmp = m_rcPos;
  57. _AfxOffsetTrackerRect(rectTmp, this);
  58. m_pRectTracker = new CControlRectTracker(rectTmp, nStyle);
  59. // Reset the window sizes, reflecting the tracker
  60. if (prcClip != NULL)
  61. m_pRectTracker->m_rectClip = *prcClip;
  62. else
  63. prcClip = m_rcPos;
  64. OnSetObjectRects(m_rcPos, prcClip);
  65. }
  66. CATCH (CException, e)
  67. {
  68. // If anything went wrong, just continue without the tracker.
  69. if (m_pRectTracker != NULL)
  70. {
  71. delete m_pRectTracker;
  72. m_pRectTracker = NULL;
  73. }
  74. }
  75. END_CATCH
  76. }
  77. /////////////////////////////////////////////////////////////////////////////
  78. // COleControl::DestroyTracker - destroys tracker when control UIDeactivates
  79. void COleControl::DestroyTracker()
  80. {
  81. #ifdef _AFXDLL
  82. ASSERT(!m_bOpen);
  83. #endif
  84. ASSERT(m_bUIActive);
  85. if (m_pRectTracker == NULL)
  86. return;
  87. // Destroy the tracker.
  88. CRect rectClip = m_pRectTracker->m_rectClip;
  89. delete m_pRectTracker;
  90. m_pRectTracker = NULL;
  91. // Reset the position based on no tracker present
  92. OnSetObjectRects(m_rcPos, rectClip);
  93. }
  94. /////////////////////////////////////////////////////////////////////////////
  95. // COleControl::OnNcPaint - handler for WM_NCPAINT message
  96. void COleControl::OnNcPaint()
  97. {
  98. #ifdef _AFXDLL
  99. if (m_bOpen || m_pRectTracker == NULL)
  100. #else
  101. if (m_pRectTracker == NULL)
  102. #endif
  103. {
  104. Default();
  105. return;
  106. }
  107. DWORD dwStyle = GetStyle();
  108. DWORD dwExStyle = GetExStyle();
  109. DWORD dwScrollStyle = dwStyle & (WS_HSCROLL | WS_VSCROLL);
  110. // Paint scrollbars, if any.
  111. if (dwScrollStyle != 0)
  112. Default();
  113. UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  114. CWindowDC dc(this);
  115. // Convert client coords to window coords, draw tracker, and convert back.
  116. CRect& rectTrack = m_pRectTracker->m_rect;
  117. int dx = rectTrack.left - nHandleSize;
  118. int dy = rectTrack.top - nHandleSize;
  119. rectTrack.OffsetRect(-dx, -dy);
  120. CRect rc = rectTrack;
  121. m_pRectTracker->Draw(&dc);
  122. m_pRectTracker->m_rect.OffsetRect(dx, dy);
  123. // Draw border, if any.
  124. _AfxDrawBorders(&dc, rc, (dwStyle & WS_BORDER),
  125. (dwExStyle & WS_EX_CLIENTEDGE));
  126. if (dwScrollStyle == (WS_HSCROLL | WS_VSCROLL))
  127. {
  128. // Workaround for Windows bug:
  129. // Draw the corner between the scrollbars
  130. int cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
  131. if (dwExStyle & WS_EX_LEFTSCROLLBAR) // Middle East Windows only
  132. rc.right = rc.left + cxVScroll;
  133. else
  134. rc.left = rc.right - cxVScroll;
  135. rc.top = rc.bottom - GetSystemMetrics(SM_CYVSCROLL);
  136. CBrush brushGUI(GetSysColor(COLOR_3DFACE));
  137. dc.FillRect(rc, &brushGUI);
  138. }
  139. }
  140. /////////////////////////////////////////////////////////////////////////////
  141. // COleControl::OnNcCalcSize - handler for WM_NCCALCSIZE message
  142. void COleControl::OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS* lpParams)
  143. {
  144. Default();
  145. #ifdef _AFXDLL
  146. if (m_bOpen || m_pRectTracker == NULL)
  147. #else
  148. if (m_pRectTracker == NULL)
  149. #endif
  150. return;
  151. // Adjust client rect to make room for tracker.
  152. UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  153. ::InflateRect(lpParams->rgrc, -(int)nHandleSize, -(int)nHandleSize);
  154. m_pRectTracker->m_rect = m_rcPos;
  155. _AfxOffsetTrackerRect(m_pRectTracker->m_rect, this);
  156. }
  157. /////////////////////////////////////////////////////////////////////////////
  158. // COleControl::OnNcHitTest - handler for WM_NCHITTEST message
  159. UINT COleControl::OnNcHitTest(CPoint point)
  160. {
  161. #ifdef _AFXDLL
  162. if (m_bOpen || m_pRectTracker == NULL ||
  163. #else
  164. if (m_pRectTracker == NULL ||
  165. #endif
  166. !(m_pRectTracker->m_nStyle & _afxResizeStyle))
  167. {
  168. return (UINT)Default();
  169. }
  170. UINT nHitCode = (UINT)Default();
  171. // Check for scrollbar or sizebox hit.
  172. if ((nHitCode == HTHSCROLL) || (nHitCode == HTVSCROLL) ||
  173. (nHitCode == HTSIZE))
  174. {
  175. return nHitCode;
  176. }
  177. // Check for client area hit.
  178. CPoint pointClient(point);
  179. ScreenToClient(&pointClient);
  180. CRect rect;
  181. GetClientRect(rect);
  182. if (rect.PtInRect(pointClient))
  183. return HTCLIENT;
  184. // Check for border hit.
  185. UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  186. GetWindowRect(rect);
  187. rect.InflateRect(-(int)nHandleSize, -(int)nHandleSize);
  188. if (rect.PtInRect(point))
  189. return HTBORDER;
  190. // If tracker detects a hit, return HTBORDER; otherwise HTNOWHERE.
  191. nHitCode = m_pRectTracker->HitTest(pointClient);
  192. return (nHitCode == CRectTracker::hitNothing) ? HTNOWHERE : HTBORDER;
  193. }
  194. /////////////////////////////////////////////////////////////////////////////
  195. // COleControl::OnNcLButtonDown - handler for WM_NCLBUTTONDOWN message
  196. void COleControl::OnNcLButtonDown(UINT nHitTest, CPoint point)
  197. {
  198. #ifdef _AFXDLL
  199. if (m_bOpen || m_pRectTracker == NULL ||
  200. #else
  201. if (m_pRectTracker == NULL ||
  202. #endif
  203. !(m_pRectTracker->m_nStyle & _afxResizeStyle) ||
  204. (nHitTest == HTHSCROLL) || (nHitTest == HTVSCROLL))
  205. {
  206. Default();
  207. return;
  208. }
  209. ScreenToClient(&point);
  210. // Setup a (semi-)permanent CWnd for the control's parent window
  211. CRect rectBefore = m_pRectTracker->m_rect;
  212. CWnd* pWndClip = CWnd::FromHandle(::GetParent(GetOuterWindow()->m_hWnd));
  213. // Move or resize the tracker.
  214. BOOL bTrack = m_pRectTracker->Track(this, point, FALSE, pWndClip);
  215. if (bTrack)
  216. {
  217. ASSERT(m_pInPlaceSite);
  218. CRect rectAfter = m_pRectTracker->m_rect;
  219. if (rectBefore != rectAfter)
  220. {
  221. // If rectangle changed, adjust the tracker's rectangle and move
  222. // the control.
  223. m_pRectTracker->m_rect.OffsetRect(-m_pRectTracker->m_rect.left,
  224. -m_pRectTracker->m_rect.top);
  225. CWnd* pWndOuter = GetOuterWindow();
  226. CWnd* pWndParent = pWndOuter->GetParent();
  227. CRect rectWindow;
  228. CRect rectParent;
  229. pWndOuter->GetWindowRect(rectWindow);
  230. pWndParent->GetClientRect(rectParent);
  231. pWndParent->ClientToScreen(rectParent);
  232. int nBorderWidth = GetBorderStyle()*GetSystemMetrics( SM_CXBORDER );
  233. int nBorderHeight = GetBorderStyle()*GetSystemMetrics( SM_CYBORDER );
  234. UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;
  235. rectAfter.OffsetRect(rectWindow.left - rectParent.left +
  236. nHandleSize + nBorderWidth, rectWindow.top - rectParent.top +
  237. nHandleSize + nBorderHeight);
  238. // Update the control's extents.
  239. SIZEL szlPixels;
  240. SIZEL szlHimetric;
  241. szlPixels.cx = (long)rectAfter.Width();
  242. szlPixels.cy = (long)rectAfter.Height();
  243. _AfxXformSizeInPixelsToHimetric(NULL, &szlPixels, &szlHimetric);
  244. if ((m_cxExtent != szlHimetric.cx) ||
  245. (m_cyExtent != szlHimetric.cy))
  246. {
  247. m_cxExtent = szlHimetric.cx;
  248. m_cyExtent = szlHimetric.cy;
  249. SetModifiedFlag();
  250. }
  251. // Move/resize the control's window.
  252. m_pInPlaceSite->OnPosRectChange(rectAfter);
  253. }
  254. }
  255. }
  256. /////////////////////////////////////////////////////////////////////////////
  257. // COleControl::OnSetCursor - handler for WM_SETCURSOR message
  258. BOOL COleControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT)
  259. {
  260. #ifdef _AFXDLL
  261. if (m_bOpen || m_pRectTracker == NULL ||
  262. #else
  263. if (m_pRectTracker == NULL ||
  264. #endif
  265. !(m_pRectTracker->m_nStyle & _afxResizeStyle))
  266. {
  267. return (BOOL)Default();
  268. }
  269. if ((nHitTest == HTCLIENT) || (nHitTest == HTHSCROLL) ||
  270. (nHitTest == HTVSCROLL) || (nHitTest == HTSIZE))
  271. {
  272. // In client area: use default cursor or arrow.
  273. if (!Default())
  274. ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
  275. }
  276. else
  277. {
  278. // In non-client area: use tracker-supplied cursor.
  279. m_pRectTracker->SetCursor(pWnd, HTCLIENT);
  280. }
  281. return TRUE;
  282. }
  283. /////////////////////////////////////////////////////////////////////////////
  284. // Force any extra compiler-generated code into AFX_INIT_SEG
  285. #ifdef AFX_INIT_SEG
  286. #pragma code_seg(AFX_INIT_SEG)
  287. #endif