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.

440 lines
13 KiB

  1. #include "stdafx.h"
  2. #include "Lava.h"
  3. #include "HWndContainer.h"
  4. #include "MsgHelp.h"
  5. #include "Spy.h"
  6. #define PROFILE_DRAW 0
  7. #if PROFILE_DRAW
  8. #include <icecap.h>
  9. #endif
  10. #if DBG
  11. UINT g_uMsgEnableSpy = RegisterWindowMessage(TEXT("GadgetSpy Enable"));
  12. UINT g_uMsgFindGadget = RegisterWindowMessage(TEXT("GadgetSpy FindGadget"));
  13. #endif // DBG
  14. /***************************************************************************\
  15. *****************************************************************************
  16. *
  17. * API Implementation
  18. *
  19. *****************************************************************************
  20. \***************************************************************************/
  21. //------------------------------------------------------------------------------
  22. HWndContainer *
  23. GetHWndContainer(DuVisual * pgad)
  24. {
  25. DuContainer * pcon = pgad->GetContainer();
  26. AssertReadPtr(pcon);
  27. HWndContainer * pconHWND = CastHWndContainer(pcon);
  28. return pconHWND;
  29. }
  30. /***************************************************************************\
  31. *****************************************************************************
  32. *
  33. * class HWndContainer
  34. *
  35. *****************************************************************************
  36. \***************************************************************************/
  37. //------------------------------------------------------------------------------
  38. HWndContainer::HWndContainer()
  39. {
  40. m_hwndOwner = NULL;
  41. }
  42. //------------------------------------------------------------------------------
  43. HWndContainer::~HWndContainer()
  44. {
  45. //
  46. // Need to destroy the gadget tree before this class is destructed since
  47. // it may need to make calls to the container during its destruction. If
  48. // we don't do this here, it may end up calling pure-virtual's on the base
  49. // class.
  50. //
  51. ContextLock cl;
  52. Verify(cl.LockNL(ContextLock::edDefer));
  53. xwDestroyGadget();
  54. }
  55. //------------------------------------------------------------------------------
  56. HRESULT
  57. HWndContainer::Build(HWND hwnd, HWndContainer ** ppconNew)
  58. {
  59. // Check parameters
  60. if (!ValidateHWnd(hwnd)) {
  61. return E_INVALIDARG;
  62. }
  63. // Create a new container
  64. HWndContainer * pconNew = ClientNew(HWndContainer);
  65. if (pconNew == NULL) {
  66. return E_OUTOFMEMORY;
  67. }
  68. pconNew->m_hwndOwner = hwnd;
  69. RECT rcClient;
  70. GetClientRect(hwnd, &rcClient);
  71. pconNew->m_sizePxl.cx = rcClient.right;
  72. pconNew->m_sizePxl.cy = rcClient.bottom;
  73. *ppconNew = pconNew;
  74. return S_OK;
  75. }
  76. //------------------------------------------------------------------------------
  77. void
  78. HWndContainer::OnInvalidate(const RECT * prcInvalidContainerPxl)
  79. {
  80. if ((!InlineIsRectEmpty(prcInvalidContainerPxl)) &&
  81. (prcInvalidContainerPxl->left <= m_sizePxl.cx) &&
  82. (prcInvalidContainerPxl->top <= m_sizePxl.cy) &&
  83. (prcInvalidContainerPxl->right >= 0) &&
  84. (prcInvalidContainerPxl->bottom >= 0)) {
  85. // TODO: How do we handle multiple layers / background?
  86. #if 0
  87. Trace("HWndContainer::OnInvalidate(): %d, %d, %d, %d\n",
  88. prcInvalidContainerPxl->left, prcInvalidContainerPxl->top,
  89. prcInvalidContainerPxl->right, prcInvalidContainerPxl->bottom);
  90. #endif
  91. InvalidateRect(m_hwndOwner, prcInvalidContainerPxl, TRUE);
  92. }
  93. }
  94. //------------------------------------------------------------------------------
  95. void
  96. HWndContainer::OnGetRect(RECT * prcDesktopPxl)
  97. {
  98. GetClientRect(m_hwndOwner, prcDesktopPxl);
  99. ClientToScreen(m_hwndOwner, (LPPOINT) &(prcDesktopPxl->left));
  100. ClientToScreen(m_hwndOwner, (LPPOINT) &(prcDesktopPxl->right));
  101. }
  102. //------------------------------------------------------------------------------
  103. void
  104. HWndContainer::OnStartCapture()
  105. {
  106. SetCapture(m_hwndOwner);
  107. }
  108. //------------------------------------------------------------------------------
  109. void
  110. HWndContainer::OnEndCapture()
  111. {
  112. ReleaseCapture();
  113. }
  114. //------------------------------------------------------------------------------
  115. BOOL
  116. HWndContainer::OnTrackMouseLeave()
  117. {
  118. TRACKMOUSEEVENT tme;
  119. tme.cbSize = sizeof(tme);
  120. tme.dwFlags = TME_LEAVE | TME_HOVER;
  121. tme.dwHoverTime = HOVER_DEFAULT;
  122. tme.hwndTrack = m_hwndOwner;
  123. return TrackMouseEvent(&tme);
  124. }
  125. //------------------------------------------------------------------------------
  126. void
  127. HWndContainer::OnSetFocus()
  128. {
  129. if (GetFocus() != m_hwndOwner) {
  130. //
  131. // Setting focus is a little more complicated than pure HWND's. This is
  132. // because Gadgets greatly simplify several things
  133. //
  134. // 1. SetFocus
  135. // 2. Setup caret, if any
  136. //
  137. //Trace("HWndContainer::OnSetFocus()\n");
  138. SetFocus(m_hwndOwner);
  139. }
  140. }
  141. //------------------------------------------------------------------------------
  142. void
  143. HWndContainer::OnRescanMouse(POINT * pptContainerPxl)
  144. {
  145. POINT ptCursor;
  146. if (!GetCursorPos(&ptCursor)) {
  147. ptCursor.x = -20000;
  148. ptCursor.y = -20000;
  149. }
  150. ScreenToClient(m_hwndOwner, &ptCursor);
  151. *pptContainerPxl = ptCursor;
  152. }
  153. //------------------------------------------------------------------------------
  154. BOOL
  155. HWndContainer::xdHandleMessage(UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT * pr, UINT nMsgFlags)
  156. {
  157. if (m_pgadRoot == NULL) {
  158. return FALSE; // If don't have a root, there is nothing to handle.
  159. }
  160. POINT ptContainerPxl;
  161. *pr = 0;
  162. switch (nMsg)
  163. {
  164. case WM_LBUTTONDOWN:
  165. case WM_RBUTTONDOWN:
  166. case WM_MBUTTONDOWN:
  167. case WM_LBUTTONDBLCLK:
  168. case WM_RBUTTONDBLCLK:
  169. case WM_MBUTTONDBLCLK:
  170. case WM_LBUTTONUP:
  171. case WM_RBUTTONUP:
  172. case WM_MBUTTONUP:
  173. {
  174. GMSG_MOUSECLICK msg;
  175. GdConvertMouseClickMessage(&msg, nMsg, wParam);
  176. ptContainerPxl.x = GET_X_LPARAM(lParam);
  177. ptContainerPxl.y = GET_Y_LPARAM(lParam);
  178. ContextLock cl;
  179. if (cl.LockNL(ContextLock::edDefer)) {
  180. return m_pgadRoot->xdHandleMouseMessage(&msg, ptContainerPxl);
  181. }
  182. break;
  183. }
  184. case WM_MOUSEWHEEL:
  185. {
  186. ptContainerPxl.x = GET_X_LPARAM(lParam);
  187. ptContainerPxl.y = GET_Y_LPARAM(lParam);
  188. // unlike every other mouse message, the x,y params for the
  189. // mouse wheel are in *screen* coordinates, not *client*
  190. // coordinates -- convert 'em here to "play along"
  191. ScreenToClient(m_hwndOwner, &ptContainerPxl);
  192. GMSG_MOUSEWHEEL msg;
  193. GdConvertMouseWheelMessage(&msg, wParam);
  194. ContextLock cl;
  195. if (cl.LockNL(ContextLock::edDefer)) {
  196. return m_pgadRoot->xdHandleMouseMessage(&msg, ptContainerPxl);
  197. }
  198. break;
  199. }
  200. case WM_MOUSEMOVE:
  201. case WM_MOUSEHOVER:
  202. {
  203. GMSG_MOUSE msg;
  204. GdConvertMouseMessage(&msg, nMsg, wParam);
  205. ptContainerPxl.x = GET_X_LPARAM(lParam);
  206. ptContainerPxl.y = GET_Y_LPARAM(lParam);
  207. ContextLock cl;
  208. if (cl.LockNL(ContextLock::edDefer)) {
  209. return m_pgadRoot->xdHandleMouseMessage(&msg, ptContainerPxl);
  210. }
  211. break;
  212. }
  213. case WM_MOUSELEAVE:
  214. {
  215. ContextLock cl;
  216. if (cl.LockNL(ContextLock::edDefer)) {
  217. m_pgadRoot->xdHandleMouseLeaveMessage();
  218. return TRUE;
  219. }
  220. break;
  221. }
  222. case WM_CAPTURECHANGED:
  223. if (m_hwndOwner != (HWND) lParam) {
  224. ContextLock cl;
  225. if (cl.LockNL(ContextLock::edDefer)) {
  226. m_pgadRoot->xdHandleMouseLostCapture();
  227. }
  228. }
  229. break;
  230. //
  231. // WM_SETFOCUS and WM_KILLFOCUS will restore and save (respectively) Gadget focus only
  232. // if we are gaining for losing focus from an HWND outside our tree.
  233. //
  234. case WM_SETFOCUS:
  235. {
  236. if ((m_hwndOwner != (HWND)wParam) && (IsChild(m_hwndOwner, (HWND)wParam) == FALSE)) {
  237. ContextLock cl;
  238. if (cl.LockNL(ContextLock::edDefer)) {
  239. return m_pgadRoot->xdHandleKeyboardFocus(GSC_SET);
  240. }
  241. }
  242. break;
  243. }
  244. case WM_KILLFOCUS:
  245. {
  246. if ((m_hwndOwner != (HWND)wParam) && (IsChild(m_hwndOwner, (HWND)wParam) == FALSE)) {
  247. ContextLock cl;
  248. if (cl.LockNL(ContextLock::edDefer)) {
  249. return m_pgadRoot->xdHandleKeyboardFocus(GSC_LOST);
  250. }
  251. }
  252. break;
  253. }
  254. case WM_CHAR:
  255. case WM_KEYDOWN:
  256. case WM_KEYUP:
  257. case WM_SYSCHAR:
  258. case WM_SYSKEYDOWN:
  259. case WM_SYSKEYUP:
  260. {
  261. GMSG_KEYBOARD msg;
  262. GdConvertKeyboardMessage(&msg, nMsg, wParam, lParam);
  263. ContextLock cl;
  264. if (cl.LockNL(ContextLock::edDefer)) {
  265. return m_pgadRoot->xdHandleKeyboardMessage(&msg, nMsgFlags);
  266. }
  267. break;
  268. }
  269. case WM_ERASEBKGND:
  270. return TRUE;
  271. case WM_PAINT:
  272. if ((!m_fManualDraw) && (m_pgadRoot != NULL)) {
  273. PAINTSTRUCT ps;
  274. if (BeginPaint(m_hwndOwner, &ps) != NULL) {
  275. #if PROFILE_DRAW
  276. StartProfile(PROFILE_GLOBALLEVEL, PROFILE_CURRENTID);
  277. #endif
  278. {
  279. ContextLock cl;
  280. if (cl.LockNL(ContextLock::edNone)) {
  281. m_pgadRoot->xrDrawTree(NULL, ps.hdc, &ps.rcPaint, 0);
  282. }
  283. }
  284. #if PROFILE_DRAW
  285. StopProfile(PROFILE_GLOBALLEVEL, PROFILE_CURRENTID);
  286. #endif
  287. EndPaint(m_hwndOwner, &ps);
  288. }
  289. return TRUE;
  290. }
  291. break;
  292. case WM_WINDOWPOSCHANGED:
  293. {
  294. WINDOWPOS * pwp = (WINDOWPOS *) lParam;
  295. UINT nFlags = 0;
  296. if (!TestFlag(pwp->flags, SWP_NOSIZE)) {
  297. RECT rcClient;
  298. GetClientRect(m_hwndOwner, &rcClient);
  299. nFlags |= SGR_SIZE;
  300. m_sizePxl.cx = rcClient.right;
  301. m_sizePxl.cy = rcClient.bottom;
  302. }
  303. //
  304. // Even if the window has moved, we don't need to change the
  305. // root gadget since it is relative to the container and that
  306. // has not changed.
  307. //
  308. // TODO: Need to change this to SGR_ACTUAL
  309. if (nFlags != 0) {
  310. ContextLock cl;
  311. if (cl.LockNL(ContextLock::edDefer)) {
  312. VerifyHR(m_pgadRoot->xdSetLogRect(0, 0, m_sizePxl.cx, m_sizePxl.cy, nFlags));
  313. }
  314. }
  315. }
  316. break;
  317. case WM_PARENTNOTIFY:
  318. // TODO: Need to notify the root gadget that an HWND has been created
  319. // or destroyed so that it can create an adapter gadget to back
  320. // it.
  321. break;
  322. case WM_GETROOTGADGET:
  323. if (m_pgadRoot != NULL) {
  324. *pr = (LRESULT) m_pgadRoot->GetHandle();
  325. return TRUE;
  326. }
  327. break;
  328. #if DBG
  329. default:
  330. if (nMsg == g_uMsgEnableSpy) {
  331. if (m_pgadRoot != NULL) {
  332. HGADGET hgadSelect = (HGADGET) lParam;
  333. HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  334. ContextLock cl;
  335. if (cl.LockNL(ContextLock::edNone)) {
  336. Spy::BuildSpy(m_hwndOwner, m_pgadRoot->GetHandle(), hgadSelect);
  337. SetCursor(hcurOld);
  338. }
  339. }
  340. } else if (nMsg == g_uMsgFindGadget) {
  341. POINT ptFindScreenPxl;
  342. ptFindScreenPxl.x = GET_X_LPARAM(lParam);
  343. ptFindScreenPxl.y = GET_Y_LPARAM(lParam);
  344. ScreenToClient(m_hwndOwner, &ptFindScreenPxl);
  345. ContextLock cl;
  346. if (cl.LockNL(ContextLock::edNone)) {
  347. POINT ptClientPxl;
  348. DuVisual * pgadFound = m_pgadRoot->FindFromPoint(ptFindScreenPxl, GS_VISIBLE, &ptClientPxl);
  349. if (wParam) {
  350. DuVisual::DEBUG_SetOutline(pgadFound);
  351. }
  352. if (pgadFound != NULL) {
  353. *pr = (LRESULT) pgadFound->GetHandle();
  354. return TRUE;
  355. }
  356. }
  357. }
  358. #endif // DBG
  359. }
  360. return FALSE;
  361. }