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.

499 lines
13 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. extern HWND hWndShell;
  4. /*
  5. ** Pointer to top of Dialog Stack DBCB (dialog box context block).
  6. */
  7. PDBCB GLOBAL(pdbcbTop) = NULL;
  8. /*
  9. ** Purpose:
  10. ** To allocate enough storage to hold one DBCB (dialog box context block).
  11. ** Arguments:
  12. ** None.
  13. ** Returns:
  14. ** A Non-NULL pointer to a block of memory the size of one DBCB if
  15. ** allocation succeeds, NULL otherwise.
  16. **
  17. ****************************************************************************/
  18. PDBCB APIENTRY PdbcbAlloc()
  19. {
  20. PDBCB pdbcb;
  21. if ((pdbcb = (PDBCB)SAlloc(sizeof(DBCB))) != (PDBCB)NULL)
  22. {
  23. pdbcb->szDlgName = (SZ)NULL;
  24. pdbcb->hDlg = (HDLG)NULL;
  25. pdbcb->lpprocDlg = (WNDPROC)NULL;
  26. pdbcb->lpprocEventHandler = (PFNEVENT)NULL;
  27. pdbcb->hDlgFocus = (HDLG)NULL;
  28. pdbcb->szHelp = (SZ)NULL;
  29. pdbcb->hDlgHelp = (HDLG)NULL;
  30. pdbcb->lpprocHelp = (WNDPROC)NULL;
  31. pdbcb->pdbcbNext = (PDBCB)NULL;
  32. pdbcb->fActive = fFalse;
  33. }
  34. return(pdbcb);
  35. }
  36. /*
  37. ** Purpose:
  38. ** To free the storage occupied by one DBCB (dialog box context block).
  39. ** Arguments:
  40. ** pdbcb: A pointer to the DBCB.
  41. ** Returns:
  42. ** fFalse if the pdbcb is NULL or the operation fails, fTrue if the
  43. ** operation succeeds.
  44. **
  45. *****************************************************************************/
  46. BOOL APIENTRY FFreeDbcb(pdbcb)
  47. PDBCB pdbcb;
  48. {
  49. PreCondition(pdbcb != NULL, fFalse);
  50. SFree(pdbcb);
  51. return(fTrue);
  52. }
  53. /*
  54. ** Purpose:
  55. ** To push a dialog onto the dialog stack.
  56. ** Arguments:
  57. ** hinst: Handle to instance of the APP (i.e. the shell).
  58. ** szDlgName: Name of the dialog (e.g. GetDestPath, PrinterSelection).
  59. ** szDlgTemplate: Name of dialog template.
  60. ** hwndParent: Handle to the dialogs parent window (i.e. the shell).
  61. ** lpprocDlg: Procedure-instance address for the dialog procedure.
  62. ** lParam: 32-bit initialization value that will be passed to the
  63. ** dialog procedure when the dialog box is created.
  64. ** Currently unused by our general dialog procedures.
  65. ** lpprocEH: Procedure-instance address for the dialog event handler.
  66. ** szHelp: Name of Help dialog template associated with this dialog.
  67. ** lpprocHelp: Procedure-instance address for the help dlg procedure.
  68. ** Returns:
  69. ** A window handle to the dialog if the Push succeeds, NULL if it fails
  70. ** (i.e. if unable to allocate storage for the DBCB or the dialog creation
  71. ** fails.
  72. **
  73. ****************************************************************************/
  74. HDLG APIENTRY HdlgPushDbcb(hinst, szDlgName, szDlgTemplate,
  75. hwndParent, lpprocDlg, lParam, lpprocEH, szHelp, lpprocHelp)
  76. HANDLE hinst;
  77. SZ szDlgName;
  78. SZ szDlgTemplate;
  79. HWND hwndParent;
  80. WNDPROC lpprocDlg;
  81. DWORD lParam;
  82. PFNEVENT lpprocEH;
  83. SZ szHelp;
  84. WNDPROC lpprocHelp;
  85. {
  86. PDBCB pdbcb;
  87. Unused(szHelp);
  88. Unused(lpprocHelp);
  89. AssertDataSeg();
  90. ChkArg(hinst != NULL, 1, NULL);
  91. ChkArg(szDlgTemplate != NULL, 2, NULL);
  92. ChkArg(hwndParent != NULL, 4, NULL);
  93. ChkArg(lpprocDlg != NULL, 5, NULL);
  94. while ((pdbcb = PdbcbAlloc()) == NULL)
  95. if (!FHandleOOM(hwndParent))
  96. return(NULL);
  97. if (szDlgName != NULL)
  98. while ((pdbcb->szDlgName = SzDupl(szDlgName)) == (SZ)NULL)
  99. if (!FHandleOOM(hwndParent))
  100. return(NULL);
  101. pdbcb->lpprocDlg = lpprocDlg;
  102. pdbcb->lpprocEventHandler = lpprocEH;
  103. pdbcb->pdbcbNext = GLOBAL(pdbcbTop);
  104. if ((pdbcb->hDlg = HdlgCreateFillAndShowDialog(hinst, szDlgTemplate,
  105. hwndParent, lpprocDlg, lParam)) != NULL)
  106. {
  107. //
  108. // Disable the main app window
  109. //
  110. EnableWindow( hWndShell, fFalse );
  111. FFlashParentWindow( fFalse ) ;
  112. //
  113. // If there is a dialog on the stack disable it too
  114. //
  115. if (GLOBAL(pdbcbTop) != NULL) {
  116. FDisableDialog(GLOBAL(pdbcbTop)->hDlg);
  117. }
  118. GLOBAL(pdbcbTop) = pdbcb;
  119. //
  120. // Set this window as the active window
  121. //
  122. //SetActiveWindow( pdbcb->hDlg );
  123. SetForegroundWindow(pdbcb->hDlg);
  124. }
  125. return(pdbcb->hDlg);
  126. }
  127. /*
  128. ** Purpose:
  129. ** To pop a dialog from the dialog stack and free the storage occupied by
  130. ** the DBCB(dialog box context block).
  131. ** Arguments:
  132. ** None.
  133. ** Returns:
  134. ** fFalse if the stack is empty, fTrue otherwise.
  135. **
  136. ****************************************************************************/
  137. BOOL APIENTRY FPopDbcb()
  138. {
  139. PDBCB pdbcbTemp = GLOBAL(pdbcbTop);
  140. AssertDataSeg();
  141. // changed so that we no longer fail if there's nothing to pop (lonnym)
  142. // PreCondition(GLOBAL(pdbcbTop) != NULL, fFalse);
  143. if(GLOBAL(pdbcbTop) == NULL) {
  144. return(fTrue);
  145. }
  146. //
  147. // Enable the shell window till we have another dialog active
  148. //
  149. EnableWindow( hWndShell, fTrue );
  150. //
  151. // If the dialog stack is empty, flash the parent app's window
  152. // if there is one.
  153. //
  154. if ( GLOBAL(pdbcbTop)->pdbcbNext == NULL )
  155. {
  156. FFlashParentWindow( fTrue ) ;
  157. }
  158. EvalAssert(FCloseDialog(GLOBAL(pdbcbTop)->hDlg));
  159. if (GLOBAL(pdbcbTop)->szDlgName != NULL) {
  160. SFree(GLOBAL(pdbcbTop)->szDlgName);
  161. }
  162. GLOBAL(pdbcbTop) = GLOBAL(pdbcbTop)->pdbcbNext;
  163. EvalAssert(FFreeDbcb(GLOBAL(pdbcbTemp)));
  164. return(fTrue);
  165. }
  166. /*
  167. ** Purpose:
  168. ** To pop N dialogs from the dialog stack and free the storage associated
  169. ** with the N DBCB's (dialog box context blocks).
  170. ** Arguments:
  171. ** n: The non-negative number of dialogs to be popped from the stack.
  172. ** Returns:
  173. ** fTrue if n == 0 or the n'th Pops succeeds, fFalse otherwise.
  174. **
  175. ****************************************************************************/
  176. BOOL APIENTRY FPopNDbcb(cDlgs)
  177. INT cDlgs;
  178. {
  179. AssertDataSeg();
  180. ChkArg(cDlgs >= 0, 1, fFalse);
  181. if (cDlgs == 0)
  182. return(fTrue);
  183. while(--cDlgs != 0)
  184. EvalAssert(FPopDbcb());
  185. return(FPopDbcb());
  186. }
  187. /*
  188. ** Purpose:
  189. ** To preprocess messages sent to the main app window (i.e. the shell) that
  190. ** have special significance to the UI component. This function must be
  191. ** inserted in the message loop in the app's WinMain. The message should
  192. ** be passed to TranslateMessage or DispatchMessage if and only if
  193. ** FUiLibFilter returns fTrue.
  194. ** Arguments:
  195. ** pmsg: points to a MSG data structure that contains the message to be
  196. ** checked.
  197. ** Returns:
  198. ** fTrue if the message should also be passed to TranslateMessage and
  199. ** DispatchMessage, and fFalse otherwise.
  200. **
  201. ****************************************************************************/
  202. BOOL APIENTRY FUiLibFilter(pmsg)
  203. MSG * pmsg;
  204. {
  205. HDLG hDlg;
  206. HDLG hDlgHelp;
  207. AssertDataSeg();
  208. switch(pmsg->message)
  209. {
  210. // case WM_SETFOCUS:
  211. // if(GLOBAL(pdbcbTop) != NULL)
  212. // SetFocus(GLOBAL(pdbcbTop)->hDlg);
  213. // break;
  214. // case WM_KEYDOWN:
  215. // if (pmsg->wParam == VK_TAB && GetKeyState(VK_CONTROL) < 0)
  216. // {
  217. // EvalAssert(FToggleDlgActivation());
  218. // return(fFalse);
  219. // }
  220. // break;
  221. case WM_SYSCOMMAND:
  222. if (pmsg->wParam == SC_CLOSE && GLOBAL(pdbcbTop) != NULL)
  223. {
  224. // if (GLOBAL(pdbcbTop)->hDlgHelp != NULL)
  225. // SendMessage(GLOBAL(pdbcbTop)->hDlgHelp, WM_SYSCOMMAND, SC_CLOSE,
  226. // pmsg->lParam);
  227. // else
  228. SendMessage(GLOBAL(pdbcbTop)->hDlg, WM_SYSCOMMAND, SC_CLOSE,
  229. pmsg->lParam);
  230. return(fFalse);
  231. }
  232. break;
  233. }
  234. if (pdbcbTop == NULL)
  235. hDlg = hDlgHelp = NULL;
  236. else
  237. {
  238. hDlg = GLOBAL(pdbcbTop)->hDlg;
  239. hDlgHelp = NULL;
  240. // hDlgHelp = GLOBAL(pdbcbTop)->hDlgHelp;
  241. }
  242. return(((hDlg == 0 || !IsDialogMessage(hDlg, pmsg)) &&
  243. (hDlgHelp == 0 || !IsDialogMessage(hDlgHelp, pmsg))));
  244. }
  245. /*
  246. ** Purpose:
  247. ** To activate and enable the dialog on the top of the stack. This is
  248. ** used after the dialog stack has been popped to resume the previously
  249. ** inactive dialog.
  250. ** Arguments:
  251. ** None.
  252. ** Returns:
  253. ** fFalse if the stack is empty, fTrue otherwise.
  254. **
  255. ****************************************************************************/
  256. BOOL APIENTRY FResumeStackTop()
  257. {
  258. AssertDataSeg();
  259. PreCondition(GLOBAL(pdbcbTop) != NULL, fFalse);
  260. EnableWindow( hWndShell, fFalse );
  261. FFlashParentWindow( fFalse );
  262. FEnableDialog(GLOBAL(pdbcbTop)->hDlg); /* do not EvalAssert */
  263. SetActiveWindow(GLOBAL(pdbcbTop)->hDlg);
  264. // EvalAssert(FActivateStackTop());
  265. return(fTrue);
  266. }
  267. /*
  268. ** Purpose:
  269. ** To get the name of the dialog on the top of the dialog stack.
  270. ** Arguments:
  271. ** None.
  272. ** Returns:
  273. ** NULL if the stack is empty, the sz that is the name of the top-of-stack
  274. ** dialog otherwise.
  275. **
  276. *****************************************************************************/
  277. SZ APIENTRY SzStackTopName()
  278. {
  279. AssertDataSeg();
  280. if (GLOBAL(pdbcbTop) == NULL)
  281. return(NULL);
  282. else
  283. return(GLOBAL(pdbcbTop)->szDlgName);
  284. }
  285. /*
  286. ** Purpose:
  287. ** Called by the main app (i.e. the shell) to handle the events that can
  288. ** occur while executing the top-of-stack dialog. The events can
  289. ** optionally be preprocessed by a specific event handler for the dialog.
  290. ** The standard events (continue, back, help, exit) can be handled
  291. ** directly.
  292. ** Arguments:
  293. ** hInst: Handle to instance of the APP (i.e. the shell).
  294. ** hwndShell: Handle to the main app window (i.e. the shell).
  295. ** wMsg: UI-Lib defined messages indicating what event occurred.
  296. ** wParam: the wParam associated with the message wMsg.
  297. ** lParam: the lParam associated with the message wMsg.
  298. ** Notes:
  299. ** This processes button events by getting the associated value for
  300. ** $(ButtonPressed) from the Symbol Table (set by the standard dialogs)
  301. ** and, if that value equals IDC_C, IDC_B, or IDC_X, setting the
  302. ** value associated with the symbol $(DLGEVENT) to either "CONTINUE",
  303. ** "BACK", or "EXIT" respectively.
  304. ** Returns:
  305. ** fTrue if the event was handled, fFalse otherwise or if the stack is
  306. ** empty.
  307. **
  308. *****************************************************************************/
  309. BOOL APIENTRY FGenericEventHandler(HANDLE hInst, HWND hwndShell,
  310. UINT wMsg, WPARAM wParam, LPARAM lParam)
  311. {
  312. PFNEVENT pfnEvent;
  313. EHRC ehrc = ehrcNotHandled;
  314. AssertDataSeg();
  315. PreCondition(GLOBAL(pdbcbTop) != NULL, fFalse);
  316. if (GLOBAL(pdbcbTop)->lpprocEventHandler != NULL)
  317. {
  318. pfnEvent = (PFNEVENT)GLOBAL(pdbcbTop)->lpprocEventHandler;
  319. ehrc = (*pfnEvent)(hInst, hwndShell, wMsg, wParam, lParam);
  320. }
  321. if (ehrc == ehrcNotHandled)
  322. {
  323. SZ szEvent;
  324. ehrc = ehrcPostInterp;
  325. EvalAssert((szEvent= SzFindSymbolValueInSymTab("ButtonPressed"))!=NULL);
  326. switch (atoi(szEvent))
  327. {
  328. case IDC_C:
  329. szEvent = "CONTINUE";
  330. break;
  331. case IDCANCEL:
  332. case IDC_B:
  333. szEvent = "BACK";
  334. break;
  335. case IDC_H:
  336. szEvent = "HELP";
  337. break;
  338. case IDC_X:
  339. szEvent = "EXIT";
  340. break;
  341. case IDC_M:
  342. szEvent = "FREEBUTTON1";
  343. break;
  344. case IDC_O:
  345. szEvent = "FREEBUTTON2";
  346. break;
  347. case IDC_BTN0:
  348. case IDC_BTN1: case IDC_BTN2: case IDC_BTN3:
  349. case IDC_BTN4: case IDC_BTN5: case IDC_BTN6:
  350. case IDC_BTN7: case IDC_BTN8: case IDC_BTN9:
  351. {
  352. SZ butns[10] = {"DLGBUTTON0",
  353. "DLGBUTTON1", "DLGBUTTON2", "DLGBUTTON3",
  354. "DLGBUTTON4", "DLGBUTTON5", "DLGBUTTON6",
  355. "DLGBUTTON7", "DLGBUTTON8", "DLGBUTTON9",
  356. };
  357. szEvent = butns[atoi(szEvent) - IDC_BTN0];
  358. }
  359. break;
  360. default:
  361. szEvent = (SZ)NULL;
  362. ehrc = ehrcError;
  363. break;
  364. }
  365. if (szEvent != (SZ)NULL)
  366. {
  367. while (!FAddSymbolValueToSymTab("DLGEVENT", szEvent))
  368. if (!FHandleOOM(hwndShell))
  369. ehrc = ehrcError;
  370. }
  371. }
  372. if (ehrc == ehrcPostInterp)
  373. PostMessage(hwndShell, (WORD)STF_SHL_INTERP, 0, 0L);
  374. return(ehrc != ehrcError);
  375. }
  376. /*
  377. ** Purpose:
  378. ** To check if the stack is empty.
  379. ** Arguments:
  380. ** None.
  381. ** Returns:
  382. ** fTrue if the stack is empty, fFalse otherwise.
  383. **
  384. *****************************************************************************/
  385. BOOL APIENTRY FStackEmpty()
  386. {
  387. AssertDataSeg();
  388. return(!GLOBAL(pdbcbTop));
  389. }
  390. /*
  391. ** Purpose:
  392. ** To get the handle of the dialog on the top of the stack.
  393. ** Arguments:
  394. ** None.
  395. ** Returns:
  396. ** The handle to the dialog on the top of the stack, or NULL if the
  397. ** stack is empty.
  398. **
  399. *****************************************************************************/
  400. HDLG APIENTRY HdlgStackTop()
  401. {
  402. AssertDataSeg();
  403. if (GLOBAL(pdbcbTop) == (PDBCB)NULL)
  404. return((HDLG)NULL);
  405. return((GLOBAL(pdbcbTop))->hDlg);
  406. }