//*----------------------------------------------------------------------- //| MODULE: WCTAPI.C //| PROJECT: Windows Comparison Tool //| //| PURPOSE: This module contains all of the API entry-points to the //| WCT engine. //| //| REVISION HISTORY: //| 04-16-92 w-steves TestDlgs (2.0) code complete //| 10-29-90 randyki Created module //*----------------------------------------------------------------------- #include "enghdr.h" #ifndef WIN32 #pragma hdrstop ("engpch.pch") #endif /* windows.h doesn't declare it */ #include #ifndef WIN32 VOID FARPUBLIC yield(VOID); #endif #define CMPTIMER 42 // timer ID value (compare) #define SAVETIMER 43 // timer ID value (save) //*----------------------------------------------------------------------- //| Global variables and stuff //*----------------------------------------------------------------------- CHAR szLogName[cchMaxfileName]; CHAR szDialogName[cchMaxfileName]; INT fDialogSet, nDynCount, fDynMenu, fCompPending, fSavePending; INT nDynNumber, fIncPar, nCompRes, fFullDynDlg, nDlgsInFile, fRep; INT nSaveOp, nSaveRes, iLibInit = 0; UINT CmpTimer, SaveTimer; CHAR szClose[128], szSaveDesc[128]; HANDLE hDynDialog, hTESTEVT; INT ( APIENTRY *DoKeys)(LPSTR); BOOL fIgnoreEvntErrTrap = FALSE; // Trap either WinMissing, or EvntErr, not both INT vWINTrapID; // WattDrvr TrapID for missing windows INT vERRTrapID; // WattDrvr TrapID for entrypoint errors TrapCallBack WINTrapCallBack = NULL;// WattDrvr Callback for missing windows TrapCallBack ERRTrapCallBack = NULL;// WattDrvr Callback for entrypoint errors //------------------------------------------------------------------------ // Define the OutDebug macro on definition of the DEBUG macro //------------------------------------------------------------------------ #ifdef DEBUG #define OutDebug(N) OutputDebugString(N) #else #define OutDebug(N) #endif //*----------------------------------------------------------------------- //| LoadTESTEVT //| //| PURPOSE: Load the TESTEVT DLL library and set the DoKeys pointer //| to the DoKeys routine. //| //| //*----------------------------------------------------------------------- INT FARPUBLIC LoadTESTEVT () { // Load the library, and return error if not successful //---------------------------------------------------------------- hTESTEVT = MLoadLibrary ("TESTEVNT.DLL"); #ifdef WIN32 if (!hTESTEVT) #else if (hTESTEVT < 32) #endif return (WCT_LIBLOADERR); // Set DoKeys accordingly, and return success/failure //---------------------------------------------------------------- (FARPROC) DoKeys = GetProcAddress (hTESTEVT, "DoKeys"); if (!DoKeys) return (WCT_LIBLOADERR); return (WCT_NOERR); } //*----------------------------------------------------------------------- //| FreeTESTEVT //| //| PURPOSE: Free the TESTEVT DLL library and set the DoKeys pointer //| to NULL. //| //| //*----------------------------------------------------------------------- VOID FARPUBLIC FreeTESTEVT () { DoKeys = NULL; FreeLibrary (hTESTEVT); } //*----------------------------------------------------------------------- //| WCTInit //| //| PURPOSE: Initialize the WCT engine //| //| //| //*----------------------------------------------------------------------- INT FARPUBLIC TESTDlgsInit () { if (!iLibInit) { lstrcpy (szLogName, (LPSTR)"RESULTS.LOG"); fDialogSet = FALSE; hDynDialog = NULL; nDynCount = 0; fCompPending = FALSE; hTESTEVT = NULL; DoKeys = NULL; fFullDynDlg = 1; lMatchPref = MATCH_DEFAULT; lMatchPref <<= 16; iLibInit = 1; } return (WCT_NOERR); } //*----------------------------------------------------------------------- //| CmpWindow //| //| PURPOSE: Compare information from given window to info in dialog //| file //| //*----------------------------------------------------------------------- INT FARPUBLIC CmpWindow (HWND hWnd, INT nDialog, INT fIncludeParent) { INT r; if( FWinExceptNULLTrap( hWnd ) ) return ErrorTrap(WCT_INVALIDHWND); // Check to see if this is a dynamic dialog comparison. If so, // make sure that there exists a dynamic dialog. //---------------------------------------------------------------- if ( (nDialog == 0) && (hDynDialog == NULL) ) return ErrorTrap(WCT_NODYNDIALOG); // If this is NOT a dynamic dialog comparison and there is no // current dialog file, return an error. //---------------------------------------------------------------- if ( (nDialog > 0) && (!fDialogSet) ) return ErrorTrap(WCT_NODLGFILE); // Now, check hWnd to see if it is NULL -- if so, get the // active window with GetActiveWindow() //---------------------------------------------------------------- if (hWnd == NULL) hWnd = GetActiveWindow(); // Now it's time to do the comparison. fDoCompare is smart enough // to know what kind of comparison (menu vs dialog) to do, as well // as to handle the dynamic dialog comparison if need be. //---------------------------------------------------------------- r = fDoCompare (szDialogName, hWnd, nDialog, fIncludeParent, szLogName, hDynDialog, nDynCount * fFullDynDlg); // Store the results in case the user calls ComparisonResults, and // return them. //---------------------------------------------------------------- nCompRes = r; return ErrorTrap(r); } //*----------------------------------------------------------------------- //| FindWindowCaption //| //| PURPOSE: Search for a window with the given caption, starting at //| the window given. Recursively searches in the order: //| 1) Given window //| 2) Given window's children //| 3) Given window's siblings //| //| RETURNS: HWND if window found, or NULL if not //| //*----------------------------------------------------------------------- HWND FARPUBLIC FindWindowCaption (LPSTR lpszCaption, HWND hWndStart) { HWND hWnd; static CHAR szCap[80]; // UNDONE: Make a constant! // See if the window given is valid - if NULL, return NULL //---------------------------------------------------------------- if (!hWndStart) return (NULL); // Check the given window - if it's the one we're looking for, // return the handle to it and we're done! //---------------------------------------------------------------- GetWindowText (hWndStart, szCap, 79); if (!lstrcmp(szCap, lpszCaption)) // We found it, return the handle! //-------------------------------------------------------- return (hWndStart); // Well, we didn't find it yet, so start the search again starting // with this window's children. //---------------------------------------------------------------- hWnd = FindWindowCaption (lpszCaption, GetWindow(hWndStart, GW_CHILD)); if (hWnd) return (hWnd); // rewrite to not use recursion. // Again, no luck. This time, start looking at the window's // siblings and see if such a window exists there. //---------------------------------------------------------------- hWnd = FindWindowCaption (lpszCaption, GetNextWindow(hWndStart, GW_HWNDNEXT)); return (hWnd); // // //without recursion, the whole thing would look something like this: //#define CBCAPTIONMAX 80 // // HWND hWnd; // static char szCap[CBCAPTIONMAX]; // // if (!hWndStart) // return (NULL); // // GetWindowText (hWndStart, szCap, CBCAPTIONMAX-1); // is it already the right one? // if (!lstrcmp(szCap, lpszCaption)) // return (hWndStart); // // do // { // hWnd = hWndStart; // look through child windows // do // { // hWnd = GetWindow(hWnd, GW_CHILD); // GetWindowText (hWnd, szCap, CBCAPTIONMAX-1); // if (!lstrcmp(szCap, lpszCaption)) // return (hWnd); // return if found // } // while (hWnd != NULL); // // hWndStart = GetNextWindow(hWndStart, GW_HWNDNEXT)); // examine siblings // GetWindowText (hWndStart, szCap, CBCAPTIONMAX-1); // if (!lstrcmp(szCap, lpszCaption)) // return (hWndStart); // return if found // } // while (hWndStart != NULL); // return (NULL); // } //*----------------------------------------------------------------------- //| CmpWindowCaption //| //| PURPOSE: Compare information from window with given caption to info //| in dialog file //| //*----------------------------------------------------------------------- INT FARPUBLIC CmpWindowCaption (LPSTR lpszCaption, INT nDialog, INT fIncludeParent) { INT r; HWND hWnd; // Check to see if this is a dynamic dialog comparison. If so, // make sure that there exists a dynamic dialog. //---------------------------------------------------------------- if ( (nDialog == 0) && (hDynDialog == NULL) ) return ErrorTrap(WCT_NODYNDIALOG); // If this is NOT a dynamic dialog comparison and there is no // current dialog file, return an error. //---------------------------------------------------------------- if ( (nDialog > 0) && (!fDialogSet) ) return ErrorTrap(WCT_NODLGFILE); // Now, check lpszCaption to see if it is NULL -- if so, get the // active window with GetActiveWindow(), else get the window with // a matching caption //---------------------------------------------------------------- if (lpszCaption == NULL) hWnd = GetActiveWindow(); else { hWnd = FindWindowCaption (lpszCaption, GetDesktopWindow()); if (hWnd == NULL) return ErrorTrap(WCT_BADCAPTION); } // Now it's time to do the comparison. fDoCompare is smart enough // to know what kind of comparison (menu vs dialog) to do, as well // as to handle the dynamic dialog comparison if need be. //---------------------------------------------------------------- r = fDoCompare (szDialogName, hWnd, nDialog, fIncludeParent, szLogName, hDynDialog, nDynCount * fFullDynDlg); // Store the results in case the user calls ComparisonResults, and // return them. //---------------------------------------------------------------- nCompRes = r; return ErrorTrap(r); } //*----------------------------------------------------------------------- //| CmpWindowActivate //| //| PURPOSE: Activate the target window (optional), compare it against //| info in dialog file, and close the window (optional) //| //*----------------------------------------------------------------------- INT FARPUBLIC CmpWindowActivate (LPSTR OpenKeys, LPSTR CloseKeys, INT nDialog, INT fIncludeParent) { HWND hWnd; INT r; // Check to see if this is a dynamic dialog comparison. If so, // make sure that there exists a dynamic dialog. //---------------------------------------------------------------- if ( (nDialog == 0) && (hDynDialog == NULL) ) return ErrorTrap(WCT_NODYNDIALOG); // If this is NOT a dynamic dialog comparison and there is no // current dialog file, return an error. //---------------------------------------------------------------- if ( (nDialog > 0) && (!fDialogSet) ) return ErrorTrap(WCT_NODLGFILE); // Load TESTEVT.DLL, and return error code if can't do it //---------------------------------------------------------------- if (LoadTESTEVT()) return ErrorTrap(WCT_LIBLOADERR); // If not NULL, send the SendKeys string OpenKeys //---------------------------------------------------------------- if (OpenKeys) { DoKeys (OpenKeys); /* do some yields to allow keys to get to app and some time ** for it to respond. */ #ifndef WIN32 yield(); yield(); yield(); yield(); yield(); #endif } // Grab the active window //---------------------------------------------------------------- hWnd = GetActiveWindow(); // Now it's time to do the comparison. fDoCompare is smart enough // to know what kind of comparison (menu vs dialog) to do, as well // as to handle the dynamic dialog comparison if need be. //---------------------------------------------------------------- r = fDoCompare (szDialogName, hWnd, nDialog, fIncludeParent, szLogName, hDynDialog, nDynCount * fFullDynDlg); // If not NULL, send the SendKeys string CloseKeys //---------------------------------------------------------------- if (CloseKeys) DoKeys (CloseKeys); // Unload the TESTEVT library //---------------------------------------------------------------- FreeTESTEVT(); // Store the results in case the user calls ComparisonResults, and // return them. //---------------------------------------------------------------- nCompRes = r; return ErrorTrap(r); } //*----------------------------------------------------------------------- //| DoDelayCmp //| //| PURPOSE: Perform the delayed comparison. //| //| //*----------------------------------------------------------------------- WORD APIENTRY DoDelayCmp (HWND hW, WORD wMsg, INT nIDEvent, DWORD dwTime) { HWND hWnd; // First thing we do is kill the timer - we don't want it going // off again... //---------------------------------------------------------------- KillTimer (NULL, CmpTimer); // Grab the active window //---------------------------------------------------------------- hWnd = GetActiveWindow(); // Now it's time to do the comparison. fDoCompare is smart enough // to know what kind of comparison (menu vs dialog) to do, as well // as to handle the dynamic dialog comparison if need be. //---------------------------------------------------------------- nCompRes = fDoCompare (szDialogName, hWnd, nDynNumber, fIncPar, szLogName, hDynDialog, nDynCount * fFullDynDlg); // If not NULL, send the SendKeys string CloseKeys //---------------------------------------------------------------- if (szClose) DoKeys (szClose); // Unload the TESTEVT library //---------------------------------------------------------------- FreeTESTEVT(); // Turn off the pending flag so ComparisonResults can return the // nCompRes value //---------------------------------------------------------------- fCompPending = FALSE; return 0; } //*----------------------------------------------------------------------- //| CmpWindowDelayed //| //| PURPOSE: Wait given time, compare active window against info in the //| dialog file, and (optionally) close the active window //| //*----------------------------------------------------------------------- INT FARPUBLIC CmpWindowDelayed (INT nDelay, INT nDialog, INT fIncludeParent, LPSTR CloseKeys) { MSG msg; // For the CompareDelayed and SaveDelayed functions, we must make // sure that one is not pending before calling another //---------------------------------------------------------------- while (fSavePending) { if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage ((LPMSG)&msg); DispatchMessage ((LPMSG)&msg); } } // Check to see if this is a dynamic dialog comparison. If so, // make sure that there exists a dynamic dialog. //---------------------------------------------------------------- if ( (nDialog == 0) && (hDynDialog == NULL) ) return ErrorTrap(WCT_NODYNDIALOG); // If this is NOT a dynamic dialog comparison and there is no // current dialog file, return an error. //---------------------------------------------------------------- if ( (nDialog > 0) && (!fDialogSet) ) return ErrorTrap(WCT_NODLGFILE); // Load TESTEVT.DLL, and return error code if can't do it //---------------------------------------------------------------- if (LoadTESTEVT()) return ErrorTrap(WCT_LIBLOADERR); // Store all the parameters in local storage so the timer routine // knows what data to use //---------------------------------------------------------------- nDynNumber = nDialog; fIncPar = fIncludeParent; _fstrncpy (szClose, CloseKeys, 127); szClose [127] = '\0'; // Set the timer and leave //---------------------------------------------------------------- CmpTimer = SetTimer (NULL, CMPTIMER, nDelay * 1000, (TIMERPROC) DoDelayCmp); if (!CmpTimer) return ErrorTrap(WCT_NOTIMER); fCompPending = TRUE; return ErrorTrap(WCT_NOERR); } //*----------------------------------------------------------------------- //| SetLogFile //| //| PURPOSE: Set the name of the error log file. //| //| //*----------------------------------------------------------------------- INT FARPUBLIC SetLogFile (LPSTR lpszLogName) { INT fh; static CHAR pathbuf[_MAX_PATH]; static CHAR partial[_MAX_PATH]; // Create a fully-specified path out of the name given //-------------------------------------------------------------------- lstrcpy (partial, lpszLogName); _fullpath (pathbuf, partial, _MAX_PATH); OutDebug (pathbuf); OutDebug ("\r\n"); // See if the file exists/can exist (is a valid file name) //-------------------------------------------------------------------- if ((fh = M_lopen(pathbuf, OF_READ)) == -1) if ( (fh= M_lcreat(pathbuf, 0)) == -1) return ErrorTrap(WCT_TMPFILEERR); // The file given is okay to write to - copy it to local space and // let the user know that there is no problem //-------------------------------------------------------------------- M_lclose(fh); lstrcpy (szLogName, pathbuf); return ErrorTrap(WCT_NOERR); } //*----------------------------------------------------------------------- //| SetDialogFile //| //| PURPOSE: Set the name of the dialog file, the source of comparisons //| //| //*----------------------------------------------------------------------- INT FARPUBLIC SetDialogFile (LPSTR lpszDialogName) { INT fh, cDialogs; static CHAR pathbuf[_MAX_PATH]; static CHAR partial[_MAX_PATH]; // Create a fully-specified path out of the name given //---------------------------------------------------------------- lstrcpy (partial, lpszDialogName); _fullpath (pathbuf, partial, _MAX_PATH); OutDebug (pathbuf); OutDebug ("\r\n"); // See if a file of this name exists -- if not, try to create it //---------------------------------------------------------------- if ( (fh=M_lopen(pathbuf, OF_READ)) == -1) if ( (fh=M_lcreat(pathbuf, 0)) == -1) return ErrorTrap(WCT_DLGFILEERR); else { M_lclose(fh); lstrcpy (szDialogName, pathbuf); fDialogSet = TRUE; nDlgsInFile = 0; remove (pathbuf); return ErrorTrap(WCT_NOERR); } // Check to see if this file is a valid WCT file. If so, // fGetCountDialogs returns the number of dialogs in the file. //---------------------------------------------------------------- M_lclose(fh); if ( (cDialogs = fGetCountDialogs (pathbuf)) < 0) return NoTrap(cDialogs);// Valid return, no Trapping is done // The file is a valid WCT file - copy name to local space, and // return count of dialogs //---------------------------------------------------------------- lstrcpy (szDialogName, pathbuf); fDialogSet = TRUE; nDlgsInFile = cDialogs; return NoTrap(cDialogs); // Valid return, no Trapping is done } //*----------------------------------------------------------------------- //| DynCreate //| //| PURPOSE: Create a dynamic dialog. All this really does is allocate //| a block of 5 (to start with) controls, making sure not to //| reallocate the block if it's already present. //| //*----------------------------------------------------------------------- INT FARPUBLIC DynCreate() { // If there's something in the dynamic dialog, don't deallocate, // but set the count to 0 and we're done! //---------------------------------------------------------------- nDynCount = 0; if (hDynDialog) return ErrorTrap(WCT_NOERR); // We must allocate from scratch - make room for 5 controls to // start with - return WCT_OUTOFMEMORY if fInitBlock fails //---------------------------------------------------------------- if (fInitBlock(&hDynDialog, 5) != WCT_NOERR) { hDynDialog = NULL; return ErrorTrap(WCT_OUTOFMEMORY); } return ErrorTrap(WCT_NOERR); } //*----------------------------------------------------------------------- //| DynFullDialog //| //| PURPOSE: Set the "Full Dialog" property of the dynamic dialog //| //| //*----------------------------------------------------------------------- INT FARPUBLIC DynFullDialog (INT fFull) { // Check to see if a dynamic dialog exists. If not, return an // error code indicating so (WCT_NODYNDIALOG) //---------------------------------------------------------------- if (!hDynDialog) return ErrorTrap(WCT_NODYNDIALOG); // fFullDynDlg is a factor of the dynamic dialog count when passed // to the comparison routine -- if the count is negative, it is // assumed that the dynamic dialog is a full dialog; if positive, // it is not. Thus, depending on fFull, fFullDynDlg is set to // either 1 or -1. //---------------------------------------------------------------- fFullDynDlg = (fFull ? -1 : 1); return ErrorTrap(WCT_NOERR); } //*----------------------------------------------------------------------- //| DynAdd //| //| PURPOSE: Adds a control to the dynamic dialog. //| //| //*----------------------------------------------------------------------- INT FARPUBLIC DynAdd (LPCTLDEF Ctl) { // Make sure the dynamic dialog has been created - if not, tell // the user he's an idiot //---------------------------------------------------------------- if (!hDynDialog) return ErrorTrap(WCT_NODYNDIALOG); // Add the user's control to the list - GOTCHA: check to see if // the control to be added is the same kind as those already in // the list (menu vs. other control info). This is done by // checking the value of fDynMenu -- if TRUE, that means the first // control added to the list was a menu type, which means that // ONLY menu types can be added from this point on, and vice versa. //---------------------------------------------------------------- if (nDynCount == 0) { // As above, the first dialog added to the list is a // special case - if it can be either menu or some other // kind of control - but the fDynMenu flag gets set here //-------------------------------------------------------- if (!lstrcmpi (Ctl->rgClass, "MenuItem")) fDynMenu = TRUE; else fDynMenu = FALSE; } else { // Here, the class name of the control to be added is // checked -- if it is "MenuItem", and fDynMenu is true, // then the control can be added, as well as if the class // name is NOT "MenuItem" and fDynMenu if false. If both // cases fail, we return WCT_BADCTLTYPE. //-------------------------------------------------------- if (!lstrcmpi (Ctl->rgClass, "MenuItem")) if (!fDynMenu) return ErrorTrap(WCT_BADCTLTYPE); else; else if (fDynMenu) return ErrorTrap(WCT_BADCTLTYPE); } // Okay, this is a valid add. Insert the control and return the // success/failure of the add operation. //---------------------------------------------------------------- return ErrorTrap(fAddCtl (hDynDialog, Ctl, &nDynCount)); } //*----------------------------------------------------------------------- //| DynDelete //| //| PURPOSE: Deletes a control from the dynamic dialog. //| //| NOTE: nCtlNum is 1-based //*----------------------------------------------------------------------- INT FARPUBLIC DynDelete (INT nCtlNum) { // Check to see that a dynamic dialog exists //---------------------------------------------------------------- if (!hDynDialog) return ErrorTrap(WCT_NODYNDIALOG); // Verify that the given index is within the number of controls in // the dynamic dialog (note that this also ensures that there is // at least one control in the dialog to delete) //---------------------------------------------------------------- if ( (nCtlNum < 1) || (nCtlNum > nDynCount) ) return ErrorTrap(WCT_BADCTLINDEX); // Delete the control and return the success of the call //---------------------------------------------------------------- return ErrorTrap(fDelCtl(hDynDialog, nCtlNum, &nDynCount)); } //*----------------------------------------------------------------------- //| DynReplace //| //| PURPOSE: Replaces a control in the dynamic dialog with the given //| control. //| //*----------------------------------------------------------------------- INT FARPUBLIC DynReplace (LPCTLDEF Ctl, INT nCtlNum) { // Make sure the dynamic dialog has been created - if not, tell // the user he's an idiot //---------------------------------------------------------------- if (!hDynDialog) return ErrorTrap(WCT_NODYNDIALOG); // Verify that the given index is within range (note - this also // ensures that there is at least one control in the dialog) //---------------------------------------------------------------- if ( (nCtlNum < 1) || (nCtlNum > nDynCount) ) return ErrorTrap(WCT_BADCTLINDEX); // Insert the user's control to the list - GOTCHA: check to see if // the to-be-inserted control is the same kind as those already in // the list (menu vs. other control info). This is done by // checking the value of fDynMenu -- if TRUE, that means the first // control added to the list was a menu type, which means that // ONLY menu types can be added from this point on, and vice versa. //---------------------------------------------------------------- if (!lstrcmpi (Ctl->rgClass, "MenuItem")) if (!fDynMenu) return ErrorTrap(WCT_BADCTLTYPE); else; else if (fDynMenu) return ErrorTrap(WCT_BADCTLTYPE); // It's safe - replace the control with the new one //---------------------------------------------------------------- return ErrorTrap(fRepCtl (hDynDialog, Ctl, nCtlNum, &nDynCount)); } //*----------------------------------------------------------------------- //| DynDestroy //| //| PURPOSE: Destroy the dynamic dialog, freeing up all memory it uses. //| //| //*----------------------------------------------------------------------- VOID FARPUBLIC DynDestroy () { // If hDynDialog is NOT NULL, free it //---------------------------------------------------------------- if (hDynDialog) GlobalFree (hDynDialog); hDynDialog = NULL; } //*----------------------------------------------------------------------- //| DoSave //| //| PURPOSE: Save dialog/menu information out to the dialog file //| //*----------------------------------------------------------------------- INT FARPUBLIC DoSave (HANDLE hCtls, INT nCount, LPSTR szDesc, INT nDialog, INT fReplace) { INT i, nAction; LPSTR lpCtls; // Lock down the array for the save operation //---------------------------------------------------------------- lpCtls = (LPSTR)GlobalLock (hCtls); if (!lpCtls) return (WCT_OUTOFMEMORY); // Make any last minute adjustments to parameters such as nDialog // and nAction //---------------------------------------------------------------- if ( (nDialog <= 0) || (nDialog > nDlgsInFile) ) { nAction = Insert; nDialog = nDlgsInFile + 1; } else nAction = (fReplace ? Replace : Insert); // Make the save call //---------------------------------------------------------------- i = fSaveDialog (szDialogName, lpCtls, nCount, szDesc, fFullDynDlg, nAction, nDialog); // Check result of save, modify global dialog count, return //---------------------------------------------------------------- GlobalUnlock (hCtls); if (i != WCT_NOERR) return (WCT_SAVEERR); if (nAction == Insert) nDlgsInFile++; return (WCT_NOERR); } //*----------------------------------------------------------------------- //| SaveCommon //| //| PURPOSE: Save child window (optionally parent) information to the //| dialog file at the given position. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveCommon (HWND hWnd, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent) { HANDLE hCtls; INT nCount=0, fFreeBlock, fSuccess, fRetVal; CHAR szCaption [24]; CHAR szNewDesc [32]; // It is required, regardless if saving the dynamic dialog or a // real window, that the dialog file be set prior to any save // function calls. //---------------------------------------------------------------- if (!fDialogSet) return (WCT_NODLGFILE); // First check is to see if this is a dynamic dialog save or not. // The differences between the two are big enough to be split // completely apart. //---------------------------------------------------------------- if (IsWindow (hWnd)) { // We are saving a real window. This means we have to // fill in a new array of control information. First, we // allocate a block with positive size, and return an // error code on failure //-------------------------------------------------------- if (fInitBlock (&hCtls, 1) != WCT_NOERR) return (WCT_OUTOFMEMORY); fFreeBlock = TRUE; // Use fPumpHandleForInfo to put all of the controls in // the new block, return error code on failure //-------------------------------------------------------- if (fRetVal = fPumpHandleForInfo (hWnd, hCtls, &nCount, nSaveOp)) { GlobalFree (hCtls); return (fRetVal); } // If fIncludeParent, add the parent as a control to the // list //-------------------------------------------------------- if (fIncludeParent) if (fRetVal = fAddControlToList (hWnd, hCtls, &nCount, NULL)) { GlobalFree (hCtls); return (fRetVal); } } else { // This is a dynamic dialog save. Make sure that the hWnd // passed in as actually NULL, otherwise tell the user // that the handle passed in is not a real window //-------------------------------------------------------- if (hWnd) return (WCT_INVALIDHWND); // Make sure a dynamic dialog has been created. //-------------------------------------------------------- else if (!hDynDialog) return (WCT_NODYNDIALOG); nCount = nDynCount; hCtls = hDynDialog; fFreeBlock = FALSE; } if (!lpszDesc) { GetWindowText (hWnd, szCaption, sizeof (szCaption)); wsprintf (szNewDesc, "%s", (LPSTR) szCaption); lpszDesc = szNewDesc; } // Time to perform the save //-------------------------------------------------------- fSuccess = DoSave(hCtls, nCount, lpszDesc, nDialog, fReplace); if (fFreeBlock) GlobalFree (hCtls); return (fSuccess); } //*----------------------------------------------------------------------- //| SaveCommonCaption //| //| PURPOSE: Save child window (optionally parent) information to the //| dialog file at the given position. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveCommonCaption (LPSTR lpszCaption, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent) { HANDLE hCtls; HWND hWnd; INT nCount=0, fSuccess, fRet; // It is required that the dialog file be set prior to any save // function calls. //---------------------------------------------------------------- if (!fDialogSet) return (WCT_NODLGFILE); // Get the window with the given caption, or the active window // if lpszCaption is NULL //---------------------------------------------------------------- if (lpszCaption) hWnd = FindWindowCaption (lpszCaption, GetDesktopWindow()); else hWnd = GetActiveWindow(); if ( (lpszCaption) && (!hWnd) ) return (WCT_BADCAPTION); // Fill in a new array of control information. First, we allocate // a block with positive size, and return an error code on failure //---------------------------------------------------------------- if (fInitBlock (&hCtls, 1) != WCT_NOERR) return (WCT_OUTOFMEMORY); // Use fPumpHandleForInfo to put all of the controls in // the new block, return error code on failure //-------------------------------------------------------- if (fRet = fPumpHandleForInfo (hWnd, hCtls, &nCount, nSaveOp)) { GlobalFree (hCtls); return (fRet); } // If fIncludeParent, add the parent as a control to the // list //-------------------------------------------------------- if (fIncludeParent) if (fRet = fAddControlToList (hWnd, hCtls, &nCount, NULL)) { GlobalFree (hCtls); return (fRet); } // Time to perform the save //-------------------------------------------------------- fSuccess = DoSave(hCtls, nCount, lpszDesc, nDialog, fReplace); GlobalFree (hCtls); return (fSuccess); } //*----------------------------------------------------------------------- //| SaveCommonActivate //| //| PURPOSE: Save child window (optionally parent) information to the //| dialog file at the given position. Optionally activate //| and close the window before/after the save. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveCommonActivate (LPSTR OpenKeys, LPSTR CloseKeys, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent) { HANDLE hCtls; HWND hWnd; INT nCount=0, fSuccess; // It is required that the dialog file be set prior to any save // function calls. //---------------------------------------------------------------- if (!fDialogSet) return (WCT_NODLGFILE); // Load TESTEVT.DLL, and return error code if can't do it //---------------------------------------------------------------- if (LoadTESTEVT()) return (WCT_LIBLOADERR); // If not NULL, send the SendKeys string OpenKeys //---------------------------------------------------------------- if (OpenKeys) { DoKeys (OpenKeys); /* do some yields to allow keys to get to app and some time ** for it to respond. */ #ifdef WIN32 Sleep (500); #else yield(); yield(); yield(); yield(); yield(); #endif } // Get the active window //---------------------------------------------------------------- hWnd = GetActiveWindow(); // Fill in a new array of control information. First, we allocate // a block with positive size, and return an error code on failure //---------------------------------------------------------------- if (fSuccess = fInitBlock (&hCtls, 1)) return (fSuccess); // Use fPumpHandleForInfo to put all of the controls in // the new block, return error code on failure //---------------------------------------------------------------- if (fSuccess = fPumpHandleForInfo (hWnd, hCtls, &nCount, nSaveOp)) { GlobalFree (hCtls); return (fSuccess); } // If fIncludeParent, add the parent as a control to the list //---------------------------------------------------------------- if (fIncludeParent) if (fSuccess = fAddControlToList (hWnd, hCtls, &nCount, NULL)) { GlobalFree (hCtls); return (fSuccess); } // Time to perform the save //---------------------------------------------------------------- fSuccess = DoSave(hCtls, nCount, lpszDesc, nDialog, fReplace); GlobalFree (hCtls); // If not NULL, send the SendKeys string CloseKeys //---------------------------------------------------------------- if (CloseKeys) DoKeys (CloseKeys); // Unload the TESTEVT library //---------------------------------------------------------------- FreeTESTEVT(); // Return the success/failure of the save operation //---------------------------------------------------------------- return (fSuccess); } //*----------------------------------------------------------------------- //| DoDelaySaveCommon //| //| PURPOSE: Performed the delayed save operation //| //*----------------------------------------------------------------------- WORD APIENTRY DoDelaySaveCommon (HWND hW, WORD wMsg, INT nIDEvent, DWORD dwTime) { HANDLE hCtls; HWND hWnd; INT nCount=0, fSuccess; // First thing we do is kill the timer - we don't want it going // off again... //---------------------------------------------------------------- if (!KillTimer (NULL, SaveTimer)) MessageBox (NULL, "KillTimer failed", "Oh NO", MB_OK); // Grab the active window //---------------------------------------------------------------- hWnd = GetActiveWindow(); // Fill in a new array of control information. First, we allocate // a block with positive size, and return an error code on failure //---------------------------------------------------------------- if (fSuccess = fInitBlock (&hCtls, 1)) return (fSuccess); // Use fPumpHandleForInfo to put all of the controls in // the new block, return error code on failure //---------------------------------------------------------------- if (fSuccess = fPumpHandleForInfo (hWnd, hCtls, &nCount, nSaveOp)) { GlobalFree (hCtls); return (fSuccess); } // If fIncPar, add the parent as a control to the list //---------------------------------------------------------------- if (fIncPar) if (fSuccess = fAddControlToList (hWnd, hCtls, &nCount, NULL)) { GlobalFree (hCtls); return (fSuccess); } // Time to perform the save. //---------------------------------------------------------------- nSaveRes = DoSave(hCtls, nCount, szSaveDesc, nDynNumber, fRep); GlobalFree (hCtls); // If not NULL, send the SendKeys string CloseKeys //---------------------------------------------------------------- if (szClose) DoKeys (szClose); // Unload the TESTEVT library //---------------------------------------------------------------- FreeTESTEVT(); fSavePending = FALSE; return 0; } //*----------------------------------------------------------------------- //| SaveCommonDelayed //| //| PURPOSE: Save child window (optionally parent) information to the //| dialog file at the given position. Wait a given time, and //| optionally close the window after the save. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveCommonDelayed (INT nDelay, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent, LPSTR CloseKeys) { MSG msg; // For the CompareDelayed and SaveDelayed functions, we must make // sure that one is not pending before calling another //-------------------------------------------------------------------- while (fCompPending) { if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); } } // It is required that the dialog file be set prior to any save // function calls. //-------------------------------------------------------------------- if (!fDialogSet) return (WCT_NODLGFILE); // Load TESTEVT.DLL, and return error code if can't do it //-------------------------------------------------------------------- if (LoadTESTEVT()) return (WCT_LIBLOADERR); // Store all the parameters in local storage so the timer routine // knows what data to use //-------------------------------------------------------------------- nDynNumber = nDialog; fIncPar = fIncludeParent; _fstrncpy (szClose, CloseKeys, 127); szClose [127] = '\0'; fRep = fReplace; _fstrncpy (szSaveDesc, lpszDesc, 127); szSaveDesc [127] = '\0'; // Set the timer and leave //-------------------------------------------------------------------- SaveTimer = SetTimer (NULL, SAVETIMER, nDelay * 1000, (TIMERPROC) DoDelaySaveCommon); if (!SaveTimer) return (WCT_NOTIMER); fSavePending = TRUE; return (WCT_NOERR); } //*----------------------------------------------------------------------- //| SaveMenu //| //| PURPOSE: Save menu information to the dialog file at the given //| position. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveMenu (HWND hWnd, INT nDialog, LPSTR lpszDesc, INT fReplace) { if( FWinExceptNULLTrap( hWnd ) ) return ErrorTrap(WCT_INVALIDHWND); nSaveOp = PUMP_MENU; return ErrorTrap(SaveCommon (hWnd, nDialog, lpszDesc, fReplace, FALSE)); } //*----------------------------------------------------------------------- //| SaveWindow //| //| PURPOSE: Save window information to the dialog file at the given //| position. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveWindow (HWND hWnd, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent) { if( FWinExceptNULLTrap( hWnd ) ) return ErrorTrap(WCT_INVALIDHWND); nSaveOp = PUMP_ALL; return ErrorTrap(SaveCommon(hWnd, nDialog, lpszDesc, fReplace, fIncludeParent)); } //*----------------------------------------------------------------------- //| SaveMenuCaption //| //| PURPOSE: Save menu information to the dialog file at the given //| position. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveMenuCaption (LPSTR lpszCaption, INT nDialog, LPSTR lpszDesc, INT fReplace) { nSaveOp = PUMP_MENU; return ErrorTrap(SaveCommonCaption (lpszCaption, nDialog, lpszDesc, fReplace, FALSE)); } //*----------------------------------------------------------------------- //| SaveWindowCaption //| //| PURPOSE: Save child window (optionally parent) information to the //| dialog file at the given position. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveWindowCaption (LPSTR lpszCaption, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent) { nSaveOp = PUMP_ALL; return ErrorTrap(SaveCommonCaption (lpszCaption, nDialog, lpszDesc, fReplace, fIncludeParent)); } //*----------------------------------------------------------------------- //| SaveMenuActivate //| //| PURPOSE: Save menu information to the dialog file at the given //| position. Optionally activate and close the window //| before/after the save. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveMenuActivate (LPSTR OpenKeys, LPSTR CloseKeys, INT nDialog, LPSTR lpszDesc, INT fReplace) { nSaveOp = PUMP_MENU; return ErrorTrap(SaveCommonActivate (OpenKeys, CloseKeys, nDialog, lpszDesc, fReplace, FALSE)); } //*----------------------------------------------------------------------- //| SaveWindowActivate //| //| PURPOSE: Save child window (optionally parent) information to the //| dialog file at the given position. Optionally activate //| and close the window before/after the save. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveWindowActivate (LPSTR OpenKeys, LPSTR CloseKeys, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent) { nSaveOp = PUMP_ALL; return ErrorTrap(SaveCommonActivate (OpenKeys, CloseKeys, nDialog, lpszDesc, fReplace, fIncludeParent)); } //*----------------------------------------------------------------------- //| SaveMenuDelayed //| //| PURPOSE: Save menu information to the dialog file at the given //| position. Wait a given time, and optionally close the //| window after the save. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveMenuDelayed (INT nDelay, INT nDialog, LPSTR lpszDesc, INT fReplace, LPSTR CloseKeys) { nSaveOp = PUMP_MENU; return ErrorTrap(SaveCommonDelayed (nDelay, nDialog, lpszDesc, fReplace, FALSE, CloseKeys)); } //*----------------------------------------------------------------------- //| SaveWindowDelayed //| //| PURPOSE: Save child window (optionally parent) information to the //| dialog file at the given position. Wait a given time, and //| optionally close the window after the save. //| //*----------------------------------------------------------------------- INT FARPUBLIC SaveWindowDelayed (INT nDelay, INT nDialog, LPSTR lpszDesc, INT fReplace, INT fIncludeParent, LPSTR CloseKeys) { nSaveOp = PUMP_ALL; return ErrorTrap(SaveCommonDelayed (nDelay, nDialog, lpszDesc, fReplace, fIncludeParent, CloseKeys)); } //*----------------------------------------------------------------------- //| ComparisonResults //| //| PURPOSE: Returns the results of the latest (or pending) comparison. //| If one is pending, will await its completion. //| //*----------------------------------------------------------------------- INT FARPUBLIC ComparisonResults() { MSG msg; // Loop until the fCompPending flag is cleared //-------------------------------------------------------------------- while (fCompPending) { if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); } } // Now, simply return the comparison results //-------------------------------------------------------------------- return ErrorTrap(nCompRes); } //*----------------------------------------------------------------------- //| MaxDialogs //| //| PURPOSE: Returns the maximum number of dialogs that can be stored //| in a WCT dialog file. //| //*----------------------------------------------------------------------- INT FARPUBLIC MaxDialogs() { return (cdlgMax); } //*----------------------------------------------------------------------- //| AwaitSaveCompletion //| //| PURPOSE: Does nothing until the fSavePending flag is cleared, thus //| awaiting the completion of a delayed save operation. //| //*----------------------------------------------------------------------- INT FARPUBLIC AwaitSaveCompletion() { MSG msg; // Loop until the fSavePending flag is cleared //-------------------------------------------------------------------- while (fSavePending) { if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); } } // Now, simply return the save results //-------------------------------------------------------------------- return (nSaveRes); } //*----------------------------------------------------------------------- //| LoadWindow //| //| PURPOSE: Load a window from the dialog file into the dynamic dialog //| //| //| //*----------------------------------------------------------------------- INT FARPUBLIC LoadWindow (INT nDialog) { INT retval, fFull, nCount; CHAR szDesc[cchMaxDsc]; LPSTR lpCtls; // First, create a dynamic dialog - destroying one if it // already exists //---------------------------------------------------------------- if (retval = DynCreate()) return ErrorTrap(retval); // Make sure the index given is a real one //---------------------------------------------------------------- if ((nDialog > nDlgsInFile) || (nDialog < 1)) return ErrorTrap(WCT_BADDLGNUM); // Get the information about the dialog, including number of // controls and the Full-Dialog flag //---------------------------------------------------------------- retval = fDialogInfo (szDialogName, nDialog, szDesc, &nCount, &fFull); if (retval) return ErrorTrap(retval); // Allocate the dynamic dialog control array. Add one to nCount // in case there are 0 controls in the saved dialog //---------------------------------------------------------------- retval = fInitBlock (&hDynDialog, nCount+1); if (retval) { hDynDialog = NULL; return ErrorTrap(retval); } // Read the control information from the dialog file //---------------------------------------------------------------- lpCtls = (LPSTR)GlobalLock (hDynDialog); if (!lpCtls) { GlobalFree (hDynDialog); hDynDialog = NULL; return ErrorTrap(WCT_OUTOFMEMORY); } retval = fGetControls (szDialogName, nDialog, (WORD) (nCount * sizeof(CTLDEF)), lpCtls); GlobalUnlock (hDynDialog); if (retval<0) { GlobalFree (hDynDialog); hDynDialog = NULL; return ErrorTrap(retval); } nDynCount = nCount; return ErrorTrap(WCT_NOERR); } //*----------------------------------------------------------------------- //| GetDynDlgHandle //| //| PURPOSE: Return the handle to the dynamic dialog control array //| //*----------------------------------------------------------------------- INT FARPUBLIC GetDynDlgHandle (HANDLE FAR *hDyn) { if (hDynDialog) { *hDyn = hDynDialog; return ErrorTrap(WCT_NOERR); } return ErrorTrap(WCT_NODYNDIALOG); } //*----------------------------------------------------------------------- //| GetDlgControlCount //| //| PURPOSE: Return the number of controls in the specified dialog //| //*----------------------------------------------------------------------- INT FARPUBLIC GetDlgControlCount (INT nDialog) { CHAR szDsc[cchMaxDsc]; INT nSourceCount = 0; INT fFullDlg; if (nDialog == 0) { if (!hDynDialog) return ErrorTrap(WCT_NODYNDIALOG); else // nDynCount is the number of controls in the dynamic dialog //---------------------------------------------------------- return NoTrap(nDynCount); } else { // Make sure the index given is okay //---------------------------------- if ((nDialog > nDlgsInFile) || (nDialog <= 0)) return ErrorTrap(WCT_BADDLGNUM); // Get the number of controls in the dialog //----------------------------------------- if( fDialogInfo(szDialogName, nDialog, (LPSTR)szDsc, (INT FAR *)&nSourceCount, (INT FAR *)&fFullDlg) != WCT_NOERR) { OutDebug ("Unable to get dialog information"); return ErrorTrap(WCT_OUTOFMEMORY); } } return NoTrap( nSourceCount ); // return a valid result - no trapping } //--------------------------------------------------------------------- // WATTDRVR TRAP ROUTINES //--------------------------------------------------------------------- // Determine if the window is enabled and visible INT PRIVATE FBadWindow(hwnd) HWND hwnd; { return(!IsWindowEnabled(hwnd) || !IsWindowVisible(hwnd)); } /****************************************************************************** * PURPOSE: This is called by all routines which need to check the validity * * of a window, generating a trap if the window is invalid. * * RETURN: TRUE if a trap was generated, FALSE otherwise. * * GLOBALS: WINTrapCallBack and vWINTrapID and fIgnoreEvntErrTrap * ******************************************************************************/ BOOL PRIVATE FWinExceptNULLTrap( HWND hWnd ) { if( WINTrapCallBack != NULL ) { if( ( hWnd != NULL ) && FBadWindow(hWnd) ) { WINTrapCallBack(vWINTrapID); fIgnoreEvntErrTrap = TRUE; return TRUE; } } return FALSE; } /****************************************************************************** * PURPOSE: This is called by WattDrvr when a script includes a * * WindowMissing Trap, to turn on that trapping support. * * RETURN: Nothing * * GLOBALS: WINTrapCallBack and vWINTrapID * ******************************************************************************/ VOID FARPUBLIC WDLG_WindowMissing(INT TrapID, INT Action, TrapCallBack CallBack) { if( Action == 0 ) WINTrapCallBack = NULL; else { vWINTrapID = TrapID; WINTrapCallBack = CallBack; } } /****************************************************************************** * PURPOSE: This is a substitute for the routine ErrorTrap - functions * which return non-zero values, but which are not Errors, should * call this instead * RETURN: Value that was passed to it * GLOBALS: fIgnoreEvntErrTrap ******************************************************************************/ INT PRIVATE NoTrap( INT n ) // just for cleanup purposes { fIgnoreEvntErrTrap = FALSE; return n; } /****************************************************************************** * PURPOSE: This is called by all PUBLIC routines which return values that * * could be Errors, so that the trap can be generated if required. * * If a Window trap was already generated, this one will not be. * * RETURN: The value passed in - to be passed on to the WTD script * * GLOBALS: ERRTrapCallBack and vERRTrapID and fIgnoreEvntErrTrap * ******************************************************************************/ INT PRIVATE ErrorTrap( INT n ) { if( ( ERRTrapCallBack != NULL ) && n && !fIgnoreEvntErrTrap ) if( (n <= WCT_FIRSTREALERROR) || (n > WCT_NOERR ) ) ERRTrapCallBack(vERRTrapID); // if( ( DIFFTrapCallBack != NULL ) && ((n > WCT_FIRSTREALERROR)&&(n < WCT_NOERR) ) ) // DIFFTrapCallBack(vDIFFTrapID); fIgnoreEvntErrTrap = FALSE; return n; } /****************************************************************************** * PURPOSE: This is called by WattDrvr when a script includes * * Error Trap support, to turn on that trap. * * RETURN: Nothing * * GLOBALS: ERRTrapCallBack and vERRTrapID * ******************************************************************************/ VOID FARPUBLIC WDLG_EventError(INT TrapID, INT Action, TrapCallBack CallBack) { if( Action == 0 ) ERRTrapCallBack = NULL; else { vERRTrapID = TrapID; ERRTrapCallBack = CallBack; } }