500 lines
13 KiB
C
500 lines
13 KiB
C
|
#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);
|
||
|
}
|