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.

275 lines
9.3 KiB

  1. /**************************** Module Header ********************************\
  2. * Module Name: help.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Help function
  7. *
  8. * History:
  9. * 04-15-91 JimA Ported.
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. DWORD _GetWindowContextHelpId(PWND pWnd)
  14. {
  15. return (DWORD)(ULONG_PTR)_GetProp(pWnd, MAKEINTATOM(gpsi->atomContextHelpIdProp),
  16. PROPF_INTERNAL);
  17. }
  18. BOOL _SetWindowContextHelpId(PWND pWnd, DWORD dwContextId)
  19. {
  20. //If dwContextId is NULL, then this implies that the caller wants to
  21. // remove the dwContextId associated with this Window.
  22. if(dwContextId == 0) {
  23. InternalRemoveProp(pWnd, MAKEINTATOM(gpsi->atomContextHelpIdProp),
  24. PROPF_INTERNAL);
  25. return(TRUE);
  26. }
  27. return (InternalSetProp(pWnd, MAKEINTATOM(gpsi->atomContextHelpIdProp),
  28. (HANDLE)LongToHandle( dwContextId ), PROPF_INTERNAL | PROPF_NOPOOL));
  29. }
  30. /***************************************************************************\
  31. * SendHelpMessage
  32. *
  33. *
  34. \***************************************************************************/
  35. void xxxSendHelpMessage(
  36. PWND pwnd,
  37. int iType,
  38. int iCtrlId,
  39. HANDLE hItemHandle,
  40. DWORD dwContextId)
  41. {
  42. HELPINFO HelpInfo;
  43. long lValue;
  44. CheckLock(pwnd);
  45. HelpInfo.cbSize = sizeof(HELPINFO);
  46. HelpInfo.iContextType = iType;
  47. HelpInfo.iCtrlId = iCtrlId;
  48. HelpInfo.hItemHandle = hItemHandle;
  49. HelpInfo.dwContextId = dwContextId;
  50. lValue = _GetMessagePos();
  51. HelpInfo.MousePos.x = GET_X_LPARAM(lValue);
  52. HelpInfo.MousePos.y = GET_Y_LPARAM(lValue);
  53. xxxSendMessage(pwnd, WM_HELP, 0, (LPARAM)(LPHELPINFO)&HelpInfo);
  54. }
  55. /*
  56. * Modal loop for when the user has selected the help icon from the titlebar
  57. *
  58. */
  59. VOID xxxHelpLoop(PWND pwnd)
  60. {
  61. HWND hwndChild;
  62. PWND pwndChild;
  63. PWND pwndControl;
  64. MSG msg;
  65. RECT rc;
  66. int cBorders;
  67. PTHREADINFO ptiCurrent = PtiCurrent();
  68. DLGENUMDATA DlgEnumData;
  69. TL tlpwndChild;
  70. CheckLock(pwnd);
  71. UserAssert(IsWinEventNotifyDeferredOK());
  72. xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPSTART, pwnd, OBJID_WINDOW, INDEXID_CONTAINER, 0);
  73. zzzSetCursor(SYSCUR(HELP));
  74. xxxCapture(ptiCurrent, pwnd, SCREEN_CAPTURE);
  75. cBorders = GetWindowBorders(pwnd->style, pwnd->ExStyle, TRUE, FALSE);
  76. CopyInflateRect(&rc, &pwnd->rcWindow, -cBorders * SYSMET(CXBORDER), -cBorders * SYSMET(CYBORDER));
  77. while (ptiCurrent->pq->spwndCapture == pwnd) {
  78. if (!xxxPeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_NOREMOVE)) {
  79. xxxWaitMessage();
  80. continue;
  81. }
  82. if (msg.message == WM_NCLBUTTONDOWN) {
  83. break;
  84. } else if (msg.message == WM_LBUTTONDOWN) {
  85. /*
  86. * If user clicked outside of window client, bail out now.
  87. */
  88. if (!PtInRect(&rc, msg.pt))
  89. break;
  90. /*
  91. * WindowHitTest() won't return a static control's handle
  92. */
  93. hwndChild = xxxWindowHitTest(pwnd, msg.pt, NULL, 0);
  94. pwndChild = ValidateHwnd( hwndChild );
  95. ThreadLock(pwndChild, &tlpwndChild);
  96. if (pwndChild && FIsParentDude(pwndChild))
  97. {
  98. /*
  99. * If this is a dialog class, then one of three things has
  100. * happened:
  101. *
  102. * o This is a static text control
  103. * o This is the background of the dialog box.
  104. *
  105. * What we do is enumerate the child windows and see if
  106. * any of them contain the current cursor point. If they do,
  107. * change our window handle and continue on. Otherwise,
  108. * return doing nothing -- we don't want context-sensitive
  109. * help for a dialog background.
  110. *
  111. * If this is a group box, then we might have clicked on a
  112. * disabled control, so we enumerate child windows to see
  113. * if we get another control.
  114. */
  115. /*
  116. * We're enumerating a dialog's children. So, if we don't
  117. * find any matches, hwndChild will be NULL and the check
  118. * below will drop out.
  119. */
  120. DlgEnumData.pwndDialog = pwndChild;
  121. DlgEnumData.pwndControl = NULL;
  122. DlgEnumData.ptCurHelp = msg.pt;
  123. xxxInternalEnumWindow(pwndChild, EnumPwndDlgChildProc, (LPARAM)&DlgEnumData, BWL_ENUMCHILDREN);
  124. pwndControl = DlgEnumData.pwndControl;
  125. } else {
  126. pwndControl = pwndChild;
  127. }
  128. /*
  129. * If we click on nothing, just exit.
  130. */
  131. if (pwndControl == pwnd) {
  132. pwndControl = NULL;
  133. }
  134. /*
  135. * HACK ALERT (Visual Basic 4.0) - they have their own non-window
  136. * based controls that draw directly on the main dialog. In order
  137. * to provide help for these controls, we pass along the WM_HELP
  138. * message iff the main dialog has a context id assigned.
  139. *
  140. * If the top level window has its own context help ID,
  141. * then pass it in the context help message.
  142. */
  143. if (!pwndControl) {
  144. if (_GetProp(pwnd, MAKEINTATOM(gpsi->atomContextHelpIdProp), TRUE))
  145. pwndControl = pwnd;
  146. }
  147. if (pwndControl) {
  148. PWND pwndSend;
  149. int id;
  150. TL tlpwndSend;
  151. TL tlpwndControl;
  152. ThreadLockAlways(pwndControl, &tlpwndControl);
  153. zzzSetCursor(SYSCUR(ARROW));
  154. xxxReleaseCapture();
  155. xxxRedrawTitle(pwnd, DC_BUTTONS);
  156. ClrWF(pwnd, WFHELPBUTTONDOWN);
  157. xxxGetMessage(&msg, NULL, 0, 0);
  158. xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR,
  159. INDEX_TITLEBAR_HELPBUTTON, FALSE);
  160. xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPEND, pwnd, OBJID_WINDOW,
  161. INDEXID_CONTAINER, FALSE);
  162. /*
  163. * Determine the ID of the control
  164. * We used to always sign extend, but Win98 doesn't do that
  165. * so we only sign extend 0xffff. MCostea #218711
  166. */
  167. if (TestwndChild(pwndControl)) {
  168. id = PTR_TO_ID(pwndControl->spmenu);
  169. if (id == 0xffff) {
  170. id = -1;
  171. }
  172. } else {
  173. id = -1;
  174. }
  175. /*
  176. * Disabled controls and static controls won't pass this
  177. * on to their parent, so instead, we send the message to
  178. * their parent.
  179. */
  180. if (TestWF(pwndControl, WFDISABLED)) {
  181. PWND pwndParent = _GetParent(pwndControl);
  182. if (!pwndParent)
  183. {
  184. ThreadUnlock( &tlpwndControl );
  185. ThreadUnlock( &tlpwndChild );
  186. return;
  187. }
  188. pwndSend = pwndParent;
  189. } else {
  190. pwndSend = pwndControl;
  191. }
  192. ThreadLockAlways(pwndSend, &tlpwndSend);
  193. xxxSendHelpMessage( pwndSend, HELPINFO_WINDOW, id,
  194. (HANDLE)HWq(pwndControl), GetContextHelpId(pwndControl));
  195. ThreadUnlock(&tlpwndSend);
  196. ThreadUnlock(&tlpwndControl);
  197. ThreadUnlock(&tlpwndChild);
  198. return;
  199. }
  200. ThreadUnlock(&tlpwndChild);
  201. break;
  202. }
  203. else if ((msg.message == WM_RBUTTONDOWN) ||
  204. (msg.message == WM_MBUTTONDOWN) ||
  205. (msg.message == WM_XBUTTONDOWN)) {
  206. /*
  207. * fix bug 29852; break the loop for right and middle buttons
  208. * and pass along the messages to the control
  209. */
  210. break;
  211. }
  212. else if (msg.message == WM_MOUSEMOVE) {
  213. if (PtInRect(&rc, msg.pt))
  214. zzzSetCursor(SYSCUR(HELP));
  215. else
  216. zzzSetCursor(SYSCUR(ARROW));
  217. }
  218. else if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
  219. {
  220. xxxGetMessage( &msg, NULL, 0, 0 );
  221. break;
  222. }
  223. xxxGetMessage(&msg, NULL, 0, 0);
  224. xxxTranslateMessage(&msg, 0);
  225. xxxDispatchMessage(&msg);
  226. }
  227. xxxReleaseCapture();
  228. zzzSetCursor(SYSCUR(ARROW));
  229. xxxRedrawTitle(pwnd, DC_BUTTONS);
  230. ClrWF(pwnd, WFHELPBUTTONDOWN);
  231. xxxWindowEvent(EVENT_OBJECT_STATECHANGE, pwnd, OBJID_TITLEBAR,
  232. INDEX_TITLEBAR_HELPBUTTON, 0);
  233. xxxWindowEvent(EVENT_SYSTEM_CONTEXTHELPEND, pwnd, OBJID_WINDOW,
  234. INDEXID_CONTAINER, 0);
  235. }