Source code of Windows XP (NT5)
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.

401 lines
11 KiB

  1. //============================================================================
  2. // Copyright (C) Microsoft Corporation, 1996 - 1999
  3. //
  4. // File: sheet.cpp
  5. //
  6. // History:
  7. // Abolade-Gbadegesin April-17-1996 Created.
  8. //
  9. // Contains implementation of modeless-capable property sheet class.
  10. //============================================================================
  11. #include "stdafx.h"
  12. #include "sheet.h"
  13. #include "dialog.h" // for FixupIpAddressHelp
  14. #ifdef _DEBUG
  15. #define new DEBUG_NEW
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. IMPLEMENT_DYNAMIC(CPropertySheetEx_Mine, CPropertySheet)
  20. BEGIN_MESSAGE_MAP(CPropertySheetEx_Mine, CPropertySheet)
  21. //{{AFX_MSG_MAP(CPropertySheetEx_Mine)
  22. //}}AFX_MSG_MAP
  23. ON_WM_HELPINFO()
  24. END_MESSAGE_MAP()
  25. static int g_piButtons[] = { IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP };
  26. //----------------------------------------------------------------------------
  27. // Function: CPropertySheetEx_Mine::DestroyWindow
  28. //
  29. // Called to destroy a modeless property-sheet.
  30. // If 'm_bDllInvoked' is TRUE, the function destroys the sheet in the context
  31. // of the DLL's 'CAdminThread', since the sheet will have been created
  32. // in that thread's context, and 'DestroyWindow' only works in the context
  33. // of the thread which created the window being destroyed.
  34. //----------------------------------------------------------------------------
  35. BOOL
  36. CPropertySheetEx_Mine::DestroyWindow(
  37. ) {
  38. BOOL bRet = FALSE;
  39. if (!m_bDllInvoked) {
  40. bRet = CPropertySheet::DestroyWindow();
  41. }
  42. else {
  43. Panic0("huh?");
  44. }
  45. return bRet;
  46. }
  47. //----------------------------------------------------------------------------
  48. // Function: CPropertySheetEx_Mine::DoModeless
  49. //
  50. // Called to display a modeless property-sheet.
  51. // If 'bDllInvoked' is TRUE, the function creates the sheet in the context
  52. // of the DLL's 'CAdminThread', to ensure that 'PreTranslateMessage'
  53. // is called for the property-sheet.
  54. //----------------------------------------------------------------------------
  55. BOOL
  56. CPropertySheetEx_Mine::DoModeless(
  57. IN CWnd* pParent,
  58. IN BOOL bDllInvoked
  59. ) {
  60. BOOL bRet = FALSE;
  61. if (!bDllInvoked) {
  62. //
  63. // We aren't in a DLL, so create the sheet
  64. // in the context of the caller's thread.
  65. //
  66. m_bDllInvoked = FALSE;
  67. bRet = Create(
  68. pParent, DS_MODALFRAME|DS_3DLOOK|DS_CONTEXTHELP|WS_POPUP|
  69. WS_VISIBLE|WS_CAPTION
  70. );
  71. }
  72. else {
  73. Panic0("huh?");
  74. }
  75. return bRet;
  76. }
  77. //----------------------------------------------------------------------------
  78. // Function: CPropertySheetEx_Mine::OnInitDialog
  79. //
  80. // Handles initialization for an extended property sheet.
  81. // This re-enables and re-displays the OK, Cancel, Apply and Help buttons
  82. // which are hidden by default for modeless sheets.
  83. //----------------------------------------------------------------------------
  84. BOOL
  85. CPropertySheetEx_Mine::OnInitDialog(
  86. ) {
  87. //
  88. // Save the absolute position of the sheet and the "OK" button
  89. // for the repair work we will do when the base version returns.
  90. // Also save the enabled/disabled state of the buttons
  91. //
  92. CRect rectWndOld;
  93. GetWindowRect(rectWndOld);
  94. CRect rectButton;
  95. HWND hwnd = ::GetDlgItem(m_hWnd, IDOK);
  96. ::GetWindowRect(hwnd, rectButton);
  97. //
  98. // Enable the Context sensitive help style for the
  99. // property sheet
  100. //
  101. LONG style = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  102. style |= WS_EX_CONTEXTHELP;
  103. ::SetWindowLong(m_hWnd, GWL_EXSTYLE, style);
  104. //
  105. // save the enabled/disabled state of the buttons
  106. //
  107. BOOL pfEnabled[sizeof(g_piButtons)/sizeof(int)];
  108. for (INT i = 0; i < sizeof(pfEnabled)/sizeof(BOOL); i++) {
  109. hwnd = ::GetDlgItem(m_hWnd, g_piButtons[i]);
  110. if (::IsWindow(hwnd)) { pfEnabled[i] = ::IsWindowEnabled(hwnd); }
  111. }
  112. //
  113. // invoke the base class property-sheet initialization
  114. //
  115. BOOL bResult = CPropertySheet::OnInitDialog();
  116. //
  117. // now if the sheet is modeless, undo the damage done
  118. // by the base class OnInitDialog. In particular, enable and unhide
  119. // the buttons OK, Cancel, Apply, and Help.
  120. // See dlgprop.cpp for the offending MFC code.
  121. //
  122. if (!m_bSheetModal && !(m_psh.dwFlags & PSH_WIZARD)) {
  123. //
  124. // resize the property-sheet window so that there is space
  125. // at the bottom for the buttons; we do this by adding back
  126. // the height of the area between the top of the OK button
  127. // and the original bottom of the property sheet
  128. //
  129. CRect rectWndNew;
  130. GetWindowRect(rectWndNew);
  131. SetWindowPos(
  132. NULL, 0, 0, rectWndNew.Width(), rectWndNew.Height() +
  133. rectWndOld.bottom - rectButton.top, SWP_NOMOVE | SWP_NOZORDER |
  134. SWP_NOACTIVATE
  135. );
  136. //
  137. // now restore the enable/disabled state of the buttons and show them
  138. //
  139. for (INT i = 0; i < sizeof(g_piButtons)/sizeof(int); i++) {
  140. if (g_piButtons[i] == IDHELP)
  141. { if (!(m_psh.dwFlags & PSH_HASHELP)) { continue; } }
  142. hwnd = ::GetDlgItem(m_hWnd, g_piButtons[i]);
  143. if (::IsWindow(hwnd)) {
  144. ::EnableWindow(hwnd, pfEnabled[i]);
  145. ::ShowWindow(hwnd, SW_SHOW);
  146. }
  147. }
  148. }
  149. return bResult;
  150. }
  151. //----------------------------------------------------------------------------
  152. // Function: CPropertySheetEx_Mine::PreTranslateMessage
  153. //
  154. // Augments the window procedure for modeless property-sheets
  155. // with a check to see whether the sheet should be destroyed.
  156. //----------------------------------------------------------------------------
  157. BOOL
  158. CPropertySheetEx_Mine::PreTranslateMessage(
  159. MSG* pmsg
  160. ) {
  161. //
  162. // Call the base version of PreTranslateMessage
  163. //
  164. // TRACE(TEXT("CPropertySheetEx_Mine::PreTranslateMessage\n"));
  165. BOOL bresult = CPropertySheet::PreTranslateMessage(pmsg);
  166. //
  167. // If the window is modeless, see if its time to destroy the window;
  168. // when it is, PropSheet_GetCurrentPageHwnd returns NULL
  169. //
  170. if (!m_bSheetModal && !PropSheet_GetCurrentPageHwnd(m_hWnd)) {
  171. DestroyWindow(); bresult = TRUE;
  172. }
  173. return bresult;
  174. }
  175. //----------------------------------------------------------------------------
  176. // Function: CPropertySheetEx_Mine::OnHelpInfo
  177. //
  178. //
  179. // This is called by MFC in response to WM_HELP message.
  180. // This function calls the AfxGetApp->WinHelp with the help ID corresponding
  181. // to the control or menu.
  182. //
  183. // MFC calls the window which received the WM_HELP message with the LPARAM
  184. // pointing to a HELPINFO structure. This HELPINFO structure has enought context
  185. // info to give us the control ID that needs the context help.
  186. //----------------------------------------------------------------------------
  187. BOOL CPropertySheetEx_Mine::OnHelpInfo(HELPINFO* pHelpInfo)
  188. {
  189. if (pHelpInfo->iContextType == HELPINFO_WINDOW)
  190. {
  191. HWND hItem = (HWND) pHelpInfo->hItemHandle;
  192. // Check for the case that we're looking for help in an IP
  193. // address control
  194. // hItem = FixupIpAddressHelp((HWND) pHelpInfo->hItemHandle);
  195. // If the help we're looking for is a different control, update
  196. // the control id also.
  197. // if (hItem != pHelpInfo->hItemHandle)
  198. // pHelpInfo->iCtrlId = ::GetDlgCtrlID(hItem);
  199. // for all dialog controls
  200. // AfxGetApp()->WinHelp(HID_BASE_CONTROL + pHelpInfo->iCtrlId, HELP_CONTEXTPOPUP);
  201. }
  202. else {
  203. // this is for menus
  204. // AfxGetApp()->WinHelp(HID_BASE_COMMAND + pHelpInfo->iCtrlId);
  205. }
  206. return TRUE;
  207. }
  208. //----------------------------------------------------------------------------
  209. // Class: CRtrSheet
  210. //
  211. //----------------------------------------------------------------------------
  212. IMPLEMENT_DYNAMIC(CRtrSheet, CPropertySheetEx_Mine)
  213. //----------------------------------------------------------------------------
  214. // Class: CRtrPage
  215. //
  216. //----------------------------------------------------------------------------
  217. IMPLEMENT_DYNAMIC(CRtrPage, CPropertyPage)
  218. BEGIN_MESSAGE_MAP(CRtrPage, CPropertyPage)
  219. ON_WM_HELPINFO()
  220. ON_WM_CONTEXTMENU()
  221. END_MESSAGE_MAP()
  222. /*!--------------------------------------------------------------------------
  223. CRtrPage::OnHelpInfo
  224. Brings up the context-sensitive help for the controls.
  225. Author: EricDav
  226. ---------------------------------------------------------------------------*/
  227. BOOL CRtrPage::OnHelpInfo(HELPINFO* pHelpInfo)
  228. {
  229. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  230. int i;
  231. DWORD dwCtrlId;
  232. if (pHelpInfo->iContextType == HELPINFO_WINDOW)
  233. {
  234. DWORD * pdwHelp = GetHelpMapInternal();
  235. if (pdwHelp)
  236. {
  237. // Ok to fix the f**king help for the f**king IP address
  238. // controls, we will need to add special case code. If we
  239. // can't find the id of our control in our list, then we look
  240. // to see if this is the child of the "RtrIpAddress" control, if
  241. // so then we change the pHelpInfo->hItemHandle to point to the
  242. // handle of the ip address control rather than the control in
  243. // the ip addrss control. *SIGH*
  244. dwCtrlId = ::GetDlgCtrlID((HWND) pHelpInfo->hItemHandle);
  245. for (i=0; pdwHelp[i]; i+=2)
  246. {
  247. if (pdwHelp[i] == dwCtrlId)
  248. break;
  249. }
  250. if (pdwHelp[i] == 0)
  251. {
  252. // Ok, we didn't find the control in our list, so let's
  253. // check to see if it's part of the IP address control.
  254. pHelpInfo->hItemHandle = FixupIpAddressHelp((HWND) pHelpInfo->hItemHandle);
  255. }
  256. ::WinHelp ((HWND)pHelpInfo->hItemHandle,
  257. AfxGetApp()->m_pszHelpFilePath,
  258. HELP_WM_HELP,
  259. (ULONG_PTR)pdwHelp);
  260. }
  261. }
  262. return TRUE;
  263. }
  264. /*!--------------------------------------------------------------------------
  265. CRtrPage::OnContextMenu
  266. Brings up the help context menu for those controls that don't
  267. usually have context menus (i.e. buttons). Note that this won't
  268. work for static controls since they just eat up all messages.
  269. Author: KennT
  270. ---------------------------------------------------------------------------*/
  271. void CRtrPage::OnContextMenu(CWnd* pWnd, CPoint point)
  272. {
  273. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  274. if (this == pWnd)
  275. return;
  276. DWORD * pdwHelp = GetHelpMapInternal();
  277. if (pdwHelp)
  278. {
  279. ::WinHelp (pWnd->m_hWnd,
  280. AfxGetApp()->m_pszHelpFilePath,
  281. HELP_CONTEXTMENU,
  282. (ULONG_PTR)pdwHelp);
  283. }
  284. }
  285. // This can be found in dialog.cpp
  286. extern PFN_FINDHELPMAP g_pfnHelpMap;
  287. DWORD * CRtrPage::GetHelpMapInternal()
  288. {
  289. DWORD * pdwHelpMap = NULL;
  290. DWORD dwIDD = 0;
  291. if ((ULONG_PTR) m_lpszTemplateName < 0xFFFF)
  292. dwIDD = (WORD) m_lpszTemplateName;
  293. // If there is no dialog IDD, give up
  294. // If there is no global help map function, give up
  295. if ((dwIDD == 0) ||
  296. (g_pfnHelpMap == NULL) ||
  297. ((pdwHelpMap = g_pfnHelpMap(dwIDD)) == NULL))
  298. return GetHelpMap();
  299. return pdwHelpMap;
  300. }