#include "precomp.h" #pragma hdrstop extern HWND hWndShell; /* ** Pointer to top of Dialog Stack DBCB (dialog box context block). */ PDBCB GLOBAL(pdbcbTop) = NULL; /* ** Purpose: ** To allocate enough storage to hold one DBCB (dialog box context block). ** Arguments: ** None. ** Returns: ** A Non-NULL pointer to a block of memory the size of one DBCB if ** allocation succeeds, NULL otherwise. ** ****************************************************************************/ PDBCB APIENTRY PdbcbAlloc() { PDBCB pdbcb; if ((pdbcb = (PDBCB)SAlloc(sizeof(DBCB))) != (PDBCB)NULL) { pdbcb->szDlgName = (SZ)NULL; pdbcb->hDlg = (HDLG)NULL; pdbcb->lpprocDlg = (WNDPROC)NULL; pdbcb->lpprocEventHandler = (PFNEVENT)NULL; pdbcb->hDlgFocus = (HDLG)NULL; pdbcb->szHelp = (SZ)NULL; pdbcb->hDlgHelp = (HDLG)NULL; pdbcb->lpprocHelp = (WNDPROC)NULL; pdbcb->pdbcbNext = (PDBCB)NULL; pdbcb->fActive = fFalse; } return(pdbcb); } /* ** Purpose: ** To free the storage occupied by one DBCB (dialog box context block). ** Arguments: ** pdbcb: A pointer to the DBCB. ** Returns: ** fFalse if the pdbcb is NULL or the operation fails, fTrue if the ** operation succeeds. ** *****************************************************************************/ BOOL APIENTRY FFreeDbcb(pdbcb) PDBCB pdbcb; { PreCondition(pdbcb != NULL, fFalse); SFree(pdbcb); return(fTrue); } /* ** Purpose: ** To push a dialog onto the dialog stack. ** Arguments: ** hinst: Handle to instance of the APP (i.e. the shell). ** szDlgName: Name of the dialog (e.g. GetDestPath, PrinterSelection). ** szDlgTemplate: Name of dialog template. ** hwndParent: Handle to the dialogs parent window (i.e. the shell). ** lpprocDlg: Procedure-instance address for the dialog procedure. ** lParam: 32-bit initialization value that will be passed to the ** dialog procedure when the dialog box is created. ** Currently unused by our general dialog procedures. ** lpprocEH: Procedure-instance address for the dialog event handler. ** szHelp: Name of Help dialog template associated with this dialog. ** lpprocHelp: Procedure-instance address for the help dlg procedure. ** Returns: ** A window handle to the dialog if the Push succeeds, NULL if it fails ** (i.e. if unable to allocate storage for the DBCB or the dialog creation ** fails. ** ****************************************************************************/ HDLG APIENTRY HdlgPushDbcb(hinst, szDlgName, szDlgTemplate, hwndParent, lpprocDlg, lParam, lpprocEH, szHelp, lpprocHelp) HANDLE hinst; SZ szDlgName; SZ szDlgTemplate; HWND hwndParent; WNDPROC lpprocDlg; DWORD lParam; PFNEVENT lpprocEH; SZ szHelp; WNDPROC lpprocHelp; { PDBCB pdbcb; Unused(szHelp); Unused(lpprocHelp); AssertDataSeg(); ChkArg(hinst != NULL, 1, NULL); ChkArg(szDlgTemplate != NULL, 2, NULL); ChkArg(hwndParent != NULL, 4, NULL); ChkArg(lpprocDlg != NULL, 5, NULL); while ((pdbcb = PdbcbAlloc()) == NULL) if (!FHandleOOM(hwndParent)) return(NULL); if (szDlgName != NULL) while ((pdbcb->szDlgName = SzDupl(szDlgName)) == (SZ)NULL) if (!FHandleOOM(hwndParent)) return(NULL); pdbcb->lpprocDlg = lpprocDlg; pdbcb->lpprocEventHandler = lpprocEH; pdbcb->pdbcbNext = GLOBAL(pdbcbTop); if ((pdbcb->hDlg = HdlgCreateFillAndShowDialog(hinst, szDlgTemplate, hwndParent, lpprocDlg, lParam)) != NULL) { // // Disable the main app window // EnableWindow( hWndShell, fFalse ); FFlashParentWindow( fFalse ) ; // // If there is a dialog on the stack disable it too // if (GLOBAL(pdbcbTop) != NULL) { FDisableDialog(GLOBAL(pdbcbTop)->hDlg); } GLOBAL(pdbcbTop) = pdbcb; // // Set this window as the active window // //SetActiveWindow( pdbcb->hDlg ); SetForegroundWindow(pdbcb->hDlg); } return(pdbcb->hDlg); } /* ** Purpose: ** To pop a dialog from the dialog stack and free the storage occupied by ** the DBCB(dialog box context block). ** Arguments: ** None. ** Returns: ** fFalse if the stack is empty, fTrue otherwise. ** ****************************************************************************/ BOOL APIENTRY FPopDbcb() { PDBCB pdbcbTemp = GLOBAL(pdbcbTop); AssertDataSeg(); // changed so that we no longer fail if there's nothing to pop (lonnym) // PreCondition(GLOBAL(pdbcbTop) != NULL, fFalse); if(GLOBAL(pdbcbTop) == NULL) { return(fTrue); } // // Enable the shell window till we have another dialog active // EnableWindow( hWndShell, fTrue ); // // If the dialog stack is empty, flash the parent app's window // if there is one. // if ( GLOBAL(pdbcbTop)->pdbcbNext == NULL ) { FFlashParentWindow( fTrue ) ; } EvalAssert(FCloseDialog(GLOBAL(pdbcbTop)->hDlg)); if (GLOBAL(pdbcbTop)->szDlgName != NULL) { SFree(GLOBAL(pdbcbTop)->szDlgName); } GLOBAL(pdbcbTop) = GLOBAL(pdbcbTop)->pdbcbNext; EvalAssert(FFreeDbcb(GLOBAL(pdbcbTemp))); return(fTrue); } /* ** Purpose: ** To pop N dialogs from the dialog stack and free the storage associated ** with the N DBCB's (dialog box context blocks). ** Arguments: ** n: The non-negative number of dialogs to be popped from the stack. ** Returns: ** fTrue if n == 0 or the n'th Pops succeeds, fFalse otherwise. ** ****************************************************************************/ BOOL APIENTRY FPopNDbcb(cDlgs) INT cDlgs; { AssertDataSeg(); ChkArg(cDlgs >= 0, 1, fFalse); if (cDlgs == 0) return(fTrue); while(--cDlgs != 0) EvalAssert(FPopDbcb()); return(FPopDbcb()); } /* ** Purpose: ** To preprocess messages sent to the main app window (i.e. the shell) that ** have special significance to the UI component. This function must be ** inserted in the message loop in the app's WinMain. The message should ** be passed to TranslateMessage or DispatchMessage if and only if ** FUiLibFilter returns fTrue. ** Arguments: ** pmsg: points to a MSG data structure that contains the message to be ** checked. ** Returns: ** fTrue if the message should also be passed to TranslateMessage and ** DispatchMessage, and fFalse otherwise. ** ****************************************************************************/ BOOL APIENTRY FUiLibFilter(pmsg) MSG * pmsg; { HDLG hDlg; HDLG hDlgHelp; AssertDataSeg(); switch(pmsg->message) { // case WM_SETFOCUS: // if(GLOBAL(pdbcbTop) != NULL) // SetFocus(GLOBAL(pdbcbTop)->hDlg); // break; // case WM_KEYDOWN: // if (pmsg->wParam == VK_TAB && GetKeyState(VK_CONTROL) < 0) // { // EvalAssert(FToggleDlgActivation()); // return(fFalse); // } // break; case WM_SYSCOMMAND: if (pmsg->wParam == SC_CLOSE && GLOBAL(pdbcbTop) != NULL) { // if (GLOBAL(pdbcbTop)->hDlgHelp != NULL) // SendMessage(GLOBAL(pdbcbTop)->hDlgHelp, WM_SYSCOMMAND, SC_CLOSE, // pmsg->lParam); // else SendMessage(GLOBAL(pdbcbTop)->hDlg, WM_SYSCOMMAND, SC_CLOSE, pmsg->lParam); return(fFalse); } break; } if (pdbcbTop == NULL) hDlg = hDlgHelp = NULL; else { hDlg = GLOBAL(pdbcbTop)->hDlg; hDlgHelp = NULL; // hDlgHelp = GLOBAL(pdbcbTop)->hDlgHelp; } return(((hDlg == 0 || !IsDialogMessage(hDlg, pmsg)) && (hDlgHelp == 0 || !IsDialogMessage(hDlgHelp, pmsg)))); } /* ** Purpose: ** To activate and enable the dialog on the top of the stack. This is ** used after the dialog stack has been popped to resume the previously ** inactive dialog. ** Arguments: ** None. ** Returns: ** fFalse if the stack is empty, fTrue otherwise. ** ****************************************************************************/ BOOL APIENTRY FResumeStackTop() { AssertDataSeg(); PreCondition(GLOBAL(pdbcbTop) != NULL, fFalse); EnableWindow( hWndShell, fFalse ); FFlashParentWindow( fFalse ); FEnableDialog(GLOBAL(pdbcbTop)->hDlg); /* do not EvalAssert */ SetActiveWindow(GLOBAL(pdbcbTop)->hDlg); // EvalAssert(FActivateStackTop()); return(fTrue); } /* ** Purpose: ** To get the name of the dialog on the top of the dialog stack. ** Arguments: ** None. ** Returns: ** NULL if the stack is empty, the sz that is the name of the top-of-stack ** dialog otherwise. ** *****************************************************************************/ SZ APIENTRY SzStackTopName() { AssertDataSeg(); if (GLOBAL(pdbcbTop) == NULL) return(NULL); else return(GLOBAL(pdbcbTop)->szDlgName); } /* ** Purpose: ** Called by the main app (i.e. the shell) to handle the events that can ** occur while executing the top-of-stack dialog. The events can ** optionally be preprocessed by a specific event handler for the dialog. ** The standard events (continue, back, help, exit) can be handled ** directly. ** Arguments: ** hInst: Handle to instance of the APP (i.e. the shell). ** hwndShell: Handle to the main app window (i.e. the shell). ** wMsg: UI-Lib defined messages indicating what event occurred. ** wParam: the wParam associated with the message wMsg. ** lParam: the lParam associated with the message wMsg. ** Notes: ** This processes button events by getting the associated value for ** $(ButtonPressed) from the Symbol Table (set by the standard dialogs) ** and, if that value equals IDC_C, IDC_B, or IDC_X, setting the ** value associated with the symbol $(DLGEVENT) to either "CONTINUE", ** "BACK", or "EXIT" respectively. ** Returns: ** fTrue if the event was handled, fFalse otherwise or if the stack is ** empty. ** *****************************************************************************/ BOOL APIENTRY FGenericEventHandler(HANDLE hInst, HWND hwndShell, UINT wMsg, WPARAM wParam, LPARAM lParam) { PFNEVENT pfnEvent; EHRC ehrc = ehrcNotHandled; AssertDataSeg(); PreCondition(GLOBAL(pdbcbTop) != NULL, fFalse); if (GLOBAL(pdbcbTop)->lpprocEventHandler != NULL) { pfnEvent = (PFNEVENT)GLOBAL(pdbcbTop)->lpprocEventHandler; ehrc = (*pfnEvent)(hInst, hwndShell, wMsg, wParam, lParam); } if (ehrc == ehrcNotHandled) { SZ szEvent; ehrc = ehrcPostInterp; EvalAssert((szEvent= SzFindSymbolValueInSymTab("ButtonPressed"))!=NULL); switch (atoi(szEvent)) { case IDC_C: szEvent = "CONTINUE"; break; case IDCANCEL: case IDC_B: szEvent = "BACK"; break; case IDC_H: szEvent = "HELP"; break; case IDC_X: szEvent = "EXIT"; break; case IDC_M: szEvent = "FREEBUTTON1"; break; case IDC_O: szEvent = "FREEBUTTON2"; break; case IDC_BTN0: case IDC_BTN1: case IDC_BTN2: case IDC_BTN3: case IDC_BTN4: case IDC_BTN5: case IDC_BTN6: case IDC_BTN7: case IDC_BTN8: case IDC_BTN9: { SZ butns[10] = {"DLGBUTTON0", "DLGBUTTON1", "DLGBUTTON2", "DLGBUTTON3", "DLGBUTTON4", "DLGBUTTON5", "DLGBUTTON6", "DLGBUTTON7", "DLGBUTTON8", "DLGBUTTON9", }; szEvent = butns[atoi(szEvent) - IDC_BTN0]; } break; default: szEvent = (SZ)NULL; ehrc = ehrcError; break; } if (szEvent != (SZ)NULL) { while (!FAddSymbolValueToSymTab("DLGEVENT", szEvent)) if (!FHandleOOM(hwndShell)) ehrc = ehrcError; } } if (ehrc == ehrcPostInterp) PostMessage(hwndShell, (WORD)STF_SHL_INTERP, 0, 0L); return(ehrc != ehrcError); } /* ** Purpose: ** To check if the stack is empty. ** Arguments: ** None. ** Returns: ** fTrue if the stack is empty, fFalse otherwise. ** *****************************************************************************/ BOOL APIENTRY FStackEmpty() { AssertDataSeg(); return(!GLOBAL(pdbcbTop)); } /* ** Purpose: ** To get the handle of the dialog on the top of the stack. ** Arguments: ** None. ** Returns: ** The handle to the dialog on the top of the stack, or NULL if the ** stack is empty. ** *****************************************************************************/ HDLG APIENTRY HdlgStackTop() { AssertDataSeg(); if (GLOBAL(pdbcbTop) == (PDBCB)NULL) return((HDLG)NULL); return((GLOBAL(pdbcbTop))->hDlg); }