*-------------------------------------------------------------------------------------------------------------------------------------------------------- * (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!! *-------------------------------------------------------------------------------------------------------------------------------------------------------- *< FOXBIN2PRG: Version="1.21" SourceFile="_framewk.vcx" CPID="1252" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries) * * DEFINE CLASS _aboutbox AS _dialog OF "_framewk.vcx" && superclass for framework-supplied default about box *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="cmdOK" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="imgApplication" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblApplicationName" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblCredits" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: applyattributestodialogelements && Called in ApplyAppAttributes(), after this method has transferred app "credits" information to dialog property values, so you can apply these attributes to the visual elements of the dialog. *p: cauthor *p: ccaption *p: ccompany *p: ccopyright *p: cimage *p: ctrademark * * Caption = "About Application" cauthor = ccaption = ccompany = ccopyright = cimage = ctrademark = cversion = DoCreate = .T. Height = 218 Name = "_aboutbox" Width = 367 * ADD OBJECT 'cmdOK' AS _commandbutton WITH ; AutoSize = .F., ; Caption = "\ ADD OBJECT 'imgApplication' AS _image WITH ; BackStyle = 0, ; Height = 72, ; Left = 14, ; Name = "imgApplication", ; Stretch = 1, ; Top = 12, ; Width = 90 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="image" /> ADD OBJECT 'lblApplicationName' AS _label WITH ; Alignment = 2, ; AutoSize = .F., ; Caption = "Application Name", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 31, ; Left = 116, ; Name = "lblApplicationName", ; Top = 12, ; Width = 237 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'lblCredits' AS _label WITH ; Alignment = 2, ; AutoSize = .F., ; Caption = "Credits", ; FontName = "MS Sans Serif", ; Height = 127, ; Left = 116, ; Name = "lblCredits", ; Top = 48, ; Width = 237 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> PROCEDURE applyappattributes LPARAMETERS toApp IF DODEFAULT(toApp) * parent dialog class is already setting Icon THIS.Caption = ABOUT_LOC+" "+TRANS(toApp.cCaption) THIS.cCaption = TRANS(toApp.cCaption) THIS.cVersion = TRANS(toApp.cVersion) THIS.cCopyright = TRANS(toApp.cCopyright) THIS.cCompany = TRANS(toApp.cCompany) THIS.cAuthor = TRANS(toApp.cAuthor) THIS.cTrademark = TRANS(toApp.cTrademark) THIS.cImage = TRANS(toApp.cImage) ENDIF THIS.ApplyAttributesToDialogElements() ENDPROC PROCEDURE applyattributestodialogelements && Called in ApplyAppAttributes(), after this method has transferred app "credits" information to dialog property values, so you can apply these attributes to the visual elements of the dialog. IF PEMSTATUS(THIS,"imgApplication",5) IF (NOT EMPTY(THIS.cImage)) AND ; (FILE(THIS.cImage)) THIS.imgApplication.Visible = .T. THIS.imgApplication.Picture = THIS.cImage ELSE THIS.imgApplication.Visible = .F. ENDIF ENDIF IF PEMSTATUS(THIS,"lblApplicationName",5) THIS.lblApplicationName.Caption = THIS.cCaption ENDIF IF PEMSTATUS(THIS,"lblCredits",5) THIS.lblCredits.Caption = THIS.cAuthor THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; THIS.cCompany THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; THIS.cCopyright THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; THIS.cTrademark THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; THIS.cVersion ENDIF ENDPROC PROCEDURE cmdOK.Click THISFORM.Release() ENDPROC ENDDEFINE DEFINE CLASS _application AS _container OF "..\ffc\_base.vcx" && application object superclass *< CLASSDATA: Baseclass="container" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="cusError" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cusDataSession" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cusWindowHandler" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cusTableSort" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cusTableNav" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="tmrRefresh" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: activate && Makes the application active *m: activateforminframe && Takes a form or toolbar reference and fixes it to appear in top form "frame" even if its ShowWindow property was 0 *m: activatesystemwindow && Activates a system window whose name has been passed, in _SCREEN, even if _SCREEN wasn't previously visible (for debugging, does nothing in runtime) *m: addcollaborator && Instantiate objects that can't be part of application container and add a reference to collaborators collection for maintenance. See SetScreenAttributes() for examples. *m: addmediatedsession && Creates a data session with a mediator object attached, referenced in the aCollaborators collection, returns a reference to this framework-enabled session. *m: applyglobaluseroptions && Applies global (non-datasession-specific) options to the _application object and environment. Where user login and preferences are not used, applies a single set at startup -- with user login and preferences, applies to each user login. *m: applyuseroptsforsession && Applies datasession-specific options a form object and its session environment. *m: beforedoform && Hook in DoForm method, allowing last-minute manipulation of environment before the form class or object is instantiated. *m: beforereadevents && Method executed before READ EVENTS is executed when ReadEvents is called. *m: caboutboxclass_access && Synchronizes classname value with lAboutBox value *m: cappfolder_access && Determines the application folder, usually the folder containing the running APP or EXE. However where a temporary wrapper program or ON... command has been used to instantiate the application, this value may be the location of the VCX *m: cascadeall && Wraps cusWindowHandler's CascadeFormInstances() method, passing no argument. *m: cascadeform && For backwards compatibility, not used *m: ccaption_access *m: ccaption_assign *m: cdatafolder_assign *m: cerrorlogtablename_access && adds cAppFolder information to the error log table name, so the default error DBF is always in one place. *m: checkpassword && Sends a passed value and a stored value from the current user information to CheckValueAgainstStoredPassword for verification. *m: checkvalueagainststoredpassword && Compares a current password entry against an encrypted stored entry. Separated from CheckPassword so its simple algorithm can be replaced as necessary. Algorithms in CreateStoredPassword and CheckValueAgainstStoredPassword should match. *m: cicon_assign *m: cimage_assign && Verifies the availability of an image file for use as the application logo *m: clearevents && Clears any pending read events. *m: clearfavorites && Called by Favorites menu item, to confirm "zap" of user favorites and invoke SetCurrentUserFavoriteIDs mechanism. *m: clearlasterror && Sets _application.iLastError to NULL, called before operations which may require an error to be tested on conclusion. Abstracted for easy overriding in subclasses. *m: createcollaborators && A startup hook to allow you to call the AddCollaborators() method during initialization procedures *m: createformmediator && Adds a app mediator object to a form *m: createframe && Creates the MDI frame for top form applications. *m: createstoredpassword && Creates an encrypted value of a password. Separated from StorePassword() for easy replacement of its simple algorithm. Algorithms in CreateStoredPassword and CheckValueAgainstStoredPassword should match. *m: createusertable && Creates and indexs user table when it does not exist. Abstracted for easy editing. The app expects this table to have 1 c-type field, with its name in the cUserTableIDField property, and 1 i-type field, its name in cUserTableLevelField. *m: creference_assign *m: cstartupformclass_access && Synchronizes classname value with lStartupForm value *m: cstartuptoolbarclass_access && Synchronizes classname value with lStartupToolbar value *m: ctextdisplayfont_assign *m: cusertablealias_assign *m: cusertablename_access *m: datarevert && Wraps cusDataSession's Revert() method. *m: dataupdate && Wraps cusDataSession's Update() method. *m: displayerrorlog && Instantiates cErrorViewerClass dialog *m: doaboutbox && Invokes cAboutBoxClass dialog class *m: dochangepassword && Invokes cChangePasswordClass dialog class *m: docontextmenu && Manages context menus and context menu collection *m: dodocumentpickerdialog && Invokes all the dialogs descending from the _documentpicker dialog superclass *m: dofile && Executes files, channelling known FoxPro-type files to appropriate application Do... methods, and files of unknown types through Windows API *m: doform && Executes an SCX form or instantiates a VCX-based form/formset class. *m: doformnoshow && Executes an SCX form or instantiates a VCX-based form/formset class, without Showing it, and returning a reference to the form or formset instantiated. *m: dohelp && Executes help of types .hlp, .dbf, .htm, or .chm *m: dolabel && Executes an LBX label *m: domenu && Executes an MPR/MPX menu. *m: domenuiteminframe && Not currently used, wraps cusWindowHandler method *m: domodaldialogclass && Instantiates a modal dialog, applying application attributes as appropriate. RETURNs a form reference, if NOSHOW. *m: donewopen && Invokes cNewOpenClass *m: dooptionsdialog && Invokes cOptionsDialogClass *m: doprogram && Executes a PRG, APP, FXP, or EXE program. *m: doreport && Executes an FRX or LBX report form. *m: doreportdialog && Invokes cReportDialogClass *m: dosort && Wraps cusTableSort's DoSort() method. *m: dostartupform && Instantiates cStartupFormClass dialog *m: dotableoutput && Looks at the current form/alias and invokes the _outputdialog class appropriately for a table. Scope 1 or all. Hooks mediator's PrepareOutputAlias() and CleanupOutputAlias(), for framework-enabled forms, and app.SetHTMLClass/SetHTMLStyleID for GENHTML. *m: dotoolbar && Parallel to DoForm. Maintains toolbars collection. Pass a toolbar class library & class name. Uses THIS.iInitialToolbarPosition to set position. *m: douserlogin && Invokes cUserLoginClass dialog. Returns (NOT EOF(THIS.cUserTableAlias)) to indicate success at locating a user. *m: exporterrorlog && Invokes _outputdialog class to allow output of error log information. *m: filenotfoundmsgbox && Displays a File Not Found messagebox. *m: filluseroptionsarray && Moves the user table's UserOpts contents to aCurrentUserOpts. Array has 4 columns: property name, value, toggle property or SET, datasession or global attribute *m: formisframeworkenabled && Reports the existance of a mediator object on a form. Uses THIS.cFormMediatorName to determine the naming convention for this object on the form. *m: getcurrentalias && Wraps the cusTableNav member's GetCurrentAlias() method. *m: getcurrenttopformref && Wraps cusWindowHandler's GetCurrentTopFormRef() method. *m: getformmediatorref && Returns a reference to a form's mediator object, or NULL if the form is not framework-enabled with a mediator object. *m: getresourcefilename && Pass: tcSource, tcExtList, tlSuppressMsg, looks for file with any of extensions in list, in order, to RETURN the appropriate pathed name ("" if none, with File Not Found msg unless tlSuppressMsg). Ignores tcExtlList if explicit ext passed in tcSource. *m: getuseroptionsetting && Takes option name and array (usually aCurrentUserOpts) and returns current value for that option, NULL if not found. *m: gobottom && Wraps cusTableNav member's GoBottom() method. *m: gonext && Wraps cusTableNav member's GoNext() method. *m: goprevious && Wraps cusTableNav member's GoPrevious() method. *m: gotop && Wraps cusTableNav member's GoTop() method. *m: gotorecord && Wraps cusTableNav member's GoToRecord() method. *m: handleprojectwindow && Hides a project with the name stored in THIS.cProjectName on startup, if it is showing, and restores it when the app object Destroys. *m: iinitialtoolbarposition_assign *m: ilasterror_access *m: instantiate && RETURNs object reference -- pass classname, classlib, APP/EXE if library is external, string of delimited parameters to be macro-executed. If being added as a member, also pass container ref plus membername if it's not OK to use unique/generated name. *m: iserrorfree && RETURNs ISNULL(THIS.iLastError) -- See THIS.ClearLastError(). *m: lgomenu_assign *m: lnavtoolbar_assign *m: lnointerrupt_assign *m: lusercanchangepassword_access *m: lusercanchangepassword_assign *m: onshutdown && Occurs when the user attempts to exit Visual FoxPro by pressing _SCREEN close button or the close button on a framework top form MDI frame. *m: purgeerrorlog && Zaps current error log with appropriate confirmation and checks. *m: querydatachanged && Wraps cusDataSession member's DataChanged() method. *m: querydatasessionunload && Wraps cusDataSession member's Queryunload() method. *m: readevents && Starts read events mode. *m: refreshfavoritepopup && DEFINEs BARs for Favorites menu popup using THIS.cCurrentUserFavoriteIDs. *m: refreshformscollection && Refresh forms collection arrays and counters. *m: refreshtoolbars && Called by member timer and at any other time you need to synch toolbars to current environment. Iterates through toolbar collection calling Refresh methods so that it doesn't assume any tbr class. *m: releasecollaborators && Manages release of collaborative objects *m: releasecontextmenu && Manages release of a single context menu and the context menu collection. *m: releasecontextmenus && Releases all context menus. *m: releaseform && Release specific or active form and manages forms collection. *m: releaseforms && Release all application forms from memory and the forms collection. *m: releaseframe && Releases top form/MDI frame. *m: releasesessions && Releases all mediated datasession collaborator objects *m: releasetoolbar && Parallel to ReleaseForm. Maintains toolbars collection. *m: releasetoolbars && Parallel to ReleaseForms. Iterates through toolbar collection *m: resetformscollection && Reset arrays and counters of forms collection. *m: restoreenvironment && Restores environment settings. *m: saveenvironment && Saves environment settings. *m: seekcurrentuser && This method finds the current user using an exact match (case sensitivity depends on THIS.lUserNameIsCaseSensitive). *m: seekdefaultuser && This method finds a record with a blank user name where default options and favorites are stores, for use when defining a new user or when user logins and separate user profiles are not required. *m: seekmetatablefavoriteid && Finds a record in the meta table using an identification specified in #DEFINE APP_META_FAVE_ID in _FRAMEWK.H. Override this method if you decide to use a more sophisticated method of identifying records in the metatable! *m: setappfilenames && Get top-level filename, and also get the name of the module (app or exe) that owns this particular object, for SET CLASSLIB ... IN... default usage, which may be different, especially in modular and non-ReadEvents apps. *m: setcurrentuser && Finds the current user and sets up the app to deal with the current user (permissions, options, favorites, and macros may all change per user). *m: setcurrentuserfavoriteids && Saves and restores THIS.cCurrentUserFavoriteIDs information to UserFave memo field in user table. This memo field also contains date information, so user can opt to clear favorites list if metatable has changed since user has identified favorites. *m: setdatasessionenvironment && Sets a specified data session to a default set of SETs, which you place in the SetDataSessionSets for use by any form or session you want. *m: setdatasessionsets && Contains a default list of data-session-related SETs so you can easily invoke this list within any form or datasesion. *m: setenvironment && Sets up certain global attributes, such as screen or frame characteristics, ON SHUTDOWN, ON ERROR, and macros for use during the life of the app. Does *nothing* if not a ReadEvents app. *m: setframeattributes && Applies application cCaption and cIcon to the MDI frame, as well as the appropriate backcolor for an MDI frame window. *m: sethtmlclass && Abstract. Takes parameters tcSource (report form or alias/table), tlTable, so you can decide what HTMLClass is appropriate. Passed to GENHTML via _outputdialog attributes. *m: sethtmlstyleid && Abstract. Takes parameters tcSource (report form or alias/table), tlTable, so you can decide what HTMLClass is appropriate. Passed to GENHTML via _outputdialog attributes. *m: setmacros && Saves and restores a set of macros using the user table. Synchronizes enabling of bars on the macro-handling popup, using THIS.cMacroPopupName, depending on current set of user macros. *m: setscreenattributes && Sets up screen attributes, including visibility, caption and icon, and system toolbars, for a read events app that does not take place in its own topform MDI frame. *m: setuserpermissions && Abstract in the base. Called when a new user logs on. Designed to use iCurrentUserLevel property, derived from user table, to maintain groups. Menu items would be added/substracted/enabled/disabled based on group level at this time. *m: show && Sets up visible aspects of the application and, if successful, Activate()s the application, at startup. *m: showstartupelements && Sets up top form MDI frame, startup menu, startup toolbar, screen attributes, and startup form. *m: showtablefinddialog && Instantiates _FindDialog class, in advanced or standard mode, depending on THIS.lFindOnMultipleTables value. (Advanced mode allows the user to choose between all open aliases in a data session.) *m: showtablegotodialog && Instantiates _GoToDialog class. *m: showtablesetfilterdialog && Instantiates _FilterExpr class, in advanced or standard depending on THIS.lUseGetExpr value. (Standard mode uses _FilterDialog as a subsidiary dialog, Advanced uses _GETEXPR.) *m: storepassword && Stores the encrypted value of a new password to the current record in the user table. *m: validatemetatable && Ensures that a table contains a valid and available table for documents registry. Validates THIS.cMetatable, if used, on startup. *p: caboutboxclass && Name of dialog class instantiated by DoAboutBox() *p: caboutboxclasslib && Class library for dialog class instantiated by DoAboutBox(). If empty defaults to same class library as application object. *p: cappfilename && Top level filename *p: cappfolder && Location of application, usually top level file, but sometimes the location of the module that owns the VCX of this application object. Indicates default location of generated system files such as error and user tables. *p: cauthor && "Credits" information. *p: ccaption && Friendly name of the application object. *p: cchangepasswordclass && Dialog class instantiated by DoChangePassword(). *p: cchangepasswordclasslib && Class library for dialog class instantiated by DoChangePassword(). If empty defaults to same class library as application object. *p: cclasscontainerfilename && APP,EXE, or DLL containing the VCX from which this app object was instantiated. *p: ccompany && "Credits" information. *p: ccopyright && "Credits" information. *p: ccurrentuser && Name of current user as logged on. *p: ccurrentuserfavoriteids && A delimited string containing IDs of metatable entries that should be included in Favorites list as well as filenames picked by user for inclusions in Favorites list. *p: cdatafolder && Not used internally, allows you to maintain a current location for your data or for user-generated files. *p: cerrorlogtablename && Default table name for error log. *p: cerrorviewerclass && Dialog class instantiated by DisplayErrorLog(). *p: cerrorviewerclasslib && Class library for dialog class instantiated by DisplayErrorLog(). If empty defaults to same class library as application object. *p: cfavoritepopupname && Name of popup displaying favorites. Required so the app object can refresh this popup between users or when a user selects new Favorites. *p: cformmediatorname && Member name the app object looks for when contacting a mediator object on framework-enabled forms. *p: cframeclass && Dialog class instantiated by CreateFrame(). *p: cframeclasslib && Class library for dialog class instantiated by CreateFrame(). If empty defaults to same class library as application object. *p: cgomenufile && Name of menu to be used when a form entry in the meta table indicates that it should have a navigation menu. *p: chelpfile && Name of help file for this application. *p: cicon && Icon of the application object. *p: cimage && Image to be used in logos, on the splash screen, etc. *p: clastdirectory && Stores default directory when a readevents-type application starts up, for later restoration. *p: clastmackey && Stores SET MACKEY when a readevents-type application starts up, for later restoration. *p: clastonerror && Stores ON ERROR when a readevents-type application starts up, for later restoration. *p: clastonshutdown && Stores ON SHUTDOWN when a readevents-type application starts up, for later restoration. *p: clastpath && Stores SET("PATH") when a readevents-type application starts up, for later restoration. *p: cmackey && Supplies the SET MACKEY for the application. Only used in ReadEvents apps. *p: cmacropopupname && Name of popup handling macro sets. Required so the app object can refresh this popup between users, when the user stores a macro set, etc. *p: cmacrosavefile && Stores the (generated) name of an FKY file created on startup of a ReadEvents app, for later restoration. *p: cmediatedsessionclass && Name of class used to instance a framework-enabled datasession object, defaults to "_MediatedSession" *p: cmediatedsessionclasslib && Classlib containing cMediatedSession class, defaults to "_FRAMEWK.VCX" *p: cmediatorclass && Class used for dynamic form enabling at runtime (see lEnableFormsAtRuntime.) Should always contain a class descended from _formmediator in _FRAMEWK.VCX. *p: cmediatorclasslib && Classlibrary used for dynamic form enabling at runtime (see lEnableFormsAtRuntime). Should always be the name of the library containing the class specified in _application.cMediatorClass. *p: cmetatable && Stores the name of the application's metatable. *p: cnavtoolbarclass && Toolbar class when a metatable entry calls for a navigation toolbar. *p: cnavtoolbarclasslib && Class library for toolbar class when a metatable entry calls for a navigation toolbar. If empty defaults to same class library as application object. *p: cnewopenclass && Dialog class instantiated by DoNewOpen(). *p: cnewopenclasslib && Class library for dialog class instantiated by DoNewOpen(). If empty defaults to same class library as application object. *p: coptionsdialogclass && Dialog class instantiated by DoOptionsDialog(). *p: coptionsdialogclasslib && Class library for dialog class instantiated by DoOptionsDialog(). If empty defaults to same class library as application object. *p: cprojectname && Name of a project that should be hidden on startup, for display at the end of the application. For convenience (so you don't inadvertently try to work on an app component while it's running, especially in non-ReadEvents or top form apps). *p: creference && The var name that the app should declare as its PUBLIC reference and release when it ends. *p: creportdialogclass && Dialog class instantiated by DoReportDialog(). *p: creportdialogclasslib && Class library for dialog class instantiated by DoReportDialog(). If empty defaults to same class library as application object. *p: csessionclass && Default class definition name to pass to any _MediatedSession collaborator. If empty will be filled by member's cSessionClass property after successful instantiation. *p: csessionclasslib && Default programmatic class definition filename to pass to any _MediatedSession collaborator. If empty will be filled by member's cSessionClassLib property after successful instantiation. *p: cstartupformclass && Form (SCX) which is executed when the application object is shown. *p: cstartupformclasslib && Class library for dialog class instantiated by DoStartupForm(). If empty defaults to same class library as application object. *p: cstartupmenu && Menu (MPR) which is executed when the application object is shown. *p: cstartupmenupad && For non-ReadEvents/Append style app menus, allows the application to remove this menu pad when the app ends. *p: cstartupmenupopup && For non-ReadEvents/Append style app menus, allows the application to release this popup when the app ends. *p: cstartuptoolbarclass && Standard toolbar instantiated by ShowStartupElements(). *p: cstartuptoolbarclasslib && Class library for standard toolbar instantiated by ShowStartupElements(). If empty defaults to same class library as application object. *p: ctextdisplayfont && A sample "global user pref", allows users to store a font for display of text such as editboxes. To see it used, see the error log dialog.ApplyAppAttributes. The app gives this value to _outputdialog, applying it to the dialog's cDisplayFontName. *p: ctrademark && "Credits" information. *p: cuserloginclass && Dialog class instantiated by DoUserLogin(). *p: cuserloginclasslib && Class library for dialog class instantiated by DoUserLogin(). If empty defaults to same class library as application object. *p: cusertablealias && Alias for user table. *p: cusertableidfield && Name of c-type field storing user name. *p: cusertablelevelfield && Name of i-type field storing user level. *p: cusertablename && Name of user table. *p: icurrentuserlevel && Current user's level. *p: iinitialtoolbarposition && Indicates how a toolbar should be Docked() when instantiated. *p: ilasterror && Stores error number of last number, or NULL when cleared. *p: iqueryunloadresultfornonvisualsessions && Used by ReleaseSessions method -- if 0, reverts, if 1, updates, otherwise asks user for confirm just like forms. Defaults to 0. *p: laboutbox && Indicates whether app should display an about box. *p: laddingnewdocument && Application flag a form can check to see whether it should start a new document rather than edit an existing one. *p: lcascadeforms && Specifies whether multiple forms of the same type are cascaded when a new form is instanced. *p: lenableformsatruntime && Indicates whether DoForm() will dynamically adds base mediator objects to forms at runtime if they don't already have them. *p: lfavorites && Specifies whether Favorites should be used/shown on a menu in this application. *p: lfindonmultipletables && Specifies whether the ShowTableFindDialog will allow the user to switch to different tables in use in the data session. *p: lgomenu && Specifies whether a navigation menu is currently required. *p: lnavtoolbar && Specifies whether a navigation toolbar is currently required. *p: lnointerrupt && Flag to alert application object that current activity, such as data-session-changing or modal dialogs, should not be interrupted by toolbar-refreshing or other timer-related activity. *p: lnoscreenduringapp && Specifies whether screen should not be made visible during the app. *p: lreadevents && Enable READ EVENTS within ReadEvents method. *p: lreleaseunusedmenuitems && Indicates whether some menu items specific to application state should be released rather than disabled, when the MPR executes, if they are inappropriate. Used by framework's template menus. *p: lrestoredenvironment *p: lsavedenvironment *p: lskiperrorhandling && Flag to allow an error number to be stored with no further error handling, for certain brief activities within the app. *p: lstartupform && Specifies whether the app should begin with a "quick start" form. *p: lstartuptoolbar && Specifies whether the app should invoke a toolbar at startup. *p: lusercanchangepassword && Determines whether DoChangePassword() will allow the user to change his or her password. A placeholder -- you affect this behavior by using the attached access and assign methods however you decide, for example by user level. *p: lusernameiscasesensitive && Determines how the user table is searched for a match when a user logs in. *p: luserpreferences && Determines whether the user logon and options system is in place, or whether one set of options is set up for the full application. *p: luse_getexpr && Determines whether the application -- or the current user -- should use _GETEXPR or the simpler _FilterDialog to enter expressions. *p: nformcount && Forms collection count for application object. *p: npixeloffset && Number of pixels which offset multiple instances of the same form. Not used in this version, but can provide a useful value for default "margins" for form and object placement. *p: oframe && Reference to MDI frame window in top form applications. *p: onavtoolbar && Reference to navigation toolbar shared by various forms as indicated in their metatable entries. *a: acollaborators[1,0] && Collection of object references for members that cannot be contained by custom application object, such as forms *a: acontextmenus[1,4] && Manages context menus invoked by the application object. *a: acurrentuseropts[1,4] && Holds user preferences for use globally (by the app object and global SETs) or in a data session (by a form or formset object and data-session-specific SETs). *a: aformnames[1,0] && Collection of strings (for SCXs, file names, for VCXs, file and class names), enabling the application object to uniquely identify form and formset classes currently instantiated and referenced in its aForms() collection. *a: aforms[1,0] *a: atoolbars[1,2] && Parallel to aForms[] * PROTECTED Destroy,Init,lrestoredenvironment,lsavedenvironment * BorderWidth = 0 caboutboxclass = caboutboxclasslib = cappfilename = cappfolder = cauthor = ccaption = cchangepasswordclass = cchangepasswordclasslib = cclasscontainerfilename = ("") ccompany = ccopyright = ccurrentuser = ccurrentuserfavoriteids = .NULL. cdatafolder = cerrorlogtablename = ("AppError") cerrorviewerclass = cerrorviewerclasslib = cfavoritepopupname = cformmediatorname = ("app_mediator") cframeclass = cframeclasslib = cgomenufile = ("GO_APP") chelpfile = cicon = cimage = clastdirectory = clastmackey = clastonerror = clastonshutdown = clastpath = cmackey = ("ALT-F10") cmacropopupname = cmacrosavefile = cmediatedsessionclass = ("_MediatedSession") cmediatedsessionclasslib = ("_FRAMEWK.VCX") cmediatorclass = ("_FormMediator") cmediatorclasslib = ("_FRAMEWK.VCX") cmetatable = cnavtoolbarclass = cnavtoolbarclasslib = cnewopenclass = cnewopenclasslib = coptionsdialogclass = coptionsdialogclasslib = cprojectname = creference = creportdialogclass = creportdialogclasslib = csessionclass = csessionclasslib = cstartupformclass = cstartupformclasslib = cstartupmenu = cstartupmenupad = cstartupmenupopup = cstartuptoolbarclass = cstartuptoolbarclasslib = ctextdisplayfont = ("Courier New") ctrademark = cuserloginclass = cuserloginclasslib = cusertablealias = cusertableidfield = ("UserName") cusertablelevelfield = ("UserLevel") cusertablename = ("AppUser") cversion = Height = 28 icurrentuserlevel = 0 iinitialtoolbarposition = 0 ilasterror = .NULL. iqueryunloadresultfornonvisualsessions = 0 laboutbox = .T. lenableformsatruntime = .T. lfavorites = .T. lreadevents = .T. lstartupform = .T. lstartuptoolbar = .T. lusercanchangepassword = .T. Name = "_application" nformcount = 0 npixeloffset = 22 oframe = .NULL. onavtoolbar = .NULL. Visible = .F. Width = 154 * ADD OBJECT 'cusDataSession' AS _datasession WITH ; Height = 19, ; Left = 25, ; Name = "cusDataSession", ; Top = 0, ; Width = 23 *< END OBJECT: ClassLib="..\ffc\_app.vcx" BaseClass="custom" /> ADD OBJECT 'cusError' AS _error WITH ; Height = 19, ; Left = 0, ; Name = "cusError", ; Top = 0, ; Width = 23 *< END OBJECT: ClassLib="..\ffc\_app.vcx" BaseClass="custom" /> ADD OBJECT 'cusTableNav' AS _tablenav WITH ; Height = 19, ; Left = 96, ; Name = "cusTableNav", ; Top = 0, ; Width = 23 *< END OBJECT: ClassLib="..\ffc\_table.vcx" BaseClass="custom" /> ADD OBJECT 'cusTableSort' AS _tablesort WITH ; Height = 19, ; Left = 72, ; Name = "cusTableSort", ; Top = 0, ; Width = 23 *< END OBJECT: ClassLib="..\ffc\_table.vcx" BaseClass="custom" /> ADD OBJECT 'cusWindowHandler' AS _windowhandler WITH ; Height = 19, ; Left = 48, ; Name = "cusWindowHandler", ; Top = 0, ; Width = 23 *< END OBJECT: ClassLib="..\ffc\_ui.vcx" BaseClass="custom" /> ADD OBJECT 'tmrRefresh' AS _traceawaretimer WITH ; Interval = 500, ; Left = 120, ; Name = "tmrRefresh", ; Top = 0 *< END OBJECT: ClassLib="..\ffc\_app.vcx" BaseClass="timer" /> PROCEDURE activate && Makes the application active THIS.ClearLastError() THIS.BeforeReadEvents() THIS.ReadEvents() RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE activateforminframe && Takes a form or toolbar reference and fixes it to appear in top form "frame" even if its ShowWindow property was 0 LPARAMETERS toFormRef LOCAL lcFormID, llToolbar IF UPPER(toFormRef.BaseClass) == "TOOLBAR" llToolbar = .T. ENDIF IF VARTYPE(THIS.oFrame) = "O" AND ; toFormRef.ShowWindow = 0 IF llToolBar lcFormID = toFormRef.Caption toFormRef.Caption = "." ELSE lcFormID = toFormRef.Name toFormRef.Name = "W"+SYS(2015) ENDIF ENDIF IF EMPTY(lcFormID) * ShowWindow is appropriate, no problem IF (NOT llToolBar) AND ; (toFormRef.WindowType = WINDOWTYPE_MODAL) toFormRef.Show(1) ELSE toFormRef.Show() ENDIF ELSE * fix the problem: IF llToolbar ACTIVATE WINDOW (toFormRef.Caption) ; IN WINDOW (THIS.oFrame.Name) toFormRef.Caption = lcFormID ELSE ACTIVATE WINDOW (toFormRef.Name) ; IN WINDOW (THIS.oFrame.Name) toFormRef.Name = lcFormID IF toFormRef.WindowType = WINDOWTYPE_MODAL toFormRef.Show(1) ENDIF ENDIF ENDIF ENDPROC PROCEDURE activatesystemwindow && Activates a system window whose name has been passed, in _SCREEN, even if _SCREEN wasn't previously visible (for debugging, does nothing in runtime) LPARAMETERs tcWindow IF EMPTY(tcWindow) OR _VFP.StartMode > 0 RETURN ENDIF LOCAL llAutoCenter llAutoCenter = _Screen.AutoCenter _SCREEN.AutoCenter = .T. _SCREEN.AutoCenter = llAutoCenter IF ! _SCREEN.Visible _SCREEN.Show() ENDIF IF WMIN("") ZOOM WINDOW SCREEN NORM ENDIF ACTIVATE WINDOW (tcWindow) IN SCREEN ENDPROC PROCEDURE addcollaborator && Instantiate objects that can't be part of application container and add a reference to collaborators collection for maintenance. See SetScreenAttributes() for examples. LPARAMETERS tcClass, tcClassLib,tcClassContainer, tcParamString, toParent, tcMemberName * should match Instantiate * Instantiate params: * LPARAMETERS tcClass, tcClassLib, tcClassContainer, tcParamString, toParent, tcMemberName * wrap Instantiate and puts the reference in the aCollaborators collection * so it can be properly managed * it's not really necessary to look out for usable empty array elements * in the middle of the array here -- objects may be released * during the life of the application, but the empty array elements will * not do any harm, so we * just re-DIME as necessary if the last element is in use... LOCAL liElement, lcClassLib liElement = ALEN(THIS.aCollaborators) IF VARTYPE(THIS.aCollaborators[liElement]) = "O" liElement = liElement + 1 DIME THIS.aCollaborators[liElement] ENDIF IF NOT EMPTY(tcClassLib) lcClassLib = tcClassLib * want to avoid passing a null string ENDIF THIS.aCollaborators[liElement] = ; THIS.Instantiate(tcClass, lcClassLib,tcClassContainer,tcParamString, toParent, tcMemberName) * Instantiate() will know to do a NEWOBJECT() or .NewObject() as required RETURN THIS.aCollaborators[liElement] ENDPROC PROCEDURE addmediatedsession && Creates a data session with a mediator object attached, referenced in the aCollaborators collection, returns a reference to this framework-enabled session. * Creates a data session with a mediator object attached, * referenced in the aCollaborators collection, * returns a reference to this framework-enabled session. LOCAL loSession, lcPass THIS.cSessionClassLib = THIS.GetResourceFileName(THIS.cSessionClassLib,".fxp .prg") IF EMPTY(THIS.cSessionClass) OR EMPTY(THIS.cSessionClassLib) lcPass = ".T." ELSE lcPass = ".T.,["+THIS.cSessionClass+"],["+THIS.cSessionClassLib+"]" ENDIF loSession = THIS.AddCollaborator(THIS.cMediatedSessionClass, THIS.cMediatedSessionClassLib,,lcPass) IF NOT ISNULL(loSession) loSession.LoadApp(THIS.cReference) * save class def information, which * may in some instances be generated, * for other members, so it doesn't need to be * re-generated each time IF EMPTY(THIS.cSessionClass) AND NOT EMPTY(loSession.cSessionClass) THIS.cSessionClass = loSession.cSessionClass ENDIF IF EMPTY(THIS.cSessionClassLib) AND NOT EMPTY(loSession.cSessionClassLib) THIS.cSessionClassLib = loSession.cSessionClassLib ENDIF ENDIF RETURN loSession ENDPROC PROCEDURE applyglobaluseroptions && Applies global (non-datasession-specific) options to the _application object and environment. Where user login and preferences are not used, applies a single set at startup -- with user login and preferences, applies to each user login. LOCAL liRow, lcItem, lvValue, liPos FOR liRow = 1 TO ALEN(THIS.aCurrentUserOpts,1) IF NOT THIS.aCurrentUserOpts[liRow,4] && datasession preference, not global LOOP ENDIF lcItem = THIS.aCurrentUserOpts[liRow,1] lvValue = THIS.aCurrentUserOpts[liRow,2] IF VARTYPE(lcItem) # "C" LOOP ENDIF IF NOT THIS.aCurrentUserOpts[liRow,3] && property of app or app member liPos = AT(".",lcItem) IF (liPos = 0 AND PEMSTATUS(THIS,lcItem,5)) OR ; (liPos > 1 AND PEMSTATUS(EVAL("THIS."+SUBSTR(lcItem,1,liPos-1)),SUBSTR(lcItem,liPos+1),5)) THIS.&lcItem. = lvValue ENDIF ELSE && SET value IF VARTYPE(lvValue) # "C" LOOP ENDIF SET &lcItem &lvValue ENDIF ENDFOR RETURN ENDPROC PROCEDURE applyuseroptsforsession && Applies datasession-specific options a form object and its session environment. LPARAMETERS toSession IF VARTYPE(toSession) # "O" RETURN ENDIF LOCAL liSession, liRow, lcItem, lvValue, liPos, llInterrupted llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF liSession = SET("DATASESSION") SET DATASESSION TO (toSession.DataSessionID) FOR liRow = 1 TO ALEN(THIS.aCurrentUserOpts,1) IF THIS.aCurrentUserOpts[liRow,4] && global preference, not private to session LOOP ENDIF lcItem = THIS.aCurrentUserOpts[liRow,1] lvValue = THIS.aCurrentUserOpts[liRow,2] IF VARTYPE(lcItem) # "C" LOOP ENDIF IF NOT THIS.aCurrentUserOpts[liRow,3] && property of form or form member liPos = AT(".",lcItem) IF (liPos = 0 AND PEMSTATUS(toSession,lcItem,5)) OR ; (liPos > 1 AND PEMSTATUS(EVAL("toSession."+SUBSTR(lcItem,1,liPos-1)),SUBSTR(lcItem,liPos+1),5)) toSession.&lcItem. = lvValue ENDIF ELSE && SET value IF VARTYPE(lvValue) # "C" LOOP ENDIF SET &lcItem &lvValue ENDIF ENDFOR SET DATASESSION TO (liSession) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN ENDPROC PROCEDURE beforedoform && Hook in DoForm method, allowing last-minute manipulation of environment before the form class or object is instantiated. LPARAMETERS tcFileName,tcClass,tlNoMultipleInstances,tlNoShow, tlGoMenu, tlNavToolbar * abstract hook from DoForm ENDPROC PROTECTED PROCEDURE beforereadevents && Method executed before READ EVENTS is executed when ReadEvents is called. ENDPROC PROCEDURE caboutboxclass_access && Synchronizes classname value with lAboutBox value IF NOT THIS.lAboutBox RETURN "" ELSE RETURN THIS.cAboutBoxClass ENDIF ENDPROC PROCEDURE cappfolder_access && Determines the application folder, usually the folder containing the running APP or EXE. However where a temporary wrapper program or ON... command has been used to instantiate the application, this value may be the location of the VCX * note: this is an access method because * conceivably directories could get renamed * while an app is running! IF EMPTY(THIS.cAppFolder) OR (NOT DIRECTORY(THIS.cAppFolder)) LOCAL lcAppFolder IF (NOT EMPTY(THIS.cClassContainerFileName)) lcAppFolder = ; LEFT(THIS.cClassContainerFileName,RAT("\",THIS.cClassContainerFileName)) ENDIF * The cClassContainerFileName could be empty... it's possible * that this CREATEOBJECT was not done in an APP or EXE... * (see comments in SetAppFileNames() for how these properties are * used and what they represent) IF ( EMPTY(lcAppFolder) OR (NOT DIRECTORY(lcAppFolder)) ) ; AND ; (NOT EMPTY(THIS.cAppFileName)) lcAppFolder = LEFT(THIS.cAppFileName,RAT("\",THIS.cAppFileName)) * this will be a wrapper program -- may or may not * be the same for every user or every login, * especially if temp programs are involved, * so it is not as good as cClassContainerFileName ENDIF * finally, both the properties may be empty, especially if * an ON... was involved in the initial call, * We still need an appfolder **on disk** to give us * a default location for some system files IF ( EMPTY(lcAppFolder) OR (NOT DIRECTORY(lcAppFolder)) ) lcAppFolder = SET("DIRECTORY") ENDIF THIS.cAppFolder = lcAppFolder ENDIF IF RIGHT(THIS.cAppFolder,1) # "\" && for example, SET("DIRE") doesn't provide a final backslash! THIS.cAppFolder = THIS.cAppFolder + "\" ENDIF RETURN THIS.cAppFolder ENDPROC PROCEDURE cascadeall && Wraps cusWindowHandler's CascadeFormInstances() method, passing no argument. LPARAMETERS tcForm THIS.cusWindowHandler.CascadeFormInstances(tcForm) ENDPROC PROCEDURE cascadeform && For backwards compatibility, not used LPARAMETERS tcFormName LOCAL lcFormName DO CASE CASE (NOT EMPTY(tcFormName)) AND WEXIST(tcFormName) lcFormName = tcFormName CASE TYPE("_SCREEN.ActiveForm")= "O" lcFormName = _SCREEN.ActiveForm.Name OTHERWISE RETURN .F. ENDCASE ENDPROC PROCEDURE ccaption_access IF VARTYPE(THIS.cCaption) # "C" RETURN "" ELSE RETURN THIS.cCaption ENDIF ENDPROC PROCEDURE ccaption_assign LPARAMETERS tvNewVal IF VARTYPE(tvNewVal) # "C" THIS.cCaption = "" ELSE THIS.cCaption = tvNewVal ENDIF ENDPROC PROCEDURE cdatafolder_assign LPARAMETERS tcDataFolder LOCAL lcDataFolder lcDataFolder = IIF(VARTYPE(tcDataFolder) = "C" AND ; DIRECTORY(tcDataFolder), ; tcDataFolder,"") THIS.cDataFolder = lcDataFolder ENDPROC PROCEDURE cerrorlogtablename_access && adds cAppFolder information to the error log table name, so the default error DBF is always in one place. LOCAL lcTable lcTable = THIS.cErrorLogTableName IF AT("\",lcTable) = 0 lcTable = THIS.cAppFolder+lcTable ENDIF IF AT(".",lcTable) = 0 lcTable = lcTable+".DBF" ENDIF RETURN lcTable ENDPROC PROCEDURE checkpassword && Sends a passed value and a stored value from the current user information to CheckValueAgainstStoredPassword for verification. LPARAMETERS tcValueToCheck ASSERT VARTYPE(tcValueToCheck) = "C" AND USED(THIS.cUserTableAlias) LOCAL lcValueToCheck, lcStoredPassword, llSuccess IF (NOT THIS.lUserPreferences) OR ; VARTYPE(tcValueToCheck) # "C" RETURN .F. ENDIF lcValueToCheck = ALLTRIM(tcValueToCheck) lcStoredPassword = EVAL("ALLTRIM("+THIS.cUserTableAlias+".UserPass)") llSuccess = THIS.CheckValueAgainstStoredPassword(lcValueToCheck, lcStoredPassword) RETURN llSuccess ENDPROC PROCEDURE checkvalueagainststoredpassword && Compares a current password entry against an encrypted stored entry. Separated from CheckPassword so its simple algorithm can be replaced as necessary. Algorithms in CreateStoredPassword and CheckValueAgainstStoredPassword should match. LPARAMETERS tcValueToCheck, tcStoredValue IF VARTYPE(tcValueToCheck) # "C" RETURN .F. ENDIF * see notes in _application.CreateStoredPassword()... * this method is separated out to make the method * of encryption more easily edited... RETURN (tcStoredValue == SYS(2007,tcValueToCheck)) ENDPROC PROCEDURE cicon_assign LPARAMETERS m.vNewVal IF NOT EMPTY(m.vNewVal) THIS.cIcon = THIS.GetResourceFileName(m.vNewVal,".ico") ELSE THIS.cIcon = "" ENDIF ENDPROC PROCEDURE cimage_assign && Verifies the availability of an image file for use as the application logo LPARAMETERS m.vNewVal *To do: Modify this routine for the Assign method IF NOT EMPTY(m.vNewVal) THIS.cimage = THIS.GetResourceFileName(m.vNewVal,".bmp .ico .gif") ELSE THIS.cImage = "" ENDIF ENDPROC PROCEDURE clearevents && Clears any pending read events. THIS.ClearLastError() IF THIS.lReadEvents CLEAR EVENTS ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE clearfavorites && Called by Favorites menu item, to confirm "zap" of user favorites and invoke SetCurrentUserFavoriteIDs mechanism. * this is meant for interactive confirmation/menu use IF (MESSAGEBOX(APP_USER_FAVES_CLEAR_LOC, ; MB_ICONQUESTION + MB_YESNO, ; THIS.cCaption)) ; = IDYES THIS.SetCurrentUserFavoriteIDs("") ENDIF ENDPROC PROCEDURE clearlasterror && Sets _application.iLastError to NULL, called before operations which may require an error to be tested on conclusion. Abstracted for easy overriding in subclasses. THIS.iLastError = .NULL. ENDPROC PROCEDURE createcollaborators && A startup hook to allow you to call the AddCollaborators() method during initialization procedures *&* The collaborators mechanism allows for things that can't be *&* a member of the app container to disappear on cue, *&* like a background image on screen. *&* This abstract method gives you a hook to create collaborators *&* at startup (during the .Show() method), using AddCollaborator(), *&* but you can scope objects to the application *&* at any time during the life of the app. *&* AddCollaborator()'s params match Instantiate()'s. RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE createformmediator && Adds a app mediator object to a form LPARAMETERS toForm IF VARTYPE(toForm) # "O" OR ; NOT (UPPER(toForm.BaseClass) == "FORM") RETURN NULL ENDIF LOCAL lcMediatorName, loMediator IF TYPE("toForm."+THIS.cFormMediatorName+".Name") # "C" lcMediatorName = THIS.cFormMediatorName ELSE lcMediatorName = "Mediator_"+SYS(2015) * a mediator with a generated name * is less useful and will cause slower * behavior but it will do in a pinch ENDIF THIS.ClearLastError() loMediator = THIS.Instantiate(THIS.cMediatorClass,THIS.cMediatorClassLib,,,; toForm,lcMediatorName) IF (NOT THIS.IsErrorFree()) OR (NOT THIS.FormIsFrameworkEnabled(toForm)) THIS.ClearLastError() * required default classes THIS.cMediatorClass = "_FormMediator" THIS.cMediatorClassLib = "_FRAMEWK.VCX" loMediator = THIS.Instantiate(THIS.cMediatorClass,THIS.cMediatorClassLib,,,; toForm,lcMediatorName) ENDIF IF THIS.IsErrorFree() loMediator.cAppRef = THIS.cReference RETURN loMediator ELSE RETURN NULL ENDIF ENDPROC PROCEDURE createframe && Creates the MDI frame for top form applications. LOCAL lcClassLib THIS.ClearLastError() IF NOT EMPTY(THIS.cFrameClassLib) lcClassLib = THIS.cFrameClassLib ENDIF IF NOT EMPTY(THIS.cFrameClass) THIS.oFrame = THIS.Instantiate(THIS.cFrameClass,lcClassLib) IF VARTYPE(THIS.oFrame) = "O" THIS.oFrame.oApp = THIS ENDIF ELSE THIS.oFrame = .NULL. ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE createstoredpassword && Creates an encrypted value of a password. Separated from StorePassword() for easy replacement of its simple algorithm. Algorithms in CreateStoredPassword and CheckValueAgainstStoredPassword should match. * separated out for easier editing, * created for Q&D checksum method of storing information, * but this is not really encryption... LPARAMETERS tcValueToStore ASSERT VARTYPE(tcValueToStore) = "C" RETURN SYS(2007,ALLTRIM(tcValueToStore)) ENDPROC PROCEDURE createusertable && Creates and indexs user table when it does not exist. Abstracted for easy editing. The app expects this table to have 1 c-type field, with its name in the cUserTableIDField property, and 1 i-type field, its name in cUserTableLevelField. LPARAMETERS tcTable * is passed exact table name and location * is separated out so that you can * use different table structures more easily * The application object expects that whatever table * you use, you will have created one c-type field and placed * its name in THIS.cUserTableIDField, and one i-type field and * placed its name in THIS.cUserTableLevelField. THIS.ClearLastError() LOCAL liSelect, lcIDField, lcLevelField lcIDField = THIS.cUserTableIDField lcLevelField = THIS.cUserTableLevelField liSelect = SELECT() SELECT 0 CREATE TABLE (tcTable) ; ((lcIDField) C(60), ; (lcLevelField) I, ; UserPass M NOCPTRANS, ; UserOpts M NOCPTRANS, ; UserFave M NOCPTRANS, ; UserMacro M NOCPTRANS, ; UserNotes M ) INDEX ON PADR(ALLTR(&lcIDField.),60) TAG ID * create a case-sensitive, exact word match INDEX ON PADR(UPPER(ALLTR(&lcIDField.)),60) TAG ID_Upper * create a case-insensitive, exact word match INDEX ON DELETED() TAG IfDeleted USE SELECT (liSelect) RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE creference_assign LPARAMETERS tcReference IF VARTYPE(tcReference) = "C" IF (TYPE(THIS.cReference+".Name") = "C" AND ; EVAL(THIS.cReference) = THIS) RELEASE (THIS.cReference) ENDIF THIS.cReference = tcReference ENDIF IF (NOT EMPTY(THIS.cReference)) AND ; (TYPE(THIS.cReference+".Name") # "C" OR ; EVAL(THIS.cReference) # THIS) RELEASE (THIS.cReference) PUBLIC (THIS.cReference) STORE THIS TO (THIS.cReference) ENDIF ENDPROC PROCEDURE cstartupformclass_access && Synchronizes classname value with lStartupForm value RETURN THIS.cStartupFormClass ENDPROC PROCEDURE cstartuptoolbarclass_access && Synchronizes classname value with lStartupToolbar value IF NOT THIS.lStartupToolbar RETURN "" ELSE RETURN THIS.cStartupToolbarClass ENDIF ENDPROC PROCEDURE ctextdisplayfont_assign LPARAMETERS tcNewVal IF VARTYPE(tcNewVal) # "C" OR EMPTY(tcNewVal) RETURN ENDIF LOCAL laTemp[1], lcVal, lcFont lcVal = ALLTR(tcNewVal) IF NOT EMPTY(AFONT(laTemp)) FOR EACH lcFont IN laTemp IF UPPER(lcVal) == UPPER(lcFont) THIS.cTextDisplayFont = lcVal EXIT ENDIF ENDFOR ENDIF ENDPROC PROCEDURE cusertablealias_assign LPARAMETERS tcNewVal IF VARTYPE(tcNewVal) # "C" OR ; (USED(tcNewVal) AND ; (NOT DBF(tcNewVal) == THIS.cUserTableName) ) THIS.cUserTableAlias = "U"+SYS(2015) ELSE THIS.cUserTableAlias = tcNewVal ENDIF ENDPROC PROCEDURE cusertablename_access LOCAL lcTable lcTable = UPPER(THIS.cUserTableName) IF AT("\",lcTable) = 0 lcTable = THIS.cAppFolder+lcTable ENDIF IF AT(".",lcTable) = 0 lcTable = lcTable+".DBF" ENDIF IF EMPTY(SYS(2000,lcTable)) OR ; EMPTY(SYS(2000,STRTRAN(lcTable,".DBF",".FPT"))) THIS.CreateUserTable(lcTable) ENDIF RETURN lcTable ENDPROC PROCEDURE datarevert && Wraps cusDataSession's Revert() method. LPARAMETERS tlUserChoiceAlreadyConfirmed, tlDataChangeAlreadyConfirmed, toSession, tlNoShow LOCAL llInterrupted, llReturn llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF llReturn = THIS.cusDataSession.Revert(tlUserChoiceAlreadyConfirmed, tlDataChangeAlreadyConfirmed, toSession, tlNoShow) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN llReturn ENDPROC PROCEDURE dataupdate && Wraps cusDataSession's Update() method. LPARAMETERS tlUserChoiceAlreadyConfirmed, tlDataChangeAlreadyConfirmed, toSession, tlNoShow LOCAL llReturn, llInterrupted llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF llReturn = THIS.cusDataSession.Update(tlUserChoiceAlreadyConfirmed, tlDataChangeAlreadyConfirmed, toSession, tlNoShow) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN llReturn ENDPROC PROTECTED PROCEDURE Destroy DODEFAULT() THIS.lNoInterrupt = .T. * one last disable the timer so we can avoid it * interfering while we're closing up shop. IF EMPTY(THIS.cFrameClass) AND (NOT EMPTY(THIS.cGoMenuFile)) RELEASE PAD _msm_Go OF _MSYSMENU RELEASE POPUP _mGo EXTENDED ENDIF * some of this is double-handling but * will not hurt -- it's possible * that a CLEAR ALL or other mechanism * has ended the app without a Release() * method having been issued -- such * as a failed Show method: THIS.ReleaseContextMenus(.T.) THIS.ReleaseSessions(.T.) THIS.ReleaseForms(.T.) THIS.ReleaseToolbars(.T.) THIS.ReleaseCollaborators() THIS.ReleaseFrame() THIS.ClearEvents() IF USED(THIS.cUserTableAlias) USE IN (THIS.cUserTableAlias) ENDIF IF NOT THIS.lRestoredEnvironment * must restore environment * at all times, because * failure may have occurred * during Show, but * have to make sure *not* * to restore environment * if it's already been done * because there are things * in here than cannot or * should not be done twice: THIS.RestoreEnvironment() ENDIF IF NOT EMPTY(THIS.cReference) RELEASE (THIS.cReference) ENDIF THIS.HandleProjectWindow(.T.) ENDPROC PROCEDURE displayerrorlog && Instantiates cErrorViewerClass dialog LOCAL loTemp, liIndex, llOK IF NOT EMPTY(THIS.cErrorViewerClass) loTemp = THIS.AddCollaborator(THIS.cErrorViewerClass,; THIS.cErrorViewerClassLib) IF VARTYPE(loTemp) = "O" llOK = loTemp.ApplyAppAttributes(THIS) IF llOK * maybe no error records, or even no table THIS.ActivateFormInFrame(loTemp) && modeless ELSE loTemp.Release() ENDIF ENDIF RETURN llOK ELSE THIS.cusError.DisplayErrorLog() ENDIF ENDPROC PROCEDURE doaboutbox && Invokes cAboutBoxClass dialog class LOCAL llReturn llReturn = THIS.DoModalDialogClass(THIS.cAboutBoxClass, THIS.cAboutBoxClassLib) RETURN llReturn ENDPROC PROCEDURE dochangepassword && Invokes cChangePasswordClass dialog class IF (NOT THIS.lUserPreferences) * shouldn't even be in here RETURN .F. ENDIF IF NOT THIS.lUserCanChangePassword * this item may be on the menu * but not applicable to this user, * for various reasons MESSAGEBOX(USER_PERMISSION_DENIED_LOC,MB_ICONEXCLAMATION,THIS.cCaption) RETURN .F. ENDIF LOCAL llOpenedTable, llReturn IF NOT USED(THIS.cUserTableAlias) USE (THIS.cUserTableName) IN 0 AGAIN SHARED ALIAS (THIS.cUserTableAlias) llOpenedTable = .T. ENDIF THIS.SeekCurrentUser() llReturn = THIS.DoModalDialogClass(THIS.cChangePasswordClass, THIS.cChangePasswordClassLib) IF llOpenedTable USE IN (THIS.cUserTableAlias) ENDIF RETURN llReturn ENDPROC PROCEDURE docontextmenu && Manages context menus and context menu collection LPARAMETERS tcMenuFileName, tcPadName, tcPopupName LOCAL lcMenuFileName, ; liElement, liIndex, liMenus, lcMenu IF EMPTY(tcMenuFileName) OR EMPTY(tcPadName) OR EMPTY(tcPopupName) RETURN 0 ENDIF ASSERT VARTYPE(tcPadName) = "C" ASSERT VARTYPE(tcPopupName) = "C" ASSERT VARTYPE(tcMenuFileName) = "C" lcMenuFileName = THIS.GetResourceFileName(tcMenuFileName,".mpx .mpr") IF EMPTY(lcMenuFileName) RETURN 0 ENDIF liElement = 0 liMenus = ALEN(THIS.aContextMenus,1) FOR liIndex = 1 TO liMenus lcMenu = THIS.aContextMenus[liIndex,1] IF VARTYPE(lcMenu) # "C" OR ; VARTYPE(THIS.aContextMenus[liIndex,2]) # "N" ; OR THIS.aContextMenus[liIndex,2] = 0 liElement = liIndex LOOP ENDIF * is this menu already up? IF lcMenu == lcMenuFileName * increment its counter THIS.aContextMenus[liIndex,2] = THIS.aContextMenus[liIndex,2]+1 RETURN liIndex ENDIF ENDFOR IF liElement = 0 IF VARTYPE(THIS.aContextMenus[1,1]) = "C" liElement = liMenus+1 ELSE liElement = 1 ENDIF DIMENSION THIS.aContextMenus[liElement,4] ENDIF THIS.aContextMenus[liElement,1]=lcMenuFileName THIS.aContextMenus[liElement,2] = 1 THIS.aContextMenus[liElement,3] = ALLTRIM(tcPadName) THIS.aContextMenus[liElement,4] = ALLTRIM(tcPopupName) THIS.DoMenu(lcMenuFileName) && we don't want unique popup names for a context menu RETURN liElement ENDPROC PROCEDURE dodocumentpickerdialog && Invokes all the dialogs descending from the _documentpicker dialog superclass LPARAMETERS tcClass,tcClassLib,tlAlternateMode IF EMPTY(tcClass) RETURN .F. ENDIF LOCAL loTemp, lcClassLib IF NOT EMPTY(tcClassLib) lcClassLib = tcClassLib ENDIF IF VARTYPE(THIS.oFrame) = "O" THIS.oFrame.Show() ENDIF loTemp = THIS.Instantiate(tcClass,; lcClassLib, ,; "THIS,"+IIF(tlAlternateMode,".T.",".F.")) IF VARTYPE(loTemp) = "O" IF PEMSTATUS(loTemp,"ApplyAppAttributes",5) loTemp.ApplyAppAttributes(THIS) ELSE IF EMPTY(loTemp.Icon) loTemp.Icon = THIS.cIcon ENDIF ENDIF loTemp.Show(1) ELSE RETURN .F. ENDIF ENDPROC PROCEDURE dofile && Executes files, channelling known FoxPro-type files to appropriate application Do... methods, and files of unknown types through Windows API LPARAMETERS tcFile LOCAL lcFileName, liReturnValue, lcExt, lcStem, llReturn, llDevProduct THIS.ClearLastError() IF VARTYPE(tcFile) = "C" AND FILE(ALLTRIM(tcFile)) lcFileName = ALLTRIM(tcFile) ENDIF IF EMPTY(lcFileName) RETURN .F. ENDIF lcFileName= THIS.GetResourceFileName(lcFileName) IF EMPTY(lcFileName) RETURN .F. ENDIF lcExt = " "+UPPER(JUSTEXT(lcFileName))+" " IF NOT EMPTY(lcExt) AND LEN(lcExt) = 5 lcStem = FORCEEXT(lcFileName,"") ENDIF llReturn = NULL llDevProduct = (VERS(2) # 0) DO CASE CASE EMPTY(lcStem) * we didn't get anything we can use, * don't bother checking the CASEs CASE INLIST(lcExt," SCX ", " SCT ") llReturn = THIS.DoForm(lcStem) CASE INLIST(lcExt," LBX ", " LBT ") llReturn = THIS.DoLabel(lcStem) CASE INLIST(lcExt, " FRX ", " FRT ") llReturn = THIS.DoReport(lcStem) CASE lcExt == " MPX " llReturn = THIS.DoMenu(lcFileName) CASE INLIST(lcExt," MPR ", " MNX ", " MNT ") AND ; ( (llDevProduct AND FILE(FORCEEXT(lcFileName,"MPR"))) OR ; FILE(FORCEEXT(lcFileName,"MPX")) ) llReturn = THIS.DoMenu(lcStem) CASE INLIST(lcExt, " APP ", " FXP ") llReturn = THIS.DoProgram(lcFileName) CASE lcExt == " PRG " AND ; ( llDevProduct OR ; FILE(FORCEEXT(lcFileName,"FXP")) ) llReturn = THIS.DoProgram(lcStem) CASE INLIST(lcExt, " QPX ", " SPX ") * must use full filename for queries and sprs, * maintaining exact same behavior as the base product llReturn = THIS.DoProgram(lcFileName) CASE lcExt == " QPR " AND ; ( llDevProduct OR ; FILE(FORCEEXT(lcFileName,"QPX")) ) llReturn = THIS.DoProgram(FORCEEXT(lcFileName, "QPX")) CASE lcExt == " SPR " AND ; ( llDevProduct OR ; FILE(FORCEEXT(lcFileName,"SPX")) ) llReturn = THIS.DoProgram(FORCEEXT(lcFileName, "SPX")) OTHERWISE * fall through to below, unknown type file ENDCASE IF ISNULL(llReturn) DECLARE long ShellExecuteA IN SHELL32 ; long, string, string, string, string, long liReturnValue = ShellExecuteA( 0, "open", ; lcFilename, "","", 1 ) llReturn = (liReturnValue >= 32) ENDIF RETURN llReturn ENDPROC PROCEDURE doform && Executes an SCX form or instantiates a VCX-based form/formset class. LPARAMETERS tcFileName,tcClass,tlNoMultipleInstances,tlNoShow, tlGoMenu, tlNavToolbar ASSERT EMPTY(tcFileName) OR VARTYPE(tcFileName) = "C" ASSERT EMPTY(tcClass) OR VARTYPE(tcClass) = "C" LOCAL lcFileName,lcClass,lnCount, lcFormName,lnFormCount, loMediator, ; loForm, loFormMember, lNeedReActivateFormset, ; llFormSet,llEnabledFormFound *&* VFP 5 framework cascade code also used: *&* LOCAL lnTop,lnLeft,loForm2,lcName THIS.ClearLastError() lcFileName=ALLTRIM(tcFileName) lcClass=IIF(VARTYPE(tcClass)="C",LOWER(ALLTRIM(tcClass)),"") IF EMPTY(lcClass) lcFileName = THIS.GetResourceFileName(lcFileName,".scx") ELSE lcFileName = THIS.GetResourceFileName(lcFileName,".vcx") ENDIF IF EMPTY(lcFileName) RETURN .F. ENDIF lcFormName=IIF(EMPTY(lcClass),lcFileName,lcFileName+","+lcClass) IF tlNoMultipleInstances FOR lnCount = 1 TO THIS.nFormCount IF THIS.aFormNames[lnCount]==lcFormName AND ; VARTYPE(THIS.aForms[lnCount])="O" IF UPPER(THIS.aForms[lnCount].BaseClass)== "FORM" AND ; THIS.aForms[lnCount].WindowState = 1 && minimized THIS.aForms[lnCount].WindowState = 0 ENDIF IF VARTYPE(THIS.oFrame) = "O" THIS.oFrame.Show() ENDIF THIS.aForms[lnCount].Show RETURN .F. ENDIF ENDFOR ENDIF * this is a hook, nothing in it IF NOT THIS.BeforeDoForm(tcFileName,tcClass,tlNoMultipleInstances,tlNoShow, tlGoMenu, tlNavToolbar) RETURN .F ENDIF THIS.RefreshFormsCollection THIS.nFormCount=THIS.nFormCount+1 DIMENSION THIS.aForms[THIS.nFormCount],THIS.aFormNames[THIS.nFormCount] THIS.aFormNames[THIS.nFormCount]=lcFormName IF VARTYPE(THIS.oFrame) = "O" THIS.oFrame.Show() ENDIF IF NOT EMPTY(lcClass) THIS.aForms[THIS.nFormCount] = ; THIS.Instantiate(lcClass, lcFileName) ELSE DO FORM (lcFileName) NAME THIS.aForms[THIS.nFormCount] LINKED NOSHOW ENDIF lnFormCount=THIS.nFormCount THIS.RefreshFormsCollection IF THIS.nFormCount>=lnFormCount * success so far, * let's enable and position the new object(s) * and then show it/them if we're supposed to: loForm = THIS.aForms[THIS.nFormCount] llFormSet = (UPPER(loForm.BaseClass) == "FORMSET") IF llFormSet FOR EACH loFormMember IN loForm.Forms IF UPPER(loFormMember.BaseClass) == "FORM" * skip toolbars loMediator = THIS.GetFormMediatorRef(loFormMember) * don't force until we know about all forms * in set; see note below IF VARTYPE(loMediator) = "O" loMediator.LoadApp(THIS.cReference) loMediator.lGoMenu = tlGoMenu loMediator.lNavToolbar = tlNavToolbar llEnabledFormFound = .T. ENDIF ENDIF ENDFOR ELSE loMediator = THIS.GetFormMediatorRef(THIS.aForms[THIS.nFormCount], ; THIS.lEnableFormsAtRunTime) * second param will force creation * if lEnableFormsAtRuntime is on IF VARTYPE(loMediator) = "O" loMediator.LoadApp(THIS.cReference) loMediator.lGoMenu = tlGoMenu loMediator.lNavToolbar = tlNavToolbar ENDIF ENDIF * if any forms in the formset are enabled, * some may have been left un-enabled by * intent, so that they don't get icon or whatever. * So if even one form in the formset is enabled * we won't dynamically enable the rest. That's * why the below FOR/ENDFOR has to be done separately * from the above attempt to load mediators in a formset: IF llFormSet AND ; (NOT llEnabledFormFound) AND ; THIS.lEnableFormsAtRunTime THIS.ClearLastError() FOR EACH loFormMember IN loForm.Forms IF UPPER(loFormMember.BaseClass) == "FORM" loMediator = THIS.CreateFormMediator(loFormMember) IF VARTYPE(loMediator) = "O" loMediator.LoadApp(THIS.cReference) loMediator.lGoMenu = tlGoMenu loMediator.lNavToolbar = tlNavToolbar ENDIF ENDIF ENDFOR ENDIF IF NOT tlNoShow IF VARTYPE(THIS.oFrame) # "O" IF llFormSet * there is something screwy about * formsets when some forms may be showwindow 0 * and others 1, even in _SCREEN, so it's * best to show each form separately: FOR EACH loFormMember IN loForm.Forms loFormMember.Show() ENDFOR ELSE loForm.Show() ENDIF ELSE * seems as though if even one form in * the formset is ShowWindow = 0, * then all forms must be brought into the top form IF llFormSet FOR EACH loFormMember IN loForm.Forms IF loFormMember.ShowWindow = 0 lNeedReActivateFormset = .T. EXIT ENDIF ENDFOR FOR EACH loFormMember IN loForm.Forms IF lNeedReActivateFormset THIS.ActivateFormInFrame(loFormMember) ELSE loFormMember.Show() ENDIF ENDFOR ELSE IF loForm.ShowWindow = 0 THIS.ActivateFormInFrame(loForm) ELSE loForm.Show() ENDIF ENDIF ENDIF ENDIF IF THIS.lCascadeForms AND NOT llFormSet THIS.CascadeAll(loForm.Name) *&* this is where VFP framework used THIS.nPixelOffset, *&* all that code removed but the property might still *&* be useful somewhere ENDIF ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE doformnoshow && Executes an SCX form or instantiates a VCX-based form/formset class, without Showing it, and returning a reference to the form or formset instantiated. LPARAMETERS tcFileName,tcClass,tlNoMultipleInstances,tlGoMenu, tlNavToolbar LOCAL loForm, liCount THIS.RefreshFormsCollection() liCount = THIS.nFormCount loForm = .NULL. THIS.DoForm(tcFileName,tcClass,tlNoMultipleInstances,.T.,tlGoMenu, tlNavToolbar) IF THIS.nFormCount > liCount loForm = THIS.aForms(THIS.nFormCount) ENDIF RETURN loForm ENDPROC PROCEDURE dohelp && Executes help of types .hlp, .dbf, .htm, or .chm LPARAMETERS tcFile LOCAL lcFileName, lcExt, llReturn llReturn = .T. THIS.ClearLastError() IF VARTYPE(tcFile) = "C" AND FILE(ALLTRIM(tcFile)) lcFileName = ALLTRIM(tcFile) ELSE lcFileName=ALLTRIM(THIS.cHelpFile) ENDIF IF EMPTY(lcFileName) RETURN .F. ENDIF lcFileName= THIS.GetResourceFileName(lcFileName,".hlp .dbf .htm .chm") IF EMPTY(lcFileName) RETURN .F. ENDIF lcExt = UPPER(JUSTEXT(lcFileName)) DO CASE CASE lcExt = "DBF" IF UPPER(lcFileName) # UPPER(SET("HELP",1)) LOCAL lcOldHelpFile, lcOldHelp lcOldHelp = SET("HELP") lcOldHelpFile = SET("HELP",1) SET HELP TO (lcFileName) SET HELP ON HELP IF NOT EMPTY(lcOldHelpFile) AND FILE(lcOldHelpFile) SET HELP TO (lcOldHelpFile) ENDIF SET HELP &lcOldHelp ELSE HELP ENDIF CASE INLIST(lcExt,"HLP","HTM","CHM") llReturn = THIS.DoFile(lcFilename) OTHERWISE * ?? ENDCASE RETURN llReturn AND (THIS.IsErrorFree()) ENDPROC PROCEDURE dolabel && Executes an LBX label LPARAMETERS tcFileName, tcDescription ASSERT EMPTY(tcFileName) OR VARTYPE(tcFileName) = "C" ASSERT EMPTY(tcDescription) OR VARTYPE(tcDescription) = "C" LOCAL lcFileName, lcDescription THIS.ClearLastError() lcFileName=ALLTRIM(tcFileName) IF EMPTY(lcFileName) RETURN .F. ENDIF lcFileName= THIS.GetResourceFileName(lcFileName,".lbx") IF EMPTY(lcFileName) RETURN .F. ENDIF IF EMPTY(tcDescription) lcDescription = PROPER(JUSTSTEM(lcFileName)) ELSE lcDescription = tcDescription ENDIF THIS.DoReport(lcFileName, lcDescription) RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE domenu && Executes an MPR/MPX menu. LPARAMETERS tcFileName, tlUniquePopupNames ASSERT EMPTY(tcFileName) OR VARTYPE(tcFileName) = "C" LOCAL lcFileName THIS.ClearLastError() lcFileName=ALLTRIM(tcFileName) IF EMPTY(lcFileName) RETURN .F. ENDIF lcFileName= THIS.GetResourceFileName(lcFileName,".mpx .mpr") IF EMPTY(lcFileName) RETURN .F. ENDIF IF VARTYPE(THIS.oFrame) # "O" DO (lcFileName) ELSE DO (lcFileName) WITH THIS.oFrame, THIS.oFrame.cMenuName, tlUniquePopupNames ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE domenuiteminframe && Not currently used, wraps cusWindowHandler method LPARAMETERS tcToken IF EMPTY(tcToken) RETURN ENDIF THIS.cusWindowHandler.InvokeMenuItemInFrame(tcToken) ENDPROC PROCEDURE domodaldialogclass && Instantiates a modal dialog, applying application attributes as appropriate. RETURNs a form reference, if NOSHOW. LPARAMETERS tcWhichDialogClass, tcWhichDialogClassLib, tlNoShow LOCAL loFormRef, lcWhichDialogClassLib IF EMPTY(tcWhichDialogClass) RETURN .F. ENDIF IF NOT EMPTY(tcWhichDialogClassLib) lcWhichDialogClassLib = tcWhichDialogClassLib ENDIF IF VARTYPE(THIS.oFrame) = "O" and THIS.oFrame.ShowWindow < 2 THIS.oFrame.Show() ENDIF loFormRef = THIS.Instantiate(tcWhichDialogClass,lcWhichDialogClassLib) IF VARTYPE(loFormRef) # "O" RETURN .F. ENDIF IF PEMSTATUS(loFormRef,"ApplyAppAttributes",5) loFormRef.ApplyAppAttributes(THIS) ELSE IF EMPTY(loFormRef.Icon) loFormRef.Icon = THIS.cIcon ENDIF ENDIF IF tlNoShow RETURN loFormRef ELSE loFormRef.WindowType = 1 THIS.ActivateFormInFrame(loFormRef) RETURN .T. ENDIF ENDPROC PROCEDURE donewopen && Invokes cNewOpenClass LPARAMETERS tlNew LOCAL llReturn THIS.lAddingNewDocument = tlNew llReturn = THIS.DoDocumentPickerDialog(THIS.cNewOpenClass,; THIS.cNewOpenClassLib, ; tlNew) THIS.ResetToDefault("lAddingNewDocument") RETURN llReturn ENDPROC PROCEDURE dooptionsdialog && Invokes cOptionsDialogClass LOCAL llOpenedTable, llReturn IF NOT USED(THIS.cUserTableAlias) USE (THIS.cUserTableName) IN 0 AGAIN SHARED ALIAS (THIS.cUserTableAlias) llOpenedTable = .T. ENDIF IF THIS.lUserPreferences THIS.SeekCurrentUser() ELSE THIS.SeekDefaultUser() ENDIF llReturn = THIS.DoModalDialogClass(THIS.cOptionsDialogClass, THIS.cOptionsDialogClassLib) IF llOpenedTable USE IN (THIS.cUserTableAlias) ENDIF RETURN llReturn ENDPROC PROCEDURE doprogram && Executes a PRG, APP, FXP, or EXE program. LPARAMETERS tcFileName ASSERT EMPTY(tcFileName) OR VARTYPE(tcFileName) = "C" LOCAL lcFileName THIS.ClearLastError() lcFileName=ALLTRIM(tcFileName) IF EMPTY(lcFileName) RETURN .F. ENDIF * the following uses the order of precedence * to determine the appropriate extension: * .EXE (executable version) * .APP (an application) * .FXP (compiled version) * .PRG (program) * this program will run an SPR/SPX or QPR/QPX * as well as the explicit list that * VFP will run if you don't supply an extension, * if you pass the name with an extension. * This is consistent with the native behavior. lcFileName= THIS.GetResourceFileName(lcFileName,".exe .app .fxp .prg") IF EMPTY(lcFileName) RETURN .F. ENDIF IF VERSION(2) = 0 AND ; UPPER(JUSTEXT(lcFileName)) == "PRG" IF NOT EMPTY(SYS(2000,lcFileName)) * FXP was not found and PRG is on disk, * not built in to a file COMPILE (lcFileName) lcFileName = FORCEEXT(lcFileName,"FXP") ELSE RETURN .F. ENDIF ENDIF DO (lcFileName) RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE doreport && Executes an FRX or LBX report form. LPARAMETERS tcFileName, tcDescription, tlModify ASSERT EMPTY(tcFileName) OR VARTYPE(tcFileName) = "C" ASSERT EMPTY(tcDescription) OR VARTYPE(tcDescription) = "C" LOCAL lcFileName THIS.ClearLastError() IF (EMPTY(tcFileName) AND NOT tlModify) RETURN .F. ENDIF lcFileName=ALLTRIM(tcFileName) lcFileName= THIS.GetResourceFileName(lcFileName,".frx .lbx", tlModify) IF tlModify * if EMPTY(lcFileName) * confirm creation, use template? * else MODIFY * not yet implemented MESSAGEBOX(APP_FEATURE_NOT_AVAILABLE_LOC, ; MB_ICONINFORMATION,THIS.cCaption) ELSE IF EMPTY(lcFileName) RETURN .F. ENDIF * we can provide output *without* going through the * user's choices in the dialog at all, simply * by instantiating an _output object and setting * its properties rather than going through this dialog * This is not implemented here, because it * would definitely require that you set properties, * as below. Would make sense for a subclass app object * to have a lWantOutputDialog property which defaults .T. * If the dialog is not desired, augment the * standard behavior by looking for developer's * information -- whether in the metatable or elsewhere * about destination and options settings. LOCAL loDialog loDialog = THIS.DoModalDialogClass("_outputdialog","_reports", .T.) * note: could add a metatable check here to fill out loDialog.cAlias * or loDialog.cFieldList, or loDialog.cAddedParams... * could prefill the destination... * also note that this dialog doesn't, strictly speaking, have to * be modal, but we're calling it from a modal dialog (the picker) so * it seems reasonable to keep it modal here. We could subclass it * to know how to be a singleton, like the error dialog, instead... * and automatically know about app attributes, rather than * using the generic gallery version and adjusting it. IF VARTYPE(loDialog) = "O" LOCAL laRecNos[1], laWorkAreas[1], ; liUsed, liRow, lcAlias liUsed = AUSED(laWorkAreas) * Unlike DoTableOutput(), we really * have no clue in this method what * workareas might be affected by * the named report or label form, so * should take care of all current * record pointers, * assuming that any workareas at all * are affected in the current data * session. * Because it has a custom property * allowing a new alias to be selected * before output is generated, the * _output object saves and * restore current workarea, * after output is generated -- so * that (at least) is not an issue here. * Note also that the report either has its * own datasession, which has been * disposed of separately, * or it takes place in this * datasession, so no save/restore * of data sessions should be necessary. * We will stipulate that any custom * datasession objects that a report * might open, and even create a public * reference to, should not affect the * environment of the application * at the time this method was called. * Any additional aliases open in * this datasession by the running * report which are not closed by * the report will not be affected * by this code. * However, see remarks about VUE * file below. IF liUsed > 0 DIMENSION laRecNos[liUsed] FOR liRow = 1 TO liUsed lcAlias = laWorkAreas[liRow,1] IF EOF(lcAlias) laRecNos[liRow] = 0 ELSE laRecNos[liRow] = RECNO(lcAlias) ENDIF ENDFOR ENDIF * We must allow for the fact that * reports can cause errors -- either * because being invoked in this generic * way they don't have access to the data * they need or a UDF causes an error. THIS.lSkipErrorHandling = .T. loDialog.Icon = THIS.cIcon IF EMPTY(tcDescription) loDialog.Caption = loDialog.Caption+" "+ ; PROPER(JUSTFNAME(lcFileName)) ELSE loDialog.Caption = loDialog.Caption + " "+tcDescription ENDIF loDialog.cHTMLClass = THIS.SetHTMLClass(tcFileName) loDialog.cHTMLStyleID = THIS.SetHTMLStyleID(tcFileName) loDialog.lAddSourceNameToDropDown = .F. loDialog.cReport = lcFileName loDialog.lPreventSourceChanges = .T. loDialog.Show(1) loDialog = .NULL. * This "restore" code does *not* * handle any dropped or changed * relations that might occur in the the * FRX or LBX data environment. * Neither does it handle the possibility * that a UDF attached to the report * or label might actually close a table, * except in the most basic way, and * there could be many other * unforeseen changes * to the current data session that could * take place in a UDF. * If complete save and restore behavior * is desirable, a VUE file * should be CREATEd earlier to a * generated tempfile name, SET here * and then ERASEd, followed by * record-pointer-restoring code similar * to the following. IF liUsed > 0 FOR liRow = 1 TO liUsed lcAlias = laWorkAreas[liRow,1] IF NOT USED(lcAlias) LOOP ENDIF IF laRecNos[liRow] = 0 GO BOTTOM IN (lcAlias) SKIP IN (lcAlias) ELSE GO (laRecNos[liRow]) IN (lcAlias) ENDIF ENDFOR ENDIF IF (NOT THIS.IsErrorFree()) MESSAGEBOX(REPORT_RUN_ERROR_LOC,MB_ICONSTOP,THIS.cCaption) ENDIF THIS.lSkipErrorHandling = .F. ELSE RETURN .F. ENDIF ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE doreportdialog && Invokes cReportDialogClass LPARAMETERS tlModify LOCAL llReturn llReturn = THIS.DoDocumentPickerDialog(THIS.cReportDialogClass,; THIS.cReportDialogClassLib, ; tlModify) RETURN llReturn ENDPROC PROCEDURE dosort && Wraps cusTableSort's DoSort() method. LPARAMETERS tcField, tcAlias, tcTag, tlDescending THIS.cusTableSort.DoSort(tcField,tcAlias,tcTag,tlDescending) ENDPROC PROCEDURE dostartupform && Instantiates cStartupFormClass dialog LPARAMETERS tlAdd LOCAL llReturn, lcFavoriteIDs lcFavoriteIDs = THIS.cCurrentUserFavoriteIDs llReturn = THIS.DoDocumentPickerDialog(THIS.cStartupFormClass,; THIS.cStartupFormClassLib, ; tlAdd) IF tlAdd AND NOT (lcFavoriteIDs == THIS.cCurrentUserFavoriteIDs) * re-refresh the popup and save to disk * note: * modal form doesn't seem to be able to * affect the popup permanently -- the new bars "leave" * when the modal dialog's Destroy() fires! * That's why we don't do this earlier... THIS.SetCurrentUserFavoriteIDs(THIS.cCurrentUserFavoriteIDs) ENDIF RETURN llReturn ENDPROC PROCEDURE dotableoutput && Looks at the current form/alias and invokes the _outputdialog class appropriately for a table. Scope 1 or all. Hooks mediator's PrepareOutputAlias() and CleanupOutputAlias(), for framework-enabled forms, and app.SetHTMLClass/SetHTMLStyleID for GENHTML. * this option looks at the current * form/alias for any form * if the form is enabled for * framework use, it can derive the * alias information with help of the * app mediator object LPARAMETERS tlOutputOneRecord LOCAL loDialog, loMediator, loActiveForm, liSession, lcAlias, ; lcCaption, lcScope, liRecno, llReturn, llInterrupted IF TYPE("_SCREEN.ActiveForm") = "O" loActiveForm = _SCREEN.ActiveForm loMediator = THIS.GetFormMediatorRef(loActiveForm) ENDIF liSession = SET("DATASESSION") DO CASE CASE TYPE("loActiveForm.Parent") = "O" SET DATASESSION TO (loActiveForm.Parent.DataSessionID) CASE VARTYPE(loActiveForm) = "O" SET DATASESSION TO (loActiveForm.DataSessionID) ENDCASE IF VARTYPE(loMediator) = "O" loMediator.PrepareOutputAlias() lcAlias = loMediator.cOutputAlias lcCaption = loMediator.cOutputCaption ENDIF IF EMPTY(lcAlias) lcAlias = ALIAS() ENDIF IF EMPTY(lcCaption) lcCaption = PROPER(lcAlias) ENDIF IF NOT ( EMPTY(lcAlias) OR EMPTY(RECCOUNT(lcAlias)) ) IF (NOT tlOutputOneRecord) llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. * we only have to worry about * this if we are * going to be using the * navigation features, which * may bring up a messagebox() ENDIF IF THIS.cusTableNav.CurrentTableAllowsNavigation(lcAlias) lcScope = "" ELSE lcScope = NULL ENDIF ELSE lcScope = "NEXT 1" ENDIF IF NOT ISNULL(lcScope) IF EOF(lcAlias) liRecno = 0 ELSE liRecno = RECNO(lcAlias) ENDIF ENDIF ENDIF IF (NOT ISNULL(lcScope)) AND ; VARTYPE(liRecno) = "N" AND ; (EMPTY(lcScope) OR liRecno # 0) IF NOT EMPTY(lcScope) lcCaption = lcCaption+"("+APP_OUTPUT_ONE_REC_LOC+")" ENDIF loDialog = THIS.DoModalDialogClass("_outputdialog","_reports", .T.) IF VARTYPE(loDialog) = "O" loDialog.cScope = lcScope loDialog.cAlias = lcAlias loDialog.Caption = loDialog.Caption + " " + lcCaption loDialog.lAddSourceNameToDropDown = .F. loDialog.cHTMLClass = THIS.SetHTMLClass(lcAlias,.T.) loDialog.cHTMLStyleID = THIS.SetHTMLStyleID(lcAlias, .T.) loDialog.Icon = THIS.cIcon loDialog.lPreventSourceChanges = .T. loDialog.cDisplayFontName = THIS.cTextDisplayFont loDialog.Show(1) loDialog = .NULL. llReturn = .T. ENDIF IF liRecno = 0 GO BOTTOM IN (lcAlias) SKIP IN (lcAlias) ELSE GO liRecno IN (lcAlias) ENDIF ENDIF IF VARTYPE(loMediator) = "O" loMediator.CleanupOutputAlias() ENDIF SET DATASESSION TO (liSession) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN llReturn ENDPROC PROCEDURE dotoolbar && Parallel to DoForm. Maintains toolbars collection. Pass a toolbar class library & class name. Uses THIS.iInitialToolbarPosition to set position. LPARAMETERS tcClassLib, tcClass ASSERT EMPTY(tcClassLib) OR VARTYPE(tcClassLib) = "C" ASSERT EMPTY(tcClass) OR VARTYPE(tcClass) = "C" LOCAL lcClass, loToolbar, lcClassLib, ; liElement, liIndex, liToolbars, lcToolbarName IF EMPTY(tcClass) RETURN 0 ENDIF IF NOT EMPTY(tcClassLib) lcClassLib = tcClassLib ENDIF lcClass = UPPER(ALLTRIM(tcClass)) liElement = 0 liToolbars = ALEN(THIS.aToolbars,1) FOR liIndex = 1 TO liToolbars loToolbar = THIS.aToolbars[liIndex,1] * do we have a free element to fill? IF VARTYPE(loToolbar) # "O" OR ; VARTYPE(THIS.aToolbars[liIndex,2]) # "N" ; OR THIS.aToolbars[liIndex,2] = 0 liElement = liIndex LOOP ENDIF * is this toolbar already instantiated? IF UPPER(loToolbar.Class) == lcClass * increment its counter THIS.aToolbars[liIndex,2] = THIS.aToolbars[liIndex,2]+1 loToolbar.Show && position or dock here? RETURN liIndex ENDIF ENDFOR IF liElement = 0 IF VARTYPE(THIS.aToolbars[1,1]) = "O" liElement = liToolbars+1 ELSE liElement = 1 ENDIF DIMENSION THIS.aToolbars[liElement,2] ENDIF THIS.aToolbars[liElement,2] = 0 IF VARTYPE(THIS.oFrame) = "O" AND (NOT WONTOP(THIS.oFrame.Name)) THIS.oFrame.Show() ENDIF THIS.aToolbars[liElement,1]=THIS.Instantiate(lcClass,lcClassLib) IF VARTYPE(THIS.aToolbars[liElement,1]) = "O" IF PEMSTATUS(THIS.aToolbars[liElement,1], "oApp",5) THIS.aToolbars[liElement,1].oApp = THIS ENDIF THIS.aToolbars[liElement,2] = 1 THIS.aToolbars(liElement,1).Dock(THIS.iInitialToolbarPosition) * THIS.aToolbars[liElement,1].Show() replaced by: THIS.ActivateFormInFrame(THIS.aToolbars[liElement,1]) ENDIF RETURN liElement ENDPROC PROCEDURE douserlogin && Invokes cUserLoginClass dialog. Returns (NOT EOF(THIS.cUserTableAlias)) to indicate success at locating a user. ASSERT USED(THIS.cUserTableAlias) * we're supposed to be setting a record pointer * in an open table here... IF (NOT THIS.lUserPreferences) RETURN .F. ENDIF LOCAL loForm loForm = THIS.DoModalDialogClass(THIS.cUserLogInClass, THIS.cUserLogInClassLib, .T.) IF VARTYPE(loForm) = "O" loForm.Show(1) RETURN (NOT EOF(THIS.cUserTableAlias)) ELSE RETURN .F. ENDIF ENDPROC PROCEDURE Error LPARAMETERS nError, cMethod, nLine THIS.iLastError = nError IF THIS.lSkipErrorHandling * special cases -- right * now this is done when * trying to USE the error log EXCLUSIVEly * for purging RETURN ENDIF THIS.cusError.Handle(nError,cMethod,nLine) LOCAL llFatal, llUserCancelled, lcCaller, lcProg, ; llNoCodeExecuting, liLevel, lcTemp llFatal = THIS.cusError.IsFatal() llUserCancelled = THIS.cusError.UserCancelled() IF NOT (llFatal OR llUserCancelled) liLevel = 0 lcCaller = "" lcProg = PROGRAM(0) DO WHILE .T. lcCaller = PROGRAM(liLevel) liLevel = liLevel + 1 lcProg = PROGRAM(liLevel) IF EMPTY(lcProg) OR (UPPER(lcProg) == UPPER(THIS.Name+".ERROR")) EXIT ENDIF ENDDO llNoCodeExecuting = (UPPER(lcCaller) == UPPER(THIS.Name+".READEVENTS")) ENDIF DO CASE CASE THIS.iLastError # nError * an error in the error handler! * this will have been taken care of * and we don't want to get * into a recursive situation CASE llFatal OR llUserCancelled IF THIS.lReadEvents lcTemp = THIS.cLastOnError ON ERROR &lcTemp * remove reference to App Object * in error handler *now* before * it can start messing about with * destroying itself ENDIF THIS.Release() CASE llNoCodeExecuting RETRY OTHERWISE RETURN ENDCASE ENDPROC PROCEDURE exporterrorlog && Invokes _outputdialog class to allow output of error log information. LOCAL lcTable, liSelect, lcAlias, loDialog, lcTableAlias, llReturn lcTable = THIS.cErrorLogTableName IF EMPTY(lcTable) OR NOT FILE(lcTable) MESSAGEBOX(ERRORVIEWER_UNAVAILABLE_LOC,MB_ICONINFORMATION,THIS.cCaption) RETURN ENDIF THIS.ClearLastError() liSelect = SELECT() lcAlias = "ExportErrors" IF USED(lcAlias) lcAlias = "E"+SYS(2015) ENDIF SELE 0 USE (lcTable) AGAIN SHARED lcTableAlias = ALIAS() IF (NOT THIS.IsErrorFree()) THIS.ClearLastError() SELECT (liSelect) RETURN ENDIF SELECT errstamp, ; MLINE (listing,1)+" "+MLINE(listing,3) AS listing, ; MLINE(usernotes,1) AS usernotes ; FROM (lcTable) ; INTO CURSOR (lcAlias) SELECT (lcAlias) USE IN (lcTableAlias) IF _TALLY > 0 loDialog = THIS.DoModalDialogClass("_outputdialog","_reports", .T.) IF VARTYPE(loDialog) = "O" loDialog.Icon = THIS.cIcon loDialog.cAlias = lcAlias loDialog.lPreventSourceChanges = .T. loDialog.cDisplayFontName = THIS.cTextDisplayFont loDialog.cHTMLClass = THIS.SetHTMLClass(lcAlias,.T.) loDialog.cHTMLStyleID = THIS.SetHTMLStyleID(lcAlias,.T.) loDialog.Show(1) loDialog = .NULL. llReturn = .T. ENDIF ELSE MESSAGEBOX(ERRORVIEWER_EMPTY_LOC,MB_ICONINFORMATION,THIS.cCaption) ENDIF IF USED(lcAlias) USE IN (lcAlias) ENDIF SELECT (liSelect) RETURN llReturn ENDPROC PROCEDURE filenotfoundmsgbox && Displays a File Not Found messagebox. LPARAMETERS tcFileName IF INLIST(_VFP.Startmode, 0, 4) MESSAGEBOX(APP_FILE_NOT_FOUND_LOC+":"+; CHR(13) + CHR(13)+ ; tcFileName,MB_ICONEXCLAMATION,THIS.cCaption) ELSE THIS.cusError.RecordServerError(; THIS.cCaption+ ": "+APP_FILE_NOT_FOUND_LOC) ENDIF ENDPROC PROCEDURE filluseroptionsarray && Moves the user table's UserOpts contents to aCurrentUserOpts. Array has 4 columns: property name, value, toggle property or SET, datasession or global attribute ASSERT USED(THIS.cUserTableAlias) IF TYPE(THIS.cUserTableAlias+".UserOpts") = "M" AND ; NOT EMPTY(EVAL(THIS.cUserTableAlias+".UserOpts")) RESTORE FROM MEMO (THIS.cUserTableAlias+".UserOpts") ADDITIVE * adds a local array, laOptions DIME THIS.aCurrentUserOpts[ALEN(laOptions,1),4] * array columns: property name, value, property or SET, datasession or global ACOPY(laOptions,THIS.aCurrentUserOpts) ENDIF ENDPROC PROCEDURE formisframeworkenabled && Reports the existance of a mediator object on a form. Uses THIS.cFormMediatorName to determine the naming convention for this object on the form. LPARAMETERS toForm RETURN (NOT ISNULL(THIS.GetFormMediatorRef(toForm))) ENDPROC PROCEDURE getcurrentalias && Wraps the cusTableNav member's GetCurrentAlias() method. RETURN THIS.cusTableNav.GetCurrentAlias() ENDPROC PROCEDURE getcurrenttopformref && Wraps cusWindowHandler's GetCurrentTopFormRef() method. RETURN THIS.cusWindowHandler.GetCurrentTopFormRef() ENDPROC PROCEDURE getformmediatorref && Returns a reference to a form's mediator object, or NULL if the form is not framework-enabled with a mediator object. LPARAMETERS toForm, tlForce IF VARTYPE(toForm) # "O" OR ; NOT (UPPER(toForm.BaseClass) == "FORM") RETURN NULL ENDIF LOCAL loMember, laCheck[1], loMediator, llExactSet loMediator = NULL llExactSet =(SET("EXACT") = "OFF") IF llExactSet SET EXACT ON ENDIF IF TYPE("toForm."+THIS.cFormMediatorName+".Name") = "C" loMediator = EVAL("toForm."+THIS.cFormMediatorName) IF ACLASS(laCheck,loMediator) = 0 OR ; ASCAN(laCheck,UPPER(APP_MEDIATOR_SUPERCLASS)) = 0 loMediator = NULL ENDIF ENDIF IF ISNULL(loMediator) AND toForm.ControlCount > 0 * try to find a member of the appropriate * class; slower than the above but still worthwhile * for generic dialogs that might not use the * appropriate mediator name for this app. FOR EACH loMember in toForm.Controls IF VARTYPE(loMember) = "O" ; AND ACLASS(laCheck,loMember) > 0 AND ; ASCAN(laCheck,UPPER(APP_MEDIATOR_SUPERCLASS)) > 0 loMediator = loMember EXIT ENDIF ENDFOR ENDIF IF ISNULL(loMediator) AND tlForce * create one loMediator = THIS.CreateFormMediator(toForm) ENDIF IF llExactSet SET EXACT OFF ENDIF RETURN loMediator ENDPROC PROCEDURE getresourcefilename && Pass: tcSource, tcExtList, tlSuppressMsg, looks for file with any of extensions in list, in order, to RETURN the appropriate pathed name ("" if none, with File Not Found msg unless tlSuppressMsg). Ignores tcExtlList if explicit ext passed in tcSource. LPARAMETERS tcSourceFileName, tcExtensionList, tlSuppressMessage ASSERT VARTYPE(tcSourceFileName) = "C" AND NOT EMPTY(tcSourceFileName) ASSERT EMPTY(tcExtensionList) OR VARTYPE(tcExtensionList) = "C" * Try out any one of a number of extensions in a delimited * list if the filename-as-delivered is not found. * The "." characer is considered the delimiter for this * list, as it forms an integral part of the definition of a * file extension. * If *no* "." characters are found in the list but the list * is passed with a string containing spaces, then the * list will be assumed to be a list of space-delimited * extensions. * Filenames passed in a list will be tried in the order passed; * see THIS.DoProgram() for a potential list by precedence. * It's up to the calling program to figure out * what extensions are appropriate. LOCAL lcSourceFileName, lcTargetFileName, lcExtList, ; lcExt, liExts, liTryExt, liThisExtStarts,liNextExtStarts IF VARTYPE(tcSourceFileName) # "C" OR EMPTY(tcSourceFileName) RETURN "" ENDIF lcSourceFileName = ALLTR(tcSourceFileName) IF EMPTY(tcExtensionList) OR ("." $ tcSourceFileName) lcTargetFileName = LOWER(FULLPATH(lcSourceFileName)) IF NOT FILE(lcTargetFileName) lcTargetFileName = "" ENDIF ELSE lcExtList = ALLTRIM(tcExtensionList) liExts = OCCURS(".",lcExtList) IF liExts = 0 lcExtList = STRTRAN(tcExtensionList," ",".") ELSE lcExtList = STRTRAN(tcExtensionList," ","") ENDIF IF LEFT(lcExtList,1) # "." lcExtList = "."+lcExtList ENDIF liExts = OCCURS(".",lcExtList) FOR liTryExt = 1 TO liExts liThisExtStarts = AT(".",lcExtList,liTryExt) IF liTryExt # liExts liNextExtStarts = AT(".",lcExtList,liTryExt + 1) lcExt = SUBSTR(lcExtList,liThisExtStarts,liNextExtStarts-liThisExtStarts) ELSE lcExt = SUBSTR(lcExtList,liThisExtStarts) ENDIF lcTargetFileName = LOWER(FULLPATH(lcSourceFileName+lcExt)) IF FILE(lcTargetFileName) EXIT ELSE lcTargetFileName = "" ENDIF ENDFOR ENDIF IF EMPTY(lcTargetFileName) AND NOT tlSuppressMessage THIS.FileNotFoundMsgBox(tcSourceFileName) ENDIF RETURN lcTargetFileName ENDPROC PROCEDURE getuseroptionsetting && Takes option name and array (usually aCurrentUserOpts) and returns current value for that option, NULL if not found. LPARAMETERS tcOption,taOptionArray IF VARTYPE(tcOption) # "C" RETURN .NULL. ENDIF IF PCOUNT() = 2 AND TYPE("taOptionArray[1,1]") # "C" RETURN .NULL. ENDIF LOCAL liElement, liRow, llExactSet LOCAL ARRAY laTemp[1] IF PCOUNT() = 2 ACOPY(taOptionArray,laTemp) ELSE ACOPY(THIS.aCurrentUserOpts,laTemp) ENDIF llExactSet = (SET("EXACT") = "OFF") IF llExactSet SET EXACT ON ENDIF liELEMENT = ASCAN(laTemp,tcOption) IF llExactSet SET EXACT OFF ENDIF IF NOT EMPTY(liElement) liRow = ASUBSCRIPT(laTemp,liElement,1) RETURN laTemp[liRow,2] ELSE RETURN .NULL. ENDIF ENDPROC PROCEDURE gobottom && Wraps cusTableNav member's GoBottom() method. THIS.lNoInterrupt = .T. THIS.cusTableNav.GoBottom() THIS.lNoInterrupt = .F. ENDPROC PROCEDURE gonext && Wraps cusTableNav member's GoNext() method. THIS.lNoInterrupt = .T. THIS.cusTableNav.GoNext() THIS.lNoInterrupt = .F. ENDPROC PROCEDURE goprevious && Wraps cusTableNav member's GoPrevious() method. THIS.lNoInterrupt = .T. THIS.cusTableNav.GoPrevious() THIS.lNoInterrupt = .F. ENDPROC PROCEDURE gotop && Wraps cusTableNav member's GoTop() method. THIS.lNoInterrupt = .T. THIS.cusTableNav.GoTop() THIS.lNoInterrupt = .F. ENDPROC PROCEDURE gotorecord && Wraps cusTableNav member's GoToRecord() method. LPARAMETERS tiRecord THIS.lNoInterrupt = .T. THIS.cusTableNav.GoToRecord(tiRecord) THIS.lNoInterrupt = .F. ENDPROC PROCEDURE handleprojectwindow && Hides a project with the name stored in THIS.cProjectName on startup, if it is showing, and restores it when the app object Destroys. LPARAMETERS tlShow IF VARTYPE(THIS.cProjectName) = "C" AND ; NOT EMPTY(THIS.cProjectName) AND ; WEXIST( APP_PM_WIN_TITLE_LOC +THIS.cProjectName) DO CASE CASE tlShow AND (NOT WVISIBLE( APP_PM_WIN_TITLE_LOC +THIS.cProjectName)) SHOW WINDOW ( APP_PM_WIN_TITLE_LOC +THIS.cProjectName) CASE tlShow * no problem OTHERWISE HIDE WINDOW ( APP_PM_WIN_TITLE_LOC +THIS.cProjectName) ENDCASE ELSE THIS.cProjectName = "" * prevent SHOWing it later * if we aren't responsible for HIDEing it * at this point, even if it does exist ENDIF ENDPROC PROCEDURE iinitialtoolbarposition_assign LPARAMETERS tiNewVal IF VARTYPE(tiNewVal) # "N" OR NOT INLIST(tiNewVal,-1,0,1,2,3) THIS.iInitialToolbarPosition = 0 ELSE THIS.iInitialToolbarPosition = tiNewVal ENDIF ENDPROC PROCEDURE ilasterror_access RETURN THIS.ilasterror ENDPROC PROTECTED PROCEDURE Init IF NOT DODEFAULT() RETURN .F. ENDIF THIS.cIcon = THIS.GetResourceFileName(THIS.cIcon, ".ico", .T.) THIS.cImage = THIS.GetResourceFileName(THIS.cImage, ".bmp .ico .gif", .T.) IF VARTYPE(THIS.cReference) = "C" AND (NOT EMPTY(THIS.cReference)) THIS.cReference = THIS.cReference ENDIF IF NOT THIS.SetAppFileNames() RETURN .F. ENDIF IF VERSION(2) = 0 AND _VFP.StartMode = 4 AND ; UPPER(THIS.cClassContainerFileName) == UPPER(THIS.cAppFileName) * if the running EXE is this file, and this file * is not set up to be Read Events, make it Read Events anyway. THIS.lReadEvents = .T. ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE instantiate && RETURNs object reference -- pass classname, classlib, APP/EXE if library is external, string of delimited parameters to be macro-executed. If being added as a member, also pass container ref plus membername if it's not OK to use unique/generated name. LPARAMETERS tcClass, tcClassLib, tcClassContainerFileName, ; tcParamString, toParent, tcMemberName *&* new third param for IN support *&* will default to "" for ReadEvents, THIS.cClassContainerFileName *&* for non-ReadEvents... LOCAL loReturn, lcMemberName, lcClass, lcClassLib, lcContainer ASSERT VARTYPE(tcClass) = "C" AND (NOT EMPTY(tcClass)) ASSERT EMPTY(tcClassLib) OR VARTYPE(tcClassLib) = "C" ASSERT EMPTY(tcClassContainerFileName) OR ; (VARTYPE(tcClassContainerFileName) = "C" AND ; NOT EMPTY(SYS(2000,FULLPATH(tcClassContainerFileName)))) ASSERT EMPTY(tcParamString) OR VARTYPE(tcParamString) = "C" ASSERT VARTYPE(toParent) = "O" OR EMPTY(toParent) ASSERT EMPTY(tcMemberName) OR VARTYPE(tcMemberName) = "C" lcClass = ALLTRIM(tcClass) DO CASE CASE VARTYPE(tcClassLib) # "C" * default library is the app object's lcClassLib = THIS.ClassLibrary lcContainer = THIS.cClassContainerFileName CASE EMPTY(tcClassLib) * somebody has already SET CLASSLIB * and passed a null string to indicate this lcClassLib = "" lcContainer = "" OTHERWISE lcClassLib = ALLTRIM(tcClassLib) IF VARTYPE(tcClassContainerFileName) = "C" lcContainer = ALLTRIM(tcClassContainerFileName) ELSE IF EMPTY(SYS(2000,lcClassLib)) AND ; EMPTY(SYS(2000,lcClassLib+".VCX")) * not on disk, gotta find it somewhere... * like the product, we are assuming * that if the extension isn't used * it's a VCX, not a PRG/FXP lcContainer = THIS.cClassContainerFileName ELSE * found it! lcContainer = "" ENDIF ENDIF ENDCASE loReturn = .NULL. lcClassLib = THIS.GetResourceFileName(lcClassLib,".vcx .fxp .prg") IF NOT EMPTY(lcContainer) lcContainer = THIS.GetResourceFileName(lcContainer,".app .exe") ENDIF IF (EMPTY(lcClassLib) AND NOT EMPTY(tcClassLib)) OR ; (EMPTY(lcContainer) AND NOT EMPTY(tcClassContainerFileName)) RETURN .F. ENDIF IF VERSION(2) = 0 AND ; UPPER(JUSTEXT(lcClassLib)) == "PRG" IF NOT EMPTY(SYS(2000,lcClassLib)) * file is on disk for sure, and * we can't use it if it is built into * another file like this... lcContainer = "" COMPILE (lcClassLib) lcClassLib = FORCEEXT(lcClassLib,"FXP") ELSE RETURN .F. ENDIF ENDIF IF VARTYPE(toParent) = "O" IF VARTYPE(tcMemberName)= "C" lcMemberName = tcMemberName ELSE lcMemberName = "C"+SYS(2015) ENDIF ASSERT TYPE("toParent."+lcMemberName) # "O" ; MESSAGE toParent.&lcMemberName..Name + " "+APP_ALREADY_EXISTS_LOC+"." THIS.ClearLastError() IF EMPTY(tcParamString) toParent.NewObject(lcMemberName,lcClass,lcClassLib,lcContainer) ELSE toParent.NewObject(lcMemberName,lcClass,lcClassLib,lcContainer,&tcParamString.) ENDIF IF THIS.IsErrorFree() loReturn = EVAL("toParent."+lcMemberName) ENDIF ELSE IF EMPTY(tcParamString) loReturn = NEWOBJECT(lcClass,lcClassLib,lcContainer) ELSE loReturn = NEWOBJECT(lcClass,lcClassLib, lcContainer,&tcParamString.) ENDIF ENDIF RETURN loReturn ENDPROC PROCEDURE iserrorfree && RETURNs ISNULL(THIS.iLastError) -- See THIS.ClearLastError(). RETURN (ISNULL(THIS.iLastError)) ENDPROC PROTECTED PROCEDURE lgomenu_assign LPARAMETERS tlGoMenuNeeded IF EMPTY(THIS.cGoMenuFile) RETURN .F. ENDIF DO CASE CASE tlGoMenuNeeded = THIS.lGoMenu * nothing to worry about CASE tlGoMenuNeeded THIS.lGoMenu = .T. IF TYPE([CNTBAR("_mGo")]) = "U" DO CASE CASE VARTYPE(THIS.oFrame) # "O" THIS.DoMenu(THIS.cGoMenuFile) CASE NOT EMPTY(THIS.oFrame.cMenuName) THIS.DoMenu(THIS.cGoMenuFile, .F.) OTHERWISE ENDCASE ELSE * already defined, just show the pad DO CASE CASE VARTYPE(THIS.oFrame) # "O" DEFINE PAD _msm_Go OF _MSYSMENU ; PROMPT APP_GO_PAD_LOC COLOR SCHEME 3 ; BEFORE _msm_windo ; KEY APP_GO_PAD_HOTKEY_LOC, [APP_GO_PAD_HOTKEY_LOC] ; MESSAGE APP_GO_MESSAGE_LOC ON PAD _msm_Go OF _MSYSMENU ACTIVATE POPUP _mgo CASE NOT EMPTY(THIS.oFrame.cMenuName) DEFINE PAD _msm_Go OF (THIS.oFrame.cMenuName); PROMPT APP_GO_PAD_LOC COLOR SCHEME 3 ; BEFORE _msm_windo ; KEY APP_GO_PAD_HOTKEY_LOC, [APP_GO_PAD_HOTKEY_LOC] ON PAD _msm_Go OF (THIS.oFrame.cMenuName) ACTIVATE POPUP _mgo OTHERWISE ENDCASE ENDIF OTHERWISE THIS.lGoMenu = .F. * for now, I am not putting menu shortcut keys on the * popup and I am just leaving it DEFINEd and inaccessible * for speed reasons -- so am not releasing it once defined DO CASE CASE VARTYPE(THIS.oFrame) # "O" RELEASE PAD _msm_Go OF _MSYSMENU * RELEASE POPUP _mGo EXTENDED CASE NOT EMPTY(THIS.oFrame.cMenuName) RELEASE PAD _msm_Go OF (THIS.oFrame.cMenuName) * RELEASE POPUP _mGo EXTENDED OTHERWISE ENDCASE ENDCASE RETURN ENDPROC PROCEDURE lnavtoolbar_assign LPARAMETERS tlNavToolbarNeeded IF EMPTY(THIS.cNavToolbarClass) RETURN .F. ENDIF DO CASE CASE tlNavToolbarNeeded = THIS.lNavToolbar THIS.lNavToolbar = tlNavToolbarNeeded * nothing to worry about CASE tlNavToolbarNeeded THIS.lNavToolbar = .T. IF VARTYPE(THIS.oNavToolbar) # "O" LOCAL liIndex liIndex = THIS.DoToolbar(THIS.cNavToolbarClassLib,THIS.cNavToolbarClass) THIS.oNavToolbar = THIS.aToolbars[liIndex,1] ELSE IF NOT THIS.oNavToolBar.Visible THIS.oNavToolbar.Show() ENDIF ENDIF OTHERWISE THIS.lNavToolbar = .F. IF (VARTYPE(THIS.oNavToolbar)= "O") AND THIS.oNavToolbar.Visible THIS.oNavToolbar.Hide() ENDIF ENDCASE RETURN ENDPROC PROCEDURE lnointerrupt_assign LPARAMETERS tvNewVal IF VARTYPE(tvNewVal) = "L" AND ; tvNewVal # THIS.lNoInterrupt WITH THIS.tmrRefresh IF tvNewVal .Interval = 0 ELSE .Interval = .iRegularInterval ENDIF ENDWITH THIS.lNoInterrupt = tvNewVal ENDIF ENDPROC PROCEDURE lusercanchangepassword_access *To do: Modify this routine for the Access method RETURN THIS.lusercanchangepassword ENDPROC PROCEDURE lusercanchangepassword_assign LPARAMETERS m.vNewVal *To do: Modify this routine for the Assign method THIS.lusercanchangepassword = m.vNewVal ENDPROC PROCEDURE onshutdown && Occurs when the user attempts to exit Visual FoxPro by pressing _SCREEN close button or the close button on a framework top form MDI frame. LPARAMETERS tlCalledFromTopForm LOCAL llReturn, llInterrupted DO CASE CASE INLIST(_VFP.StartMode,1,2,3,5) * we really shouldn't be here at all llReturn = .T. CASE TYPE("_SCREEN.ActiveForm.Parent") = "O" AND ; _SCREEN.ActiveForm.Parent.WindowType = 1 && modal * formset overrides form on this one ?? CHR(7) CASE TYPE("_SCREEN.ActiveForm") = "O" AND ; _SCREEN.ActiveForm.WindowType = 1 ?? CHR(7) OTHERWISE llReturn = .T. ENDCASE IF llReturn llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF llReturn = (INLIST(_VFP.StartMode,1,2,3,5) OR ; (MESSAGEBOX(APP_READY_TO_SHUTDOWN_LOC, ; MB_YESNO+MB_ICONQUESTION, ; THIS.cCaption)= IDYES)) IF llReturn llReturn = THIS.ReleaseForms() ENDIF IF llInterrupted THIS.lNoInterrupt = .F. ENDIF ENDIF IF llReturn IF NOT tlCalledFromTopForm THIS.Release() QUIT ENDIF ENDIF RETURN llReturn ENDPROC PROCEDURE purgeerrorlog && Zaps current error log with appropriate confirmation and checks. LOCAL lcTable, liSelect, lcAlias, llSafety lcTable = THIS.cErrorLogTableName IF EMPTY(lcTable) OR NOT FILE(lcTable) MESSAGEBOX(ERRORVIEWER_UNAVAILABLE_LOC,MB_ICONINFORMATION,THIS.cCaption) RETURN ENDIF THIS.ClearLastError() THIS.lSkipErrorHandling = .T. liSelect = SELECT() lcAlias = "E"+SYS(2015) USE (lcTable) ALIAS (lcAlias) EXCLUSIVE IN 0 THIS.lSkipErrorHandling = .F. IF (NOT THIS.IsErrorFree()) OR (NOT USED(lcAlias)) THIS.ClearLastError() MESSAGEBOX(ERRORVIEWER_IN_USE_LOC,MB_ICONSTOP,THIS.cCaption) IF USED(lcAlias) USE IN (lcAlias) ENDIF RETURN ENDIF IF NOT (RECCOUNT(lcAlias) = 0) llSafety = SET("SAFETY") = "OFF" IF llSafety SET SAFETY ON ENDIF SELECT (lcAlias) ZAP SELECT (liSelect) IF llSafety SET SAFETY OFF ENDIF ENDIF IF (RECCOUNT(lcAlias) = 0) MESSAGEBOX(ERRORVIEWER_EMPTY_LOC,MB_ICONINFORMATION,THIS.cCaption) ENDIF USE IN (lcAlias) RETURN ENDPROC PROCEDURE querydatachanged && Wraps cusDataSession member's DataChanged() method. LPARAMETERS toSession, tiChangeMode LOCAL llReturn, llInterrupted llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF llReturn = THIS.cusDataSession.DataChanged(toSession,tiChangeMode) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN llReturn ENDPROC PROCEDURE querydatasessionunload && Wraps cusDataSession member's Queryunload() method. LPARAMETERS tlDataChangeAlreadyConfirmed, toSession ASSERT VARTYPE(tlDataChangeAlreadyConfirmed) = "L" ASSERT TYPE("toSession.DataSessionID") = "N" OR ; TYPE("_SCREEN.ActiveForm") = "O" LOCAL llDataHandled, loSession, llInterrupted llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF IF TYPE("toSession.DataSessionID") = "N" loSession = toSession ELSE loSession = _SCREEN.ActiveForm ENDIF IF tlDataChangeAlreadyConfirmed OR ; THIS.cusDataSession.DataChanged(loSession) llDataHandled = ; THIS.cusDataSession.QueryUnload(.t., loSession) ELSE llDataHandled = .T. ENDIF IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN llDataHandled ENDPROC PROCEDURE readevents && Starts read events mode. THIS.ClearLastError() IF THIS.lReadEvents READ EVENTS ENDIF ENDPROC PROCEDURE refreshfavoritepopup && DEFINEs BARs for Favorites menu popup using THIS.cCurrentUserFavoriteIDs. IF (NOT THIS.lFavorites) OR ; TYPE("CNTBAR(THIS.cFavoritePopupName)") # "N" RETURN .F. ENDIF LOCAL lcThisRef, lcStatement, lcFavoriteID, ; liBarNo, lcAlias, liSelect, laFavorites[1] lcThisRef = THIS.cReference * release all but top bars: FOR liBarNo = 4 TO CNTBAR(THIS.cFavoritePopupName) RELEASE BAR liBarNo OF (THIS.cFavoritePopupName) ENDFOR liBarNo = 3 * open metatable THIS.ClearLastError() IF NOT EMPTY(THIS.cMetaTable) lcAlias = "M"+SYS(2015) USE (THIS.cMetaTable) ALIAS (lcAlias) AGAIN SHARED IN 0 ENDIF IF NOT (THIS.IsErrorFree()) SET SKIP OF BAR 1 OF (THIS.cFavoritePopupName) .T. SET SKIP OF BAR 2 OF (THIS.cFavoritePopupName) .T. RETURN ENDIF liSelect = SELECT() IF NOT EMPTY(lcAlias) SELECT (lcAlias) ENDIF * now add rest of bars: IF NOT EMPTY(THIS.cCurrentUserFavoriteIDs) ALINES(laFavorites,THIS.cCurrentUserFavoriteIDs,.T.) STORE "" TO lcFavoriteID, lcStatement FOR EACH lcFavoriteID IN laFavorites IF NOT EMPTY(lcFavoriteID) lcFavoriteID = UPPER(ALLTR(lcFavoriteID)) lcStatement = "" IF FILE(lcFavoriteID) liBarNo = liBarNo + 1 DEFINE BAR liBarNo OF (THIS.cFavoritePopupName) ; PROMPT lcFavoriteID lcStatement = lcThisRef+"." lcStatement = lcStatement+"DoFile" lcStatement = lcStatement + "(["+lcFavoriteID+"])" ELSE IF NOT EMPTY(lcAlias) AND ; THIS.SeekMetaTableFavoriteID(lcFavoriteID,lcAlias) liBarNo = liBarNo + 1 DEFINE BAR liBarNo OF (THIS.cFavoritePopupName) ; PROMPT ALLTR(Doc_Descr) DO CASE CASE NOT EMPTY(Alt_Exec) lcStatement = ALLTRIM(Alt_Exec) CASE Doc_Wrap lcStatement = "DO (["+ ALLTRIM(Doc_Exec)+"])" CASE Doc_Type = PJX_META_DOC_REPORT_TYPE lcStatement = lcThisRef+".DoReport(["+; ALLTRIM(Doc_Exec)+"],["+ ; ALLTRIM(Doc_Descr)+"])" CASE Doc_Type = PJX_META_DOC_FORM_TYPE lcStatement = lcThisRef+".DoForm(["+ ; ALLTRIM(Doc_Exec)+"],["+ ; ALLTRIM(Doc_Class)+"],"+; IIF(Doc_Single,".T.,",".F.,")+; IIF(Doc_NoShow,".T.,",".F.,")+; IIF(Doc_Go,".T.,",".F.,")+; IIF(Doc_Nav,".T.",".F.")+")" OTHERWISE * ... ? ENDCASE ENDIF ENDIF IF NOT EMPTY(lcStatement) ON SELECTION BAR liBarNo OF ; (THIS.cFavoritePopupName) &lcStatement ENDIF ENDIF ENDFOR ENDIF * no possible docs? got all possible docs as favorites? didn't get any favorites? * the first two possibilities are no longer possible , since * we allow GETFILE() picking of favorites... * however it's still possible not to be able to clear any favorites * because there are none saved SET SKIP OF BAR 2 OF (THIS.cFavoritePopupName) (liBarNo = 3) IF NOT EMPTY(lcAlias) USE IN (lcAlias) ENDIF SELECT (liSelect) ENDPROC PROCEDURE refreshformscollection && Refresh forms collection arrays and counters. LOCAL lnCount,lnCount2 THIS.ClearLastError() lnCount=1 DO WHILE lnCount<=THIS.nFormCount IF VARTYPE(THIS.aForms[lnCount])="O" lnCount=lnCount+1 LOOP ENDIF FOR lnCount2 = lnCount TO (THIS.nFormCount-1) THIS.aForms[lnCount2]=THIS.aForms[lnCount2+1] THIS.aForms[lnCount2+1]=.NULL. THIS.aFormNames[lnCount2]=THIS.aFormNames[lnCount2+1] THIS.aFormNames[lnCount2+1]="" ENDFOR THIS.nFormCount=THIS.nFormCount-1 IF THIS.nFormCount=0 EXIT ENDIF DIMENSION THIS.aForms[THIS.nFormCount],THIS.aFormNames[THIS.nFormCount] ENDDO IF THIS.nFormCount=0 THIS.ResetFormsCollection ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE refreshtoolbars && Called by member timer and at any other time you need to synch toolbars to current environment. Iterates through toolbar collection calling Refresh methods so that it doesn't assume any tbr class. IF THIS.lNoInterrupt * shouldn't happen RETURN ENDIF LOCAL loToolbar FOR EACH loToolbar IN THIS.aToolbars IF VARTYPE(loToolbar) = "O" loToolbar.Refresh ENDIF ENDFOR ENDPROC PROCEDURE release LPARAMETERS tlForce IF NOT THIS.ReleaseSessions(tlForce) RETURN .F. ENDIF IF NOT THIS.ReleaseForms(tlForce) RETURN .F. ENDIF THIS.lNoInterrupt = .T. THIS.ReleaseContextMenus(tlForce) THIS.ReleaseToolbars(tlForce) THIS.ReleaseCollaborators() THIS.ReleaseFrame() THIS.ClearEvents() RELEASE THIS ENDPROC PROCEDURE releasecollaborators && Manages release of collaborative objects THIS.ClearLastError() LOCAL liMemberIndex, loMember FOR liMemberIndex = 1 TO ALEN(THIS.aCollaborators) loMember = THIS.aCollaborators[liMemberIndex] IF VARTYPE(loMember) = "O" IF TYPE("loMember.Parent") = "O" loMember.Parent.RemoveObject(loMember.Name) ELSE * otherwise it was just done with a CREATEOBJECT, IF PEMSTATUS(loMember,"Release",5) loMember.Release() ENDIF ENDIF ENDIF * the following should get rid of the object, if any: loMember = NULL THIS.aCollaborators[liMemberIndex] = NULL ENDFOR RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE releasecontextmenu && Manages release of a single context menu and the context menu collection. LPARAMETERS tiMenuIndex, tlForce ASSERT VARTYPE(tiMenuIndex) = "N" AND ; BETWEEN(tiMenuIndex,1,ALEN(THIS.aContextMenus,1)) ASSERT VARTYPE(tlForce) = "L" * this function expects an index from the context menu array. * see comments in the ReleaseToolbar method. THIS.ClearLastError() IF PCOUNT()=0 OR EMPTY(tiMenuIndex) RETURN .F. ENDIF LOCAL liCurrentMenuRefCount IF VARTYPE(THIS.aContextMenus[tiMenuIndex,2]) # "N" liCurrentMenuRefCount = 0 ELSE liCurrentMenuRefCount = THIS.aContextMenus[tiMenuIndex,2] ENDIF IF tlForce OR liCurrentMenuRefCount <= 1 IF VARTYPE(THIS.oFrame) # "O" RELEASE PAD (THIS.aContextMenus[tiMenuIndex,3]) OF _MSYSMENU ELSE RELEASE PAD (THIS.aContextMenus[tiMenuIndex,3]) OF (THIS.oFrame.cMenuName) ENDIF RELEASE POPUP (THIS.aContextMenus[tiMenuIndex,4]) EXTENDED STORE .F. TO THIS.aContextMenus[tiMenuIndex,1], ; THIS.aContextMenus[tiMenuIndex,2], ; THIS.aContextMenus[tiMenuIndex,3], ; THIS.aContextMenus[tiMenuIndex,4] ELSE THIS.aContextMenus[tiMenuIndex,2] = liCurrentMenuRefCount - 1 ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE releasecontextmenus && Releases all context menus. LPARAMETERS tlForce LOCAL liMenu, liMenuCount THIS.ClearLastError() liMenuCount = ALEN(THIS.aContextMenus,1) FOR liMenu = 1 TO liMenuCount IF VARTYPE(THIS.aContextMenus[liMenu,1]) = "C" AND ; NOT THIS.ReleaseContextMenu(liMenu, .T.) IF NOT tlForce RETURN .F. ENDIF ENDIF ENDFOR RELEASE POPUP _mGo EXTENDED RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE releaseform && Release specific or active form and manages forms collection. LPARAMETERS toForm THIS.ClearLastError() IF PCOUNT()=0 IF TYPE("_SCREEN.ActiveForm")= "O" _SCREEN.ActiveForm.Release() ENDIF ELSE IF VARTYPE(toForm)="O" toForm.Release() ENDIF ENDIF THIS.RefreshFormsCollection RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE releaseforms && Release all application forms from memory and the forms collection. LPARAMETERS tlForce LOCAL lnFormCount THIS.RefreshFormsCollection IF THIS.nFormCount = 0 RETURN ENDIF LOCAL loForm, loMemberForm, liResult, llInterrupted llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF FOR EACH loForm IN THIS.aForms IF VARTYPE(loForm) # "O" OR ; NOT INLIST("#"+UPPER(loForm.BaseClass)+"#","#FORMSET#","#FORM#") LOOP ENDIF IF tlForce THIS.DataRevert(.T.,.F.,loForm,.T.) ELSE IF NOT THIS.QueryDataSessionUnload(.F.,loForm) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN .F. ENDIF ENDIF ENDFOR * only once they have confirmed all possible dataupdating/cancelling * out of the process can we begin to actually close forms. DO WHILE THIS.nFormCount>0 lnFormCount=THIS.nFormCount THIS.ReleaseForm(THIS.aForms[lnFormCount]) IF THIS.nFormCount=lnFormCount IF NOT tlForce IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN .F. ENDIF ENDIF ENDDO IF llInterrupted THIS.lNoInterrupt = .F. ENDIF ENDPROC PROCEDURE releaseframe && Releases top form/MDI frame. IF VARTYPE(THIS.oFrame) = "O" THIS.oFrame.oApp = .NULL. THIS.oFrame.Release() THIS.oFrame = .NULL. ENDIF ENDPROC PROCEDURE releasesessions && Releases all mediated datasession collaborator objects LPARAMETERS tlForce LOCAL loCollaborator, liMemberIndex, llInterrupted llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF FOR EACH loCollaborator IN THIS.aCollaborators IF VARTYPE(loCollaborator) # "O" ; OR NOT PEMSTATUS(loCollaborator,"DataSessionID",5) LOOP ENDIF IF tlForce THIS.DataRevert(.T.,.F.,loCollaborator) ELSE DO CASE CASE THIS.iQueryUnloadResultForNonVisualSessions = 0 THIS.DataRevert(.T.,.F.,loCollaborator) CASE THIS.iQueryUnloadResultForNonVisualSessions = 1 THIS.DataUpdate(.T.,.F.,loCollaborator) OTHERWISE IF NOT THIS.QueryDataSessionUnload(.F.,loCollaborator) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN .F. ENDIF ENDCASE ENDIF ENDFOR * only once they have confirmed all possible dataupdating/cancelling * out of the process do we begin to actually close sessions, just as with forms FOR liMemberIndex = 1 TO ALEN(THIS.aCollaborators) loCollaborator = THIS.aCollaborators[liMemberIndex] IF VARTYPE(loCollaborator) # "O" ; OR NOT PEMSTATUS(loCollaborator,"DataSessionID",5) LOOP ENDIF IF TYPE("loCollaborator.Parent") = "O" loCollaborator.Parent.RemoveObject(loCollaborator.Name) ELSE IF PEMSTATUS(loCollaborator,"Release",5) loCollaborator.Release() ENDIF ENDIF loCollaborator = NULL THIS.aCollaborators[liMemberIndex] = NULL ENDFOR IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE releasetoolbar && Parallel to ReleaseForm. Maintains toolbars collection. LPARAMETERS tiToolbarIndex, tlForce ASSERT VARTYPE(tiToolbarIndex) = "N" AND ; BETWEEN(tiToolbarIndex,1,ALEN(THIS.aToolbars,1)) ASSERT VARTYPE(tlForce) = "L" * this function expects an index from the toolbar array. * The second parameter normally comes from the * application releasing all toolbars by ReleaseToolbars() * or from some other manager releasing all forms of some * particular type, which represent all the "clients" of * this toolbar. In either case they would normally * use the tlForce parameter. * OTOH you pass can pass the index of the toolbar from * a single client of the toolbar, such as a form, * which would have kept a record of this reference when it * issued an app.dotoolbar() on its load. (DoToolbar returns * this index). WHen the form releases it wants * to notify the application that it doesn't need the toolbar * any more. The client form has no way of knowing * how many other clients may be using this toolbar, so tlForce * is not used. THIS.ClearLastError() IF PCOUNT()=0 OR EMPTY(tiToolbarIndex) RETURN .F. ENDIF LOCAL liCurrentToolbarRefCount IF VARTYPE(THIS.aToolbars[tiToolbarIndex,2]) # "N" liCurrentToobarRefCount = 0 ELSE liCurrentToolbarRefCount = THIS.aToolbars[tiToolbarIndex,2] ENDIF * toolbars don't have a RELEASE method by default, * and I don't want to assume any particular baseclass, * which is why I'm using the toolbar collection index * instead * release if this is the last reference to this * toolbar or if we are releasing all toolbars IF tlForce OR liCurrentToolbarRefCount <= 1 IF VARTYPE(THIS.aToolbars[tiToolbarIndex,1]) = "O" THIS.aToolbars[tiToolbarIndex,1].Release() ENDIF THIS.aToolbars[tiToolbarIndex,1] = .NULL. THIS.aToolbars[tiToolbarIndex,2] = 0 ELSE THIS.aToolbars[tiToolbarIndex,2] = liCurrentToolbarRefCount - 1 ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE releasetoolbars && Parallel to ReleaseForms. Iterates through toolbar collection LPARAMETERS tlForce LOCAL liToolbar, liToolbarCount, llInterrupted THIS.ClearLastError() llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF liToolbarCount = ALEN(THIS.aToolbars,1) FOR liToolbar = 1 TO liToolbarCount IF VARTYPE(THIS.aToolbars[liToolbar,1]) = "O" AND ; NOT THIS.ReleaseToolbar(liToolbar, .T.) IF NOT tlForce IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN .F. ENDIF ENDIF ENDFOR THIS.oNavToolbar = .NULL. && can't hurt IF llInterrupted THIS.lNoInterrupt = .F. ENDIF RETURN (THIS.IsErrorFree()) ENDPROC PROTECTED PROCEDURE resetformscollection && Reset arrays and counters of forms collection. THIS.nFormCount=0 DIMENSION THIS.aForms[1],THIS.aFormNames[1] THIS.aForms=.NULL. THIS.aFormNames="" ENDPROC PROTECTED PROCEDURE restoreenvironment && Restores environment settings. IF THIS.lRestoredEnvironment OR ; (NOT THIS.lSavedEnvironment) RETURN .T. ENDIF THIS.ClearLastError() LOCAL lcTemp IF THIS.lReadEvents lcTemp = THIS.cLastOnShutDown ON SHUTDOWN &lcTemp lcTemp = THIS.cLastOnError ON ERROR &lcTemp lcTemp = THIS.cLastMacKey SET MACKEY TO &lcTemp SET PATH TO (THIS.cLastPath) CD (THIS.cLastDirectory) IF FILE(THIS.cMacroSaveFile) CLEAR MACROS && restore macros is additive RESTORE MACROS FROM (THIS.cMacroSaveFile) ERASE (THIS.cMacroSaveFile) NORECYCLE ENDIF IF EMPTY(THIS.cFrameClass) AND (NOT EMPTY(THIS.cStartUpMenu)) RELEASE MENU _MSYSMENU EXTENDED POP MENU _MSYSMENU ENDIF ENDIF THIS.lRestoredEnvironment = .T. RETURN THIS.IsErrorFree() ENDPROC PROTECTED PROCEDURE saveenvironment && Saves environment settings. IF THIS.lReadEvents THIS.cLastOnShutDown = ON("SHUTDOWN") THIS.cLastPath = SET("PATH") THIS.cLastOnError = ON("ERROR") THIS.cLastDirectory = SET("DIRECTORY") THIS.cLastMacKey = SET("MACKEY") THIS.cMacroSaveFile = THIS.cAppFolder+"M"+SYS(2015)+".FKY" THIS.lSkipErrorHandling = .T. SAVE MACROS TO (THIS.cMacroSaveFile) THIS.lSkipErrorHandling = .F. IF EMPTY(THIS.cFrameClass) AND ; (NOT EMPTY(THIS.cStartupMenu)) PUSH MENU _MSYSMENU ENDIF ENDIF THIS.lSavedEnvironment = .T. ENDPROC PROCEDURE seekcurrentuser && This method finds the current user using an exact match (case sensitivity depends on THIS.lUserNameIsCaseSensitive). LPARAMETERS tcName * This method is separated out so you can use different * user-location strategies (move the record pointer * differently) if you like. You will want to * change CreateUserTable() to match any changes you make here. * The application object expects that whatever table * you use, you will have created one c-type field and placed * its name in THIS.cUserTableIDField, and one i-type field and * placed its name in THIS.iUserTableLevelField. LOCAL llOpenedTable, llSuccess, lcName, llDeletedOff IF VARTYPE(tcName) = "C" lcName = tcName ELSE lcName = THIS.cCurrentUser ENDIF IF NOT USED(THIS.cUserTableAlias) * Note that ordinarily this method will be called with the * user table already opened but it might some time * be useful just to validate the current user USE (THIS.cUserTableName) IN 0 AGAIN SHARED ALIAS (THIS.cUserTableAlias) IF NOT (THIS.IsErrorFree()) RETURN .F. ENDIF llOpenedTable = .T. ENDIF * this is an exact but case-insensitive match IF SET("DELETED") = "OFF" llDeletedOff = .F. SET DELETED ON ENDIF IF THIS.lUserNameIsCaseSensitive llSuccess = SEEK(PADR(ALLTR((lcName)), ; LEN(EVAL(THIS.cUserTableAlias+"."+THIS.cUserTableIDField))), ; THIS.cUserTableAlias,"ID") ELSE llSuccess = SEEK(PADR(UPPER(ALLTR((lcName))), ; LEN(EVAL(THIS.cUserTableAlias+"."+THIS.cUserTableIDField))), ; THIS.cUserTableAlias,"ID_Upper") ENDIF IF llDeletedOff SET DELETED OFF ENDIF IF llOpenedTable USE IN (THIS.cUserTableAlias) ENDIF RETURN llSuccess ENDPROC PROCEDURE seekdefaultuser && This method finds a record with a blank user name where default options and favorites are stores, for use when defining a new user or when user logins and separate user profiles are not required. * this is broken out in case * you want a different way of * assigning a "default user record" * than this one (blank user id field) LOCAL llOpenedTable IF NOT USED(THIS.cUserTableAlias) * see notes in SeekCurrentUser() USE (THIS.cUserTableName) IN 0 AGAIN SHARED ALIAS (THIS.cUserTableAlias) IF NOT (THIS.IsErrorFree()) RETURN .F. ENDIF llOpenedTable = .T. ENDIF IF RECCOUNT(THIS.cUserTableAlias) > 0 IF NOT THIS.SeekCurrentUser("") GO TOP IN (THIS.cUserTableAlias) ENDIF ELSE APPEND BLANK IN (THIS.cUserTableAlias) ENDIF IF llOpenedTable USE IN (THIS.cUserTableAlias) ENDIF ENDPROC PROCEDURE seekmetatablefavoriteid && Finds a record in the meta table using an identification specified in #DEFINE APP_META_FAVE_ID in _FRAMEWK.H. Override this method if you decide to use a more sophisticated method of identifying records in the metatable! LPARAMETERS tcFavoriteID,tcAlias ASSERT USED(tcAlias) ASSERT TYPE("VAL(tcFavoriteID)") = "N" LOCAL liRecID * this is meant to be overridden if you have a better idea! * see the #DEFINE APP_META_FAVE_ID for what I'm using * here... liRecID = VAL(tcFavoriteID) IF liRecID > 0 AND liRecID <= RECCOUNT(tcAlias) GO liRecID IN (tcAlias) RETURN (NOT DELETED(tcAlias)) ELSE RETURN .F. ENDIF ENDPROC PROCEDURE setappfilenames && Get top-level filename, and also get the name of the module (app or exe) that owns this particular object, for SET CLASSLIB ... IN... default usage, which may be different, especially in modular and non-ReadEvents apps. LOCAL lcSys16, liLevel lcSys16 = UPPER(SYS(16,0)) * get top-level filename, and also * get the name of the module (app or exe) that * owns this particular object, for SET CLASSLIB ... IN... * default usage, which may be different. * The latter is important to non-READ EVENTS apps. IF EMPTY(lcSys16) THIS.cAppFileName = "" ELSE THIS.cAppFileName = lcSys16 IF "PROCEDURE" $ THIS.cAppFileName THIS.cAppFileName = SUBSTR(THIS.cAppFileName,11) THIS.cAppFileName = SUBSTR(THIS.cAppFileName,1,AT(" ",THIS.cAppFileName)-1) ENDIF IF NOT FILE(THIS.cAppFileName) * this can happen if an "ON..." was involved... THIS.cAppFileName = "" ENDIF IF INLIST(RIGHT(THIS.cAppFileName,3),"VCT","DCT") * createobject from the command window, * or a stored procedure -- * a top-level SCX/FRX/LBX/MPR/QPR/SPR actually has a * chance at being used properly later, * but I don't think these two do! THIS.cAppFileName = "" ENDIF ENDIF * FOR liLevel = 256 TO 1 STEP -1 && 256 = twice the nested programs currently allowed! FOR liLevel = PROGRAM(-1) TO 1 STEP -1 lcSys16 = UPPER(SYS(16,liLevel)) IF INLIST(RIGHT(lcSys16,3),"APP","EXE","DLL") THIS.cClassContainerFileName = lcSys16 EXIT ENDIF ENDFOR RETURN (THIS.IsErrorFree()) ENDPROC PROCEDURE setcurrentuser && Finds the current user and sets up the app to deal with the current user (permissions, options, favorites, and macros may all change per user). LPARAMETERS tlChangeUser ASSERT VARTYPE(tlChangeUser) = "L" LOCAL llOpenedTable, llSuccess THIS.ClearLastError() IF NOT USED(THIS.cUserTableAlias) USE (THIS.cUserTableName) IN 0 AGAIN SHARED ALIAS (THIS.cUserTableAlias) IF NOT (THIS.IsErrorFree()) RETURN .F. ENDIF llOpenedTable = .T. ENDIF IF THIS.lUserPreferences IF EMPTY(THIS.cCurrentUser) OR tlChangeUser llSuccess = THIS.DoUserLogIn() ELSE llSuccess = THIS.SeekCurrentUser() ENDIF ELSE * we are using a global set of preferences * to cover all users THIS.SeekDefaultUser() llSuccess = .T. ENDIF IF llSuccess THIS.cCurrentUser = ; EVAL(THIS.cUserTableAlias+"."+THIS.cUserTableIDField) THIS.iCurrentUserLevel = ; EVAL(THIS.cUserTableAlias+"."+THIS.cUserTableLevelField) THIS.SetUserPermissions() && abstract in the base THIS.FillUserOptionsArray() THIS.ApplyGlobalUserOptions() THIS.SetCurrentUserFavoriteIDs(.NULL.) IF THIS.lReadEvents THIS.SetMacros() ENDIF ENDIF IF llOpenedTable USE IN (THIS.cUserTableAlias) ENDIF RETURN llSuccess ENDPROC PROCEDURE setcurrentuserfavoriteids && Saves and restores THIS.cCurrentUserFavoriteIDs information to UserFave memo field in user table. This memo field also contains date information, so user can opt to clear favorites list if metatable has changed since user has identified favorites. LPARAMETERS tcNewVal LOCAL llOpenedTable, lcMetaTableLastUpdated, lcNewVal, ; laFavorites[1], liVal lcNewVal = "" THIS.ClearLastError() IF NOT USED(THIS.cUserTableAlias) USE (THIS.cUserTableName) ALIAS (THIS.cUserTableAlias) SHARED AGAIN IN 0 llOpenedTable = .T. ENDIF IF THIS.IsErrorFree() IF THIS.lUserPreferences THIS.SeekCurrentUser() ELSE THIS.SeekDefaultUser() ENDIF ENDIF IF THIS.IsErrorFree() IF VARTYPE(tcNewVal) # "C" * assignment to NULL while setting up a new user, * or for some other reason improperly initialized, so * refresh from the current or default record, * checking lupdate and lastrefresh first * set to "" if no good, with message IF TYPE(THIS.cUserTableAlias+".UserFave") = "M" AND ; NOT EMPTY(EVAL(THIS.cUserTableAlias+".UserFave")) IF (ALINES(laFavorites,EVAL(THIS.cUserTableAlias+".UserFave"),.T.) > 1) AND ; (TYPE(laFavorites[1])= "N") IF DTOS(LUPDATE(THIS.cUserTableAlias)) # laFavorites[1] * the meta table has been edited IF (MESSAGEBOX(APP_META_TABLE_CHANGED_LOC, ; MB_YESNO+MB_ICONEXCLAMATION, ; THIS.cCaption) = IDYES) REPLACE (THIS.cUserTableAlias+".UserFave") WITH "" ; IN (THIS.cUserTableAlias) ELSE * change the datestamp so they don't get asked again lcNewVal = EVAL(THIS.cUserTableAlias+".UserFave") lcNewVal = DTOS(LUPDATE(THIS.cUserTableAlias))+ ; SUBSTR(lcNewVal,AT(CHR(13),lcNewVal)) REPLACE (THIS.cUserTableAlias+".UserFave") WITH lcNewVal ; IN (THIS.cUserTableAlias) lcNewVal = "" ENDIF ENDIF IF NOT EMPTY(EVAL(THIS.cUserTableAlias+".UserFave")) FOR liVal = 2 TO ALEN(laFavorites) IF NOT EMPTY(laFavorites[liVal]) lcNewVal = lcNewVal + CHR(13)+laFavorites[liVal] ENDIF ENDFOR ENDIF ELSE MESSAGEBOX(APP_USER_FAVES_CORRUPT_LOC, ; MB_ICONSTOP, ; THIS.cCaption) REPLACE (THIS.cUserTableAlias+".UserFave") ; WITH "" IN (THIS.cUserTableAlias) ENDIF ENDIF ELSE * store the new string and the meta table lupdate, * back to the current user in the table, or clear the entry IF THIS.IsErrorFree() IF NOT EMPTY(tcNewVal) REPLACE (THIS.cUserTableAlias+".UserFave") ; WITH DTOS(LUPDATE(THIS.cUserTableAlias))+ ; tcNewVal ; IN (THIS.cUserTableAlias) lcNewVal = tcNewVal ELSE REPLACE (THIS.cUserTableAlias+".UserFave") ; WITH "" IN (THIS.cUserTableAlias) ENDIF ENDIF ENDIF ENDIF THIS.cCurrentUserFavoriteIDs = lcNewVal IF llOpenedTable USE IN (THIS.cUserTableAlias) ENDIF THIS.RefreshFavoritePopup() ENDPROC PROCEDURE setdatasessionenvironment && Sets a specified data session to a default set of SETs, which you place in the SetDataSessionSets for use by any form or session you want. LPARAMETERS tiSessionID LOCAL liSessionID liThisSessionID = SET("DATASESSION") IF VARTYPE(tiSessionID) = "N" SET DATASESSION TO (tiSessionID) ENDIF THIS.SetDataSessionSets() SET DATASESSION TO (liThisSessionID) ENDPROC PROCEDURE setdatasessionsets && Contains a default list of data-session-related SETs so you can easily invoke this list within any form or datasesion. SET MULTILOCKS ON SET TALK OFF * .... ENDPROC PROCEDURE setenvironment && Sets up certain global attributes, such as screen or frame characteristics, ON SHUTDOWN, ON ERROR, and macros for use during the life of the app. Does *nothing* if not a ReadEvents app. THIS.ClearLastError() IF THIS.lReadEvents lcTemp = THIS.cReference+".OnShutdown()" ON SHUTDOWN &lcTemp lcTemp = THIS.cReference+".Error(ERROR(),PROGRAM(),LINENO())" ON ERROR &lcTemp IF VARTYPE(THIS.cMacKey) = "C" lcTemp = THIS.cMacKey SET MACKEY TO &lcTemp ELSE SET MACKEY TO ENDIF CLEAR MACROS ENDIF IF THIS.lNoScreenDuringApp THIS.SetScreenAttributes(.F.) * you always have the option to turn off _SCREEN, * in any type of app, although you should use * this ability sparingly if you are non-ReadEvents! * This ability is placed outside the CASE statement * below because the various permutations -- * readevents top form in a development environment, * ActiveDoc from which environment, even a special * type of server that you instantiate and "takes over" * temporary -- can't really be predicted. * Since original state will be restored at cleanup, * this isn't a risk, but the option is still .F. by * default because you should think before implementing * it . ENDIF DO CASE CASE VARTYPE(THIS.oFrame) = "O" THIS.SetFrameAttributes() CASE THIS.lReadEvents AND (NOT THIS.lNoScreenDuringApp) THIS.SetScreenAttributes(.T.) OTHERWISE * hands off! ENDCASE RETURN THIS.IsErrorFree() ENDPROC PROCEDURE setframeattributes && Applies application cCaption and cIcon to the MDI frame, as well as the appropriate backcolor for an MDI frame window. IF VARTYPE(THIS.oFrame) # "O" ** shouldn't happen RETURN ENDIF THIS.oFrame.BackColor = THIS.cusWindowHandler.iMDIWorkSpaceColor THIS.oFrame.Icon = THIS.cIcon THIS.oFrame.Caption = THIS.cCaption ENDPROC PROCEDURE sethtmlclass && Abstract. Takes parameters tcSource (report form or alias/table), tlTable, so you can decide what HTMLClass is appropriate. Passed to GENHTML via _outputdialog attributes. LPARAMETERS tcSource, tlTable ENDPROC PROCEDURE sethtmlstyleid && Abstract. Takes parameters tcSource (report form or alias/table), tlTable, so you can decide what HTMLClass is appropriate. Passed to GENHTML via _outputdialog attributes. LPARAMETERS tcSource, tlTable ENDPROC PROCEDURE setmacros && Saves and restores a set of macros using the user table. Synchronizes enabling of bars on the macro-handling popup, using THIS.cMacroPopupName, depending on current set of user macros. LPARAMETERS tlSave IF VARTYPE(tlSave) # "L" OR (NOT THIS.lReadEvents) RETURN ENDIF LOCAL llOpenedTable, liBar, llSuccess THIS.ClearLastError() IF NOT USED(THIS.cUserTableAlias) USE (THIS.cUserTableName) ALIAS (THIS.cUserTableAlias) SHARED AGAIN IN 0 llOpenedTable = .T. ENDIF IF THIS.lUserPreferences THIS.SeekCurrentUser() ELSE THIS.SeekDefaultUser() ENDIF IF THIS.IsErrorFree() IF TYPE(THIS.cUserTableAlias+".UserMacro") = "M" DO CASE CASE tlSave SAVE MACROS TO MEMO (THIS.cUserTableAlias+".UserMacro") llSuccess = .T. CASE NOT EMPTY(EVAL(THIS.cUserTableAlias+".UserMacro")) llSuccess = .T. CLEAR MACROS RESTORE MACROS FROM MEMO (THIS.cUserTableAlias+".UserMacro") OTHERWISE CLEAR MACROS * can't restore from empty field ENDCASE ENDIF ENDIF IF llOpenedTable USE IN (THIS.cUserTableAlias) ENDIF IF TYPE("CNTBAR(THIS.cMacroPopupName)") = "N" FOR liBar = 1 TO CNTBAR(THIS.cMacroPopupName) IF UPPER(APP_MACRO_RESTORE_LOC) $ UPPER(BARPROMPT(liBar,THIS.cMacroPopupName)) SET SKIP OF BAR liBar OF (THIS.cMacroPopupName) (NOT llSuccess) EXIT ENDIF ENDFOR ENDIF ENDPROC PROCEDURE setscreenattributes && Sets up screen attributes, including visibility, caption and icon, and system toolbars, for a read events app that does not take place in its own topform MDI frame. LPARAMETERS tlOn LOCAL loTemp loTemp = THIS.AddCollaborator("_SysToolbars","_app",,".T.") loTemp = THIS.AddCollaborator("_ObjectState","_app",,"_SCREEN") IF VARTYPE(loTemp) = "O" IF tlOn IF NOT EMPTY(THIS.cCaption) loTemp.Set("Caption", THIS.cCaption, .T.) ENDIF loTemp.Set("Icon",THIS.cIcon, .T.) ENDIF loTemp.Set("Visible",tlOn,.T.) ELSE * this should never happen, but JIC, we'd * have a hard time debugging if we didn't do this! IF tlOn AND NOT _SCREEN.Visible _SCREEN.Visible = .T. ENDIF * notice I don't bother turning it off in the ! tlOn case. ENDIF ENDPROC PROCEDURE setuserpermissions && Abstract in the base. Called when a new user logs on. Designed to use iCurrentUserLevel property, derived from user table, to maintain groups. Menu items would be added/substracted/enabled/disabled based on group level at this time. * This method is abstract in the base, * meant to utilize iCurrentUserLevel property to maintain groups ENDPROC PROCEDURE show && Sets up visible aspects of the application and, if successful, Activate()s the application, at startup. LOCAL llSuccess llSuccess = THIS.SaveEnvironment() IF llSuccess llSuccess = THIS.ValidateMetaTable() ENDIF IF llSuccess llSuccess = THIS.CreateFrame() ENDIF IF llSuccess AND NOT EMPTY(APP_LOADING_LOC) IF VARTYPE(THIS.oFrame) = "O" THIS.oFrame.Show() ENDIF WAIT WINDOW NOWAIT ; LEFT(APP_LOADING_LOC,254) ENDIF IF llSuccess llSuccess = THIS.ResetFormsCollection() ENDIF IF llSuccess llSuccess = THIS.CreateCollaborators() ENDIF IF llSuccess llSuccess = THIS.HandleProjectWindow() ENDIF IF llSuccess llSuccess = THIS.SetEnvironment() ENDIF IF llSuccess THIS.cUserTableAlias = JUSTSTEM(THIS.cUserTableName) llSuccess = NOT EMPTY(THIS.cUserTableAlias) ENDIF IF llSuccess llSuccess = THIS.SetCurrentUser() ENDIF IF llSuccess llSuccess = THIS.ShowStartupElements() ENDIF WAIT CLEAR IF llSuccess llSuccess = THIS.Activate() ENDIF THIS.RestoreEnvironment() RETURN llSuccess ENDPROC PROCEDURE showstartupelements && Sets up top form MDI frame, startup menu, startup toolbar, screen attributes, and startup form. LOCAL llSuccess THIS.lNoInterrupt = .T. IF VARTYPE(THIS.oFrame) = "O" THIS.oFrame.Show() ENDIF llSuccess = ; (EMPTY(THIS.cStartupToolbarClass) OR ; (NOT EMPTY(THIS.DoToolbar( THIS.cStartupToolbarClassLib,THIS.cStartupToolbarClass))) ) IF llSuccess AND (NOT EMPTY(THIS.cStartupMenu)) DO CASE CASE VARTYPE(THIS.oFrame) = "O" llSuccess = THIS.DoMenu(THIS.cStartupMenu, .T.) CASE THIS.lReadEvents llSuccess = THIS.DoMenu(THIS.cStartupMenu) OTHERWISE * append type IF EMPTY(THIS.cStartupMenuPad) llSuccess = THIS.DoMenu(THIS.cStartupMenu) * it's hard to believe that anybody is going to take over the * menu for a non-read-events app, but it could happen ELSE llSuccess = (NOT EMPTY(THIS.DoContextMenu(THIS.cStartupMenu, ; THIS.cStartupMenuPad, ; THIS.cStartupMenuPopup))) * this one returns a # so we can't do the exact same llSuccess check ENDIF ENDCASE ENDIF IF llSuccess IF (VARTYPE(THIS.oFrame) = "O") * if we closed screen during a topform-in-development-version * app, the frame is likely behind another Windows app at this point... THIS.oFrame.Show() ELSE SET MESSAGE TO && for neatness' sake ENDIF THIS.lNoInterrupt = .F. IF THIS.lStartupForm THIS.DoStartupForm() ENDIF ENDIF RETURN llSuccess ENDPROC PROCEDURE showtablefinddialog && Instantiates _FindDialog class, in advanced or standard mode, depending on THIS.lFindOnMultipleTables value. (Advanced mode allows the user to choose between all open aliases in a data session.) LOCAL loForm, llInterrupted loForm = THIS.DoModalDialogClass("_FindDialog", "_table.vcx", .T.) IF VARTYPE(loForm) = "O" loForm.lAdvanced = THIS.lFindOnMultipleTables llInterrupted = (NOT THIS.lNoInterrupt) IF llInterrupted THIS.lNoInterrupt = .T. ENDIF loForm.Show(1) IF llInterrupted THIS.lNoInterrupt = .F. ENDIF ELSE RETURN .F. ENDIF ENDPROC PROCEDURE showtablegotodialog && Instantiates _GoToDialog class. LOCAL llReturn llReturn = THIS.DoModalDialogClass("_GoTodialog", "_table.vcx") RETURN llReturn ENDPROC PROCEDURE showtablesetfilterdialog && Instantiates _FilterExpr class, in advanced or standard depending on THIS.lUseGetExpr value. (Standard mode uses _FilterDialog as a subsidiary dialog, Advanced uses _GETEXPR.) LOCAL loForm THIS.cusTableNav.SetToActiveSession() loForm = THIS.DoModalDialogClass("_FilterExpr", "_table.vcx", .T.) IF VARTYPE(loForm) = "O" loForm.lAdvanced = THIS.lUse_GETEXPR loForm.Show(1) ELSE RETURN .F. ENDIF ENDPROC PROCEDURE storepassword && Stores the encrypted value of a new password to the current record in the user table. LPARAMETERS tcValueToStore IF (NOT THIS.lUserPreferences) OR ; NOT USED(THIS.cUserTableAlias) OR ; VARTYPE(tcValueToStore) # "C" RETURN .F. ENDIF REPLACE UserPass WITH ; (THIS.CreateStoredPassword(tcValueToStore)) IN ; (THIS.cUserTableAlias) ENDPROC PROCEDURE validatemetatable && Ensures that a table contains a valid and available table for documents registry. Validates THIS.cMetatable, if used, on startup. LPARAMETERS tcTable, tlOmitFeedback IF EMPTY(tcTable) AND EMPTY(THIS.cMetaTable) RETURN .T. ENDIF LOCAL lcTable, lcMessage, lcAlias, liSelect, ; llReturn, liTagCount ,laRequired[1], laKeys[1], ; liFound, llExactOff lcAlias = "M"+SYS(2015) THIS.ClearLastError() IF EMPTY(tcTable) USE (THIS.cMetaTable) ALIAS (lcAlias) EXCLU IN 0 lcTable = THIS.cMetaTable ELSE USE (tcTable) ALIAS (lcAlias) EXCLU IN 0 lcTable = tcTable ENDIF llReturn = THIS.IsErrorFree() AND USED(lcAlias) IF NOT llReturn lcMessage = APP_META_UNAVAILABLE_LOC+; CHR(13) + CHR(13)+ ; lcTable ENDIF IF llReturn llReturn = ; TYPE(lcAlias+".DOC_TYPE") = "C" AND ; TYPE(lcAlias+".DOC_DESCR") = "C" AND ; TYPE(lcAlias+".DOC_EXEC") = "M" AND ; TYPE(lcAlias+".DOC_CLASS") = "M" AND ; TYPE(lcAlias+".DOC_NEW") = "L" AND ; TYPE(lcAlias+".DOC_OPEN") = "L" AND ; TYPE(lcAlias+".DOC_SINGLE") = "L" AND ; TYPE(lcAlias+".DOC_NOSHOW") = "L" AND ; TYPE(lcAlias+".DOC_WRAP") = "L" AND ; TYPE(lcAlias+".DOC_GO") = "L" AND ; TYPE(lcAlias+".DOC_NAV") = "L" AND ; TYPE(lcAlias+".ALT_EXEC") = "M" * the last two fields in the delivered metatable * are non-required fields IF NOT llReturn lcMessage = APP_META_WRONGFORMAT_LOC + ; CHR(13)+CHR(13)+ ; lcTable ENDIF ENDIF IF llReturn IF (SET("EXACT") = "OFF") SET EXACT ON llExactOff = .T. ENDIF liSelect = SELECT() SELECT (lcAlias) * check for required tags... DIME laRequired[5] laRequired[1] = "DOC_OPEN" laRequired[2] = "DOC_NEW" laRequired[3] = "DOC_DESCR" laRequired[4] = "DOC_TYPE" laRequired[5] = "DELETED()" DIME laKeys[TAGCOUNT()] FOR liTagCount = 1 TO TAGCOUNT() laKeys[liTagCount] = UPPER(KEY(liTagCount)) ENDFOR FOR liTagCount = 1 TO ALEN(laRequired) liFound = ASCAN(laKeys,UPPER(laRequired[liTagCount])) IF liFound = 0 llReturn = .F. EXIT ENDIF ENDFOR IF NOT llReturn lcMessage = APP_META_MISSINGINDEX_LOC + CHR(13) + ; laRequired[1]+ CHR(13)+ ; laRequired[2]+ CHR(13)+ ; laRequired[3]+ CHR(13) + ; laRequired[4]+ CHR(13) + ; laRequired[5] ENDIF IF llExactOff SET EXACT OFF ENDIF SELECT (liSelect) ENDIF IF NOT (llReturn OR tlOmitFeedback) IF INLIST(_VFP.Startmode, 0, 4) MESSAGEBOX(lcMessage,MB_ICONSTOP,THIS.cCaption) ELSE THIS.cusError.RecordServerError(; THIS.cCaption+": "+lcMessage) ENDIF ENDIF IF USED(lcAlias) USE IN (lcAlias) ENDIF RETURN llReturn ENDPROC PROCEDURE cusError.Error LPARAMETERS nError, cMethod, nLine THIS.Parent.iLastError = nError DODEFAULT(nError, cMethod, nLine) ENDPROC PROCEDURE cusError.getmessageboxtitle LOCAL lcTitle, lcCaption lcCaption = THIS.Parent.cCaption lcTitle = DODEFAULT() IF NOT EMPTY(lcCaption) lcTitle = ALLTR(lcCaption+" "+lcTitle) ENDIF RETURN lcTitle ENDPROC PROCEDURE cusError.setlog LPARAMETERS tcTableName, tcAlias DODEFAULT(THIS.Parent.cErrorLogTableName,tcAlias) ENDPROC PROCEDURE tmrRefresh.Timer IF THIS.Parent.lNoInterrupt * shouldn't happen RETURN ENDIF DODEFAULT() THIS.Parent.RefreshToolbars() LOCAL loMediator, loForm, llBusy IF TYPE("_SCREEN.ActiveForm") = "O" loForm = _SCREEN.ActiveForm ELSE STORE .F. TO THIS.Parent.lGoMenu, THIS.Parent.lNavToolbar RETURN ENDIF IF TYPE("loForm.Parent") = "O" AND ; INLIST(loForm.Parent.WindowType,WINDOWTYPE_MODAL, WINDOWTYPE_READMODAL) RETURN ENDIF IF loForm.WindowType = WINDOWTYPE_MODAL RETURN ENDIF loMediator = THIS.Parent.GetFormMediatorRef(_SCREEN.ActiveForm) IF VARTYPE(loMediator) = "O" THIS.Parent.lGoMenu = loMediator.lGoMenu THIS.Parent.lNavToolbar = loMediator.lNavToolbar ELSE STORE .F. TO THIS.Parent.lGoMenu, THIS.Parent.lNavToolbar ENDIF ENDPROC ENDDEFINE DEFINE CLASS _changepassword AS _dialog OF "_framewk.vcx" && superclass for framework-supplied default password-changing dialog *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="txtPassword" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblPassword" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="txtConfirmPassword" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblConfirmPassword" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdOK" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdCancel" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: savepassword && Confirms and stores new password for the user. *p: oapp * * DoCreate = .T. Height = 80 Name = "_changepassword" oapp = .NULL. Width = 390 * ADD OBJECT 'cmdCancel' AS _commandbutton WITH ; Cancel = .T., ; Caption = "\ ADD OBJECT 'cmdOK' AS _commandbutton WITH ; Caption = "\ ADD OBJECT 'lblConfirmPassword' AS _label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Confirm Password:", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 15, ; Left = 12, ; Name = "lblConfirmPassword", ; TabIndex = 16, ; Top = 47, ; Width = 89 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'lblPassword' AS _label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "New Password:", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 15, ; Left = 12, ; Name = "lblPassword", ; TabIndex = 15, ; Top = 15, ; Width = 76 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'txtConfirmPassword' AS _textbox WITH ; FontBold = .T., ; FontName = "Courier New", ; FontSize = 9, ; Height = 24, ; Left = 118, ; Name = "txtConfirmPassword", ; PasswordChar = "*", ; SelectOnEntry = .T., ; TabIndex = 6, ; Top = 43, ; Value = (""), ; Width = 174 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="textbox" /> ADD OBJECT 'txtPassword' AS _textbox WITH ; FontBold = .T., ; FontName = "Courier New", ; FontSize = 9, ; Height = 24, ; Left = 118, ; Name = "txtPassword", ; PasswordChar = "*", ; SelectOnEntry = .T., ; TabIndex = 5, ; Top = 11, ; Value = (""), ; Width = 174 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="textbox" /> PROCEDURE applyappattributes LPARAMETERS toApp LOCAL llSuccess llSuccess = DODEFAULT(toApp) IF llSuccess IF USED(toApp.cUserTableAlias) THIS.Caption = toApp.cCaption + " " + CHANGEPASSWORD_LOC THIS.oApp = toApp ELSE llSuccess = .F. ENDIF ENDIF IF NOT (llSuccess AND THIS.oApp.IsErrorFree()) THIS.Release() ENDIF ENDPROC PROCEDURE Destroy DODEFAULT() THIS.oApp = .NULL. ENDPROC PROCEDURE KeyPress LPARAMETERS nKeyCode, nShiftAltCtrl IF nKeyCode = 27 THIS.Release() ENDIF ENDPROC PROCEDURE savepassword && Confirms and stores new password for the user. IF ALLTRIM(THIS.txtConfirmPassword.Value) == ALLTRIM(THIS.txtPassword.Value) THIS.oApp.StorePassword(ALLTRIM(THIS.txtPassword.Value)) MESSAGEBOX(OPTIONS_PASSWORD_CONFIRMED_LOC,0,THIS.Caption) STORE SPACE(30) TO THIS.txtConfirmPassword.Value, THIS.txtPassword.Value ENDIF ENDPROC PROCEDURE cmdCancel.Click THISFORM.Release() ENDPROC PROCEDURE cmdOK.Click THISFORM.SavePassword() THISFORM.Release() ENDPROC PROCEDURE txtConfirmPassword.InteractiveChange THISFORM.cmdOK.Enabled = (ALLTRIM(THISFORM.txtPassword.Value) == ALLTRIM(THIS.Value)) ENDPROC PROCEDURE txtPassword.InteractiveChange THISFORM.cmdOK.Enabled = (ALLTRIM(THISFORM.txtConfirmPassword.Value) == ALLTRIM(THIS.Value)) ENDPROC ENDDEFINE DEFINE CLASS _dialog AS _form OF "..\ffc\_base.vcx" && superclass for framework-supplied default dialogs *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> #INCLUDE "_framewk.h" * *m: adjustforsystemfontsize && Handles large font use for any dialogs that are supplied with the framework. Since the framework visual elements default to MS San Serif, these dialogs switch to Arial if the user is in large font mode. *m: applyappattributes && Takes a reference to the application object and applies app session-specific attributes, caption, and icon to this dialog. *p: lsingleton && Indicates that this dialog should re-show rather re-instantiate, if invoked when it already exists. * * AutoCenter = .T. BorderStyle = 0 Caption = ("") DoCreate = .T. Height = 250 Icon = ..\model\ MaxButton = .F. MinButton = .F. Name = "_dialog" Width = 375 * PROCEDURE adjustforsystemfontsize && Handles large font use for any dialogs that are supplied with the framework. Since the framework visual elements default to MS San Serif, these dialogs switch to Arial if the user is in large font mode. LOCAL lcStandardFont, loControl IF FONTMETRIC(1, 'MS Sans Serif', 8, '') # 13 OR ; FONTMETRIC(4, 'MS Sans Serif', 8, '') # 2 OR ; FONTMETRIC(6, 'MS Sans Serif', 8, '') # 5 OR ; FONTMETRIC(7, 'MS Sans Serif', 8, '') # 11 lcStandardFont = UPPER(DIALOG_SMALLFONT_NAME) FOR EACH loControl IN THIS.Controls DO CASE CASE PEMSTATUS(loControl,"FontName",5) AND ; UPPER(loControl.FontName) == lcStandardFont loControl.FontName = DIALOG_LARGEFONT_NAME CASE TYPE("loControl.Buttons(1)") = "O" loControl.SetAll("FontName",DIALOG_LARGEFONT_NAME) OTHERWISE * note: I am *not* going to do this recursively, * although I would in other instances. * none of the _framewk dialogs based on * _dialog class use containers extensively, * and if some were added it would be unwise * for me to assume that these containers should * be unilaterally altered by this code. * The best thing to do would be to add a * FontName property to such containers, with * an assign method so that the change could * be applied appropriately to the members of * said container. ENDCASE ENDFOR ENDIF ENDPROC PROCEDURE applyappattributes && Takes a reference to the application object and applies app session-specific attributes, caption, and icon to this dialog. LPARAMETERS toApp IF VARTYPE(toApp) = "O" IF EMPTY(THIS.Caption) THIS.Caption = toApp.cCaption + " " + THIS.Caption ENDIF IF EMPTY(THIS.Icon) THIS.Icon = toApp.cIcon ENDIF THIS.AdjustForSystemFontSize() toApp.ApplyUserOptsForSession(THIS.DataSessionID) ELSE RETURN .F. ENDIF ENDPROC PROCEDURE Load DODEFAULT() SET TALK OFF IF THIS.lSingleton LOCAL loForm, llFound FOR EACH loForm IN _SCREEN.Forms IF (loForm.ClassLibrary == THIS.ClassLibrary AND ; loForm.Class == THIS.Class ) AND ; loForm.Visible llFound = .T. loForm.Show() loForm.Autocenter = loForm.AutoCenter EXIT ENDIF ENDFOR IF llFound RETURN .F. ENDIF ENDIF ENDPROC ENDDEFINE DEFINE CLASS _documentpicker AS _dialog OF "_framewk.vcx" && superclass for framework-supplied dialogs manipulating the metatable of documents *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="lstDocuments" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdOK" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdCancel" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: execdocument && Abstract, called when the user presses OK or makes a selection from the document list. *m: filldocumentsarray && Abstract, called on startup to dimension and fill the array that supplies the listbox with values and provides potential action parameters when the user chooses from the listbox. *m: setdialogsizeparameters && Sets initial, minimum, and maximum dialog size based on number of items in the listbox. *p: lnew && Toggles the dialog between two states. *p: lsorted && Determines whether items in list will be sorted by visible field when descendent classes' FillDocumentsArray method prepares contents *p: oapp *a: adocuments[1,7] * * BorderStyle = 3 Caption = "Choose a document" DataSession = 2 DoCreate = .T. Height = 229 KeyPreview = .T. lsorted = .T. Name = "_documentpicker" oapp = .NULL. Width = 328 * ADD OBJECT 'cmdCancel' AS _commandbutton WITH ; Cancel = .T., ; Caption = "\ ADD OBJECT 'cmdOK' AS _commandbutton WITH ; Caption = "\ ADD OBJECT 'lstDocuments' AS _listbox WITH ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 204, ; IntegralHeight = .T., ; ItemTips = .T., ; Left = 12, ; Name = "lstDocuments", ; RowSourceType = 5, ; Top = 12, ; Value = 1, ; Width = 230 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="listbox" /> PROCEDURE applyappattributes LPARAMETERS toapp IF DODEFAULT(toApp) THIS.SetDialogSizeParameters() THIS.Resize() ENDIF ENDPROC PROCEDURE Destroy DODEFAULT() THIS.oApp = .NULL. ENDPROC PROCEDURE execdocument && Abstract, called when the user presses OK or makes a selection from the document list. ENDPROC PROCEDURE filldocumentsarray && Abstract, called on startup to dimension and fill the array that supplies the listbox with values and provides potential action parameters when the user chooses from the listbox. ENDPROC PROCEDURE Init LPARAMETERS toApp, tlNew IF NOT DODEFAULT() RETURN .F. ENDIF LOCAL laTemp[1], llReturn ASSERT VARTYPE(tlNew) = "L" ASSERT TYPE("toApp.cMetaTable") = "C" AND ; ACLASS(laTemp,toApp) > 0 AND ; ASCAN(laTemp,"_APPLICATION") > 0 ; MESSAGE DOCUMENTPICKER_NO_APP_LOC THIS.lNew = tlNew THIS.oApp = toApp DO CASE CASE EMPTY(toApp.cMetaTable) OR ; (NOT THIS.FillDocumentsArray(toApp.GetResourceFileName(toApp.cMetaTable,".dbf"))) OR ; VARTYPE(THIS.aDocuments[1,1]) # "C" MESSAGEBOX(DOCUMENTPICKER_NO_DOCUMENTS_LOC, ; MB_ICONEXCLAMATION, ; toApp.cCaption) CASE ALEN(THIS.aDocuments,1) = 1 THIS.lstDocuments.RowSource = "THISFORM.aDocuments" THIS.lstDocuments.Value = 1 THIS.ExecDocument() OTHERWISE llReturn = .T. THIS.lstDocuments.RowSource = "THISFORM.aDocuments" ENDCASE IF NOT llReturn THIS.oApp = .NULL. ENDIF RETURN llReturn ENDPROC PROCEDURE KeyPress LPARAMETERS nKeyCode, nShiftAltCtrl DO CASE CASE nKeyCode = 27 THIS.cmdCancel.Click() NODEFAULT CASE nKeyCode = 23 THIS.cmdOK.Click() NODEFAULT OTHERWISE ENDCASE ENDPROC PROCEDURE Load DODEFAULT() SET DELETED ON ENDPROC PROCEDURE Resize LOCAL lnMargin lnMargin = THIS.lstDocuments.Left STORE THIS.Width - (THIS.cmdCancel.Width + lnMargin ) TO ; THIS.cmdCancel.Left, ; THIS.cmdOK.Left STORE THIS.cmdCancel.Left - (lnMargin * 2) TO THIS.lstDocuments.Width lnMargin = THIS.lstDocuments.Top STORE THIS.Height - (lnMargin * 2) TO THIS.lstDocuments.Height ENDPROC PROCEDURE setdialogsizeparameters && Sets initial, minimum, and maximum dialog size based on number of items in the listbox. LOCAL liMaxRows, lnListRowHeight, lnListMaxHeight, lnListMinHeight, lnMargin liMaxRows = ALEN(THIS.aDocuments,1) lnMargin = THIS.lstDocuments.Top WITH THIS.lstDocuments lnListRowHeight = FONTM(1,.FontName,.FontSize) + ; FONTM(5,.FontName,.FontSize) + ; FONTM(4,.FontName,.FontSize) lnListMaxHeight = MIN(lnListRowHeight * liMaxRows, ; (SYSMETRIC(2) - lnMargin * 2)) lnListMinHeight = lnListRowHeight * 2 IF NOT BETWEEN(.Height, lnListMinHeight, lnListMaxHeight) .Height = MIN(lnListMaxHeight, .Height) ENDIF ENDWITH THIS.MinWidth = THIS.Width THIS.MinHeight = MAX(lnListMinHeight + (lnMargin * 2), ; (THIS.cmdCancel.Top + THIS.cmdCancel.Height + lnMargin)) THIS.MaxHeight = MAX(THIS.MinHeight, lnListMaxHeight + (lnMargin * 2)) THIS.Height = MAX(THIS.MinHeight,THIS.lstDocuments.Height + (lnMargin * 2)) lnMargin = THIS.lstDocuments.Left THIS.Width = THIS.lstDocuments.Width+THIS.cmdCancel.Width+ lnMargin * 3 ENDPROC PROCEDURE cmdCancel.Click THISFORM.Release() ENDPROC PROCEDURE cmdOK.Click IF NOT EMPTY(THISFORM.lstDocuments.Value) THISFORM.ExecDocument() ENDIF THISFORM.Release() ENDPROC PROCEDURE lstDocuments.DblClick THISFORM.cmdOK.Click() ENDPROC PROCEDURE lstDocuments.KeyPress LPARAMETERS nKeyCode, nShiftAltCtrl IF INLIST(nKeyCode,13,32) THIS.DblClick() NODEFAULT ENDIF ENDPROC ENDDEFINE DEFINE CLASS _errorlogviewer AS _dialog OF "_framewk.vcx" && superclass for framework-supplied default dialog to browse error log and add user notes to the log *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="pgfErrorLog" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfErrorLog.Page1.edtListing" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfErrorLog.Page2.edtUserNotes" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="txtErrStamp" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="spnNav" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdBrowseErrorLog" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="app_mediator" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: ctextdisplayfont_assign *m: donologmessage *p: calias *p: ctextdisplayfont *p: imargin * * BorderStyle = 3 calias = ("ErrorLog") DataSession = 2 DoCreate = .T. Height = 250 imargin = 0 lsingleton = .T. Name = "_errorlogviewer" ShowTips = .T. TabIndex = 1 Width = 375 WindowState = 0 * ADD OBJECT 'app_mediator' AS _formmediator WITH ; Left = 48, ; Name = "app_mediator", ; Top = 36 *< END OBJECT: ClassLib="_framewk.vcx" BaseClass="custom" /> ADD OBJECT 'cmdBrowseErrorLog' AS _commandbutton WITH ; Caption = (""), ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 24, ; Left = 10, ; Name = "cmdBrowseErrorLog", ; Picture = graphics\browse.bmp, ; TabIndex = 4, ; ToolTipText = ("Browse the Error Log records"), ; Top = 35, ; Width = 24 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'pgfErrorLog' AS _pageframe WITH ; ActivePage = 1, ; ErasePage = .T., ; Height = 252, ; Left = 0, ; Name = "pgfErrorLog", ; PageCount = 2, ; TabIndex = 1, ; Top = 0, ; Width = 377, ; Page1.Caption = "\ ADD OBJECT 'pgfErrorLog.Page1.edtListing' AS _editbox WITH ; DefLeft = , ; FontCondense = .T., ; FontName = "Courier New", ; FontSize = 9, ; Height = 180, ; Left = (THISFORM.iMargin), ; Name = "edtListing", ; ToolTipText = ("Technical details of the error for you to tell the programmer"), ; Top = 39, ; Width = 367 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="editbox" /> ADD OBJECT 'pgfErrorLog.Page2.edtUserNotes' AS _editbox WITH ; DefLeft = , ; FontName = "Courier New", ; Height = 180, ; Left = (THISFORM.iMargin), ; Name = "edtUserNotes", ; ToolTipText = ("A place for you to write whatever might help the programmer fix the error"), ; Top = 39, ; Width = 367 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="editbox" /> ADD OBJECT 'spnNav' AS _spinner WITH ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 24, ; Left = 352, ; Name = "spnNav", ; TabIndex = 3, ; TabStop = .F., ; ToolTipText = ("Move to a different Error Log record"), ; Top = 36, ; Width = 16 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="spinner" /> ADD OBJECT 'txtErrStamp' AS _textbox WITH ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 24, ; Left = 120, ; Name = "txtErrStamp", ; ReadOnly = .T., ; TabIndex = 2, ; TabStop = .F., ; ToolTipText = ("Date and Time of this error"), ; Top = 36, ; Width = 228 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="textbox" /> PROCEDURE Activate IF RECCOUNT(THIS.cAlias) < 2 THIS.spnNav.Enabled = .F. ELSE STORE RECCOUNT(THIS.cAlias) TO ; THIS.spnNav.SpinnerHighValue, THIS.spnNav.KeyboardHighValue STORE 1 TO THIS.spnNav.SpinnerLowValue, THIS.spnNav.KeyboardLowValue STORE RECNO(THIS.cAlias) TO THIS.spnNav.Value ENDIF THIS.Refresh() ENDPROC PROCEDURE applyappattributes LPARAMETERS toApp LOCAL lcTable IF DODEFAULT(toApp) lcTable = toApp.cErrorLogTableName IF EMPTY(lcTable) OR NOT FILE(lcTable) THIS.DoNoLogMessage(ERRORVIEWER_UNAVAILABLE_LOC ) RETURN .F. ENDIF USE (lcTable) SHARED ALIAS (THIS.cAlias) IN 0 IF NOT USED(THIS.cAlias) THIS.DoNoLogMessage(ERRORVIEWER_UNAVAILABLE_LOC ) RETURN .F. ENDIF IF EMPTY(RECCOUNT(THIS.cAlias)) THIS.DoNoLogMessage(ERRORVIEWER_EMPTY_LOC ) RETURN .F. ENDIF GO BOTTOM THIS.txtErrStamp.ControlSource=THIS.cAlias+".ErrStamp" THIS.pgfErrorLog.Page1.edtListing.ControlSource = THIS.cAlias+".Listing" THIS.pgfErrorLog.Page2.edtUserNotes.ControlSource = THIS.cAlias+".UserNotes" THIS.app_mediator.LoadApp(toApp.cReference) * the error log viewer is different from other * _dialog descendents in that it's not modal, * so it deserves a mediator for later use. ELSE RETURN .F. ENDIF ENDPROC PROCEDURE ctextdisplayfont_assign LPARAMETERS tvNewVal IF VARTYPE(tvNewVal) = "C" THIS.cTextDisplayFont = tvNewVal STORE tvNewVal TO THIS.pgfErrorLog.Page1.edtListing.FontName, ; THIS.pgfErrorLog.Page2.edtUserNotes.FontName ENDIF ENDPROC PROCEDURE Destroy IF (NOT EMPTY(THIS.cAlias)) AND USED(THIS.cAlias) USE IN (THIS.cAlias) ENDIF ENDPROC PROCEDURE donologmessage LPARAMETERS tcMessage ?? CHR(7) MESSAGEBOX(tcMessage,MB_ICONINFORMATION,THIS.Caption) RETURN ENDPROC PROCEDURE Init IF DODEFAULT() THIS.MinHeight = THIS.Height THIS.MinWidth = THIS.Width THIS.iMargin = SYSMETRIC(12) STORE THIS.iMargin TO ; THIS.pgfErrorLog.Page1.edtListing.Left, ; THIS.pgfErrorLog.Page2.edtUserNotes.Left THIS.Resize() ELSE RETURN .F. ENDIF ENDPROC PROCEDURE Resize WITH THIS.pgfErrorLog .Height = THIS.Height .Width = THIS.Width THIS.txtErrStamp.Left = (THIS.Width - THIS.txtErrStamp.Width)/2 THIS.spnNav.Left = THIS.txtErrStamp.Left+THIS.txtErrStamp.Width STORE .PageHeight - ; (THIS.pgfErrorLog.Page1.edtListing.Top+ ; THIS.iMargin) TO ; THIS.pgfErrorLog.Page1.edtListing.Height, ; THIS.pgfErrorLog.Page2.edtUserNotes.Height STORE THIS.Width - (THIS.iMargin*2) TO ; .Page1.edtListing.Width, ; .Page2.edtUserNotes.Width ENDWITH ENDPROC PROCEDURE app_mediator.dosessionsets LPARAMETERS toApp LOCAL loApp IF VARTYPE(toApp) = "O" loApp = toApp ELSE loApp = THIS.GetAppRef() ENDIF IF VARTYPE(loApp) = "O" DODEFAULT(loApp) THISFORM.cTextDisplayFont = loApp.cTextDisplayFont ENDIF loApp = NULL ENDPROC PROCEDURE cmdBrowseErrorLog.Click LOCAL lcFrame, loApp, iSelect && jic iSelect = SELECT() SELECT (THISFORM.cAlias) loApp = THISFORM.app_mediator.GetAppRef() IF TYPE("loApp.oFrame.Name") = "C" lcFrame = " IN WINDOW (loApp.oFrame.Name) " ELSE lcFrame = " IN SCREEN " ENDIF BROWSE FIELDS ; errstamp :H= "Error Date and Time", ; field2 = LEFT(Listing, 20) :H="Tech Listing", ; field3 = LEFT(UserNotes,10) :H= "Your Notes Go Here" ; WINDOW (THISFORM.Name) ; FONT (THISFORM.cTextDisplayFont) ; &lcFrame THISFORM.Refresh() THISFORM.spnNav.Value = RECNO() SELECT (iSelect) loApp = NULL ENDPROC PROCEDURE spnNav.DownClick IF THIS.Value = THIS.SpinnerLowValue ?? CHR(7) ENDIF THISFORM.cmdBrowseErrorLog.SetFocus() ENDPROC PROCEDURE spnNav.InteractiveChange GO THIS.Value IN (THISFORM.cAlias) THISFORM.Refresh() ENDPROC PROCEDURE spnNav.UpClick IF THIS.Value = THIS.SpinnerHighValue ?? CHR(7) ENDIF THISFORM.cmdBrowseErrorLog.SetFocus() ENDPROC ENDDEFINE DEFINE CLASS _favoritepicker AS _documentpicker OF "_framewk.vcx" && superclass for framework-supplied default dialog to add items to the Favorites menu (in New mode) or execute a document at startup ("quick start") *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="cmdBrowse" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdRemove" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: refreshbuttons *m: refreshfavoriteids && Adds to the app cCurrentUserFavoriteIDs list when the user makes a new choice. *m: removedocument *p: lallowfilebrowsing && Determines whether the user is allowed to pick files from disk for QuickStart or Favorites use. * * DoCreate = .T. lallowfilebrowsing = .T. Name = "_favoritepicker" lstDocuments.Name = "lstDocuments" lstDocuments.TabIndex = 1 lstDocuments.Top = 12 cmdOK.Left = 254 cmdOK.Name = "cmdOK" cmdOK.TabIndex = 2 cmdOK.Top = 14 cmdOK.Width = 63 cmdCancel.Height = 27 cmdCancel.Left = 254 cmdCancel.Name = "cmdCancel" cmdCancel.TabIndex = 4 cmdCancel.Top = 82 cmdCancel.Width = 63 * ADD OBJECT 'cmdBrowse' AS _commandbutton WITH ; Caption = "\ ADD OBJECT 'cmdRemove' AS _commandbutton WITH ; Caption = "\ PROCEDURE execdocument LPARAMETERS tcFile * if a filename has been sent here, * we're browsing/picking directly * otherwise, we're working off the documents array LOCAL liRow, lcExt, lcFile, lcStatement, ; laFavorites[1], ; llDocumentFromDisk, llExactSet liRow = THIS.lstDocuments.Value IF VARTYPE(tcFile) # "C" AND ; (EMPTY(THIS.aDocuments[liRow,1]) OR ; NOT BETWEEN(liRow,1,ALEN(THIS.aDocuments,1))) RETURN ENDIF IF VARTYPE(tcFile) = "C" lcFile = UPPER(ALLTRIM(tcFile)) lcExt = JUSTEXT(lcFile) IF INLIST(lcExt,"SCT","LBT","FRT") lcFile = LEFT(lcFile,LEN(lcFile)-1)+"X" lcExt = LEFT(lcExt,LEN(lcExt)-1)+"X" ENDIF IF NOT FILE(lcFile) THIS.oApp.FileNotFoundMsgBox(lcFile) RETURN ENDIF llDocumentFromDisk = .T. ELSE IF LEFT(THIS.aDocuments[liRow,1],FAVORITEPICKER_PICKED_LEN ) = ; FAVORITEPICKER_PICKED_LOC * we're removing a document * we've been called from * doubleclick on list or something, * so let's toggle: THIS.RemoveDocument() RETURN ENDIF IF THIS.lNew lcFile = THIS.aDocuments[liRow,11] THIS.aDocuments[liRow,1] = ; FAVORITEPICKER_PICKED_LOC +THIS.aDocuments[liRow,1] ELSE * is this a document from disk instead * of a metatable entry? * documents from disk use only * the first column of the array IF EMPTY(THIS.aDocuments[liRow,11]) lcFile = THIS.aDocuments[liRow,1] llDocumentFromDisk = .T. lcExt = JUSTEXT(lcFile) ENDIF ENDIF ENDIF IF THIS.lNew * we have a document to add to the * list. Is it from the metatable or disk? * and is it already there? IF (NOT EMPTY(lcFile)) ALINES(laFavorites,THIS.oApp.cCurrentUserFavoriteIDs,.T.) llExactSet = (SET("EXACT") = "OFF") IF llExactSet SET EXACT ON ENDIF IF (ASCAN(laFavorites,lcFile) = 0) IF llDocumentFromDisk liRow = ALEN(THIS.aDocuments,1) IF VARTYPE(THIS.aDocuments[liRow,1]) = "C" AND ; (NOT EMPTY(THIS.aDocuments[liRow,1])) liRow = liRow + 1 DIME THIS.aDocuments[liRow,11] ENDIF THIS.aDocuments[liRow,1] = FAVORITEPICKER_PICKED_LOC +lcFile ENDIF THIS.lstDocuments.Requery() THIS.lstDocuments.Value = liRow THIS.RefreshFavoriteIDs(lcFile) ELSE MESSAGEBOX(lcFile+; CHR(13)+CHR(13)+ ; FAVORITEPICKER_DOC_ALREADY_LOC, ; 48,THISFORM.oApp.cCaption) ENDIF IF llExactSet SET EXACT OFF ENDIF ENDIF ELSE IF llDocumentFromDisk THIS.oApp.DoFile(lcFile) ELSE DO CASE CASE NOT EMPTY(THIS.aDocuments[liRow,9]) && alt-exec lcStatement = ALLTR(THIS.aDocuments[liRow,9]) &lcStatement CASE THIS.aDocuments[liRow,8] && wrapped DO (ALLTRIM(THIS.aDocuments[liRow,2])) OTHERWISE && report or form?? IF ALLTR(THIS.aDocuments[liRow,10]) = PJX_META_DOC_REPORT_TYPE THIS.oApp.DoReport(ALLTRIM(THIS.aDocuments[liRow,2]), ; ALLTRIM(THIS.aDocuments[liRow,1])) ELSE THIS.oApp.DoForm(ALLTRIM(THIS.aDocuments[liRow,2]), ; ALLTRIM(THIS.aDocuments[liRow,3]), ; THIS.aDocuments[liRow,4], ; THIS.aDocuments[liRow,5], ; THIS.aDocuments[liRow,6], ; THIS.aDocuments[liRow,7]) ENDIF ENDCASE ENDIF ENDIF ENDPROC PROCEDURE filldocumentsarray LPARAMETERS tcMetaTableName DIME THIS.aDocuments[1,11] LOCAL liTally, liDocument, lcConditions, laFavorites[1], ; liFaves, lcDocument, llExactSet, lcTable, liDocs llExactSet = (SET("EXACT") = "OFF") IF llExactSet SET EXACT ON ENDIF liTally = 0 liDocs = 0 IF NOT EMPTY(tcMetaTableName) lcTable = THIS.oApp.GetResourceFileName(tcMetaTableName,".dbf") IF NOT EMPTY(lcTable) lcConditions = " DOC_OPEN AND NOT DELETED() " SELECT DOC_DESCR, DOC_EXEC, DOC_CLASS, ; DOC_SINGLE, DOC_NOSHOW, ; DOC_GO, DOC_NAV, ; DOC_WRAP, ALT_EXEC, DOC_TYPE, APP_META_FAVE_ID AS DOC_ID ; FROM (lcTable) ; WHERE &lcConditions ; INTO ARRAY THIS.aDocuments * this is for a startup form, and picking favorites, using * all metatable's document items, both reports and forms, * so array fits both types of documents' usage * above is form's use of metatable fields + one (doc_type) + ID field or expression * below is report's use of fields (favorites/startup has to use both) * report's use of fields: * SELECT DOC_DESCR, DOC_EXEC, ; * DOC_WRAP, ALT_EXEC ; * FROM (tcMetaTableName) ; * WHERE DOC_TYPE = PJX_META_DOC_REPORT_TYPE ; * &lcConditions ; * AND NOT DELETED() ; * INTO ARRAY THIS.aDocuments STORE _TALLY TO liTally, liDocs ENDIF ENDIF liFaves = ALINES(laFavorites,THIS.oApp.cCurrentUserFavoriteIDs,.T.) IF (liTally # 0) FOR liDocument = 1 TO liTally THIS.aDocuments[liDocument,11] = ALLTR(THIS.aDocuments[liDocument,11]) IF ASCAN(laFavorites,; THIS.aDocuments[liDocument,11]) > 0 IF THIS.lNew THIS.aDocuments[liDocument,1] = ; FAVORITEPICKER_PICKED_LOC + ; THIS.aDocuments[liDocument,1] liTally = liTally - 1 * show as disabled items already * in the user table as favorites ENDIF ENDIF ENDFOR ENDIF IF (liFaves # 0) * if a favorite is a document on disk, * rather than something from the metatable, * add it to the list, * disabled if we are in New, * enabled otherwise FOR EACH lcDocument IN laFavorites IF NOT EMPTY(lcDocument) AND ; ASCAN(THIS.aDocuments,lcDocument) = 0 AND ; FILE(lcDocument) liTally = liTally + 1 liDocs = liDocs + 1 DIME THIS.aDocuments[liDocs,11] THIS.aDocuments[liDocs,1] = ALLTR(UPPER(lcDocument)) IF THIS.lNew THIS.aDocuments[liDocs,1] = FAVORITEPICKER_PICKED_LOC + THIS.aDocuments[liDocs,1] ENDIF ENDIF ENDFOR ENDIF If llExactSet SET EXACT OFF ENDIF IF THIS.lSorted ASORT(THIS.aDocuments) ENDIF IF liDocs = 0 AND (THIS.lNew AND THIS.lAllowFileBrowsing) * make sure list doesn't look stupid THIS.aDocuments[1,1]="" ENDIF RETURN (liTally # 0) OR ; (THIS.lNew AND (THIS.lAllowFileBrowsing OR liDocs # 0)) ENDPROC PROCEDURE Init LPARAMETERS toApp, tlAdd LOCAL laTemp[1], llReturn THIS.lNew = tlAdd THIS.oApp = toApp ASSERT TYPE("toApp.cMetaTable") = "C" AND ; ACLASS(laTemp,toApp) > 0 AND ; ASCAN(laTemp,"_APPLICATION") > 0 ; MESSAGE DOCUMENTPICKER_NO_APP_LOC * override of some document picker stuff... * favorites can work without a * registered document table or a list at all... DO CASE CASE NOT THIS.FillDocumentsArray(toApp.cMetaTable) IF THIS.lAllowFileBrowsing LOCAL lcFile, lcWaitMessage THIS.lNew = tlAdd IF tlAdd lcWaitMessage = FAVORITEPICKER_CAPTION_ADD_LOC ELSE lcWaitMessage = FAVORITEPICKER_CAPTION_START_LOC ENDIF WAIT WINDOW NOWAIT ; LEFT(lcWaitMessage, 250)+"..." lcFile = GETFILE() WAIT CLEAR IF (NOT EMPTY(lcFile)) AND FILE(lcFile) THIS.ExecDocument(lcFile) ENDIF ELSE MESSAGEBOX(DOCUMENTPICKER_NO_DOCUMENTS_LOC, ; MB_ICONEXCLAMATION, ; toApp.cCaption) ENDIF THIS.oApp = .NULL. RETURN .F. CASE ALEN(THIS.aDocuments,1) = 1 AND ; NOT (tlAdd OR THIS.lAllowFileBrowsing) THIS.lstDocuments.RowSource = "THISFORM.aDocuments" THIS.lstDocuments.Value = 1 THIS.ExecDocument() THIS.oApp = .NULL. RETURN .F. OTHERWISE THIS.lstDocuments.RowSource = "THISFORM.aDocuments" THIS.lstDocuments.Value = 1 IF tlAdd THIS.Caption = FAVORITEPICKER_CAPTION_ADD_LOC THIS.cmdOK.Caption = FAVORITEPICKER_ADDBUTTON_LOC THIS.cmdCancel.Caption = FAVORITEPICKER_CLOSEBUTTON_LOC THIS.cmdOK.Default = .F. ELSE THIS.Caption = FAVORITEPICKER_CAPTION_START_LOC THIS.cmdCancel.Top = THIS.cmdRemove.Top STORE .F. TO THIS.cmdRemove.Visible, ; THIS.cmdRemove.Enabled ENDIF IF NOT THIS.lAllowFileBrowsing STORE .F. TO THIS.cmdBrowse.Visible, ; THIS.cmdBrowse.Enabled ENDIF ENDCASE ENDPROC PROCEDURE refreshbuttons IF THIS.lNew IF THIS.lstDocuments.Value = 0 OR ; EMPTY(THIS.aDocuments[THIS.lstDocuments.Value,1]) STORE .F. TO THIS.cmdOK.Enabled, THIS.cmdRemove.Enabled ELSE STORE (LEFT(THIS.aDocuments[THIS.lstDocuments.Value,1], ; FAVORITEPICKER_PICKED_LEN ) # ; FAVORITEPICKER_PICKED_LOC ) TO ; THIS.cmdOK.Enabled STORE ! THIS.cmdOK.Enabled TO ; THIS.cmdRemove.Enabled ENDIF ENDIF ENDPROC PROCEDURE refreshfavoriteids && Adds to the app cCurrentUserFavoriteIDs list when the user makes a new choice. LPARAMETERS tcFavoriteIDToAdd ASSERT THIS.lNew LOCAL lcCurrentIDs, lcID, liID IF VARTYPE(tcFavoriteIDToAdd) = "C" AND ; NOT EMPTY(tcFavoriteIDToAdd) lcID = ALLTRIM(tcFavoriteIDToAdd) lcCurrentIDs = ALLTRIM(THIS.oApp.cCurrentUserFavoriteIDs) IF INLIST(RIGHT(lcCurrentIDs,1), ; CHR(13), CHR(10)) THIS.oApp.cCurrentUserFavoriteIDs = ; lcCurrentIDs + lcID ELSE THIS.oApp.cCurrentUserFavoriteIDs = ; lcCurrentIDs +CHR(13)+lcID ENDIF ELSE * removing or otherwise doing a general refresh lcCurrentIDs = "" FOR liID = 1 TO ALEN(THIS.aDocuments,1) IF LEFT(THIS.aDocuments[liID,1],FAVORITEPICKER_PICKED_LEN) = FAVORITEPICKER_PICKED_LOC lcCurrentIDs = lcCurrentIDs + CHR(13) IF EMPTY(THIS.aDocuments[liID,11]) lcCurrentIDs = lcCurrentIDs + SUBSTR(THIS.aDocuments[liID,1],FAVORITEPICKER_PICKED_LEN+1) ELSE lcCurrentIDs = lcCurrentIDs + THIS.aDocuments[liID,11] ENDIF ENDIF ENDFOR THIS.oApp.cCurrentUserFavoriteIDs = lcCurrentIDs ENDIF ENDPROC PROCEDURE removedocument ASSERT THIS.lNew LOCAL liRow, liCount liRow = THIS.lstDocuments.Value liCount = ALEN(THIS.aDocuments,1) IF (NOT BETWEEN(liRow,1,liCount)) OR ; (LEFT(THIS.aDocuments[liRow,1], ; FAVORITEPICKER_PICKED_LEN) # ; FAVORITEPICKER_PICKED_LOC ) * shouldn't happen RETURN ENDIF DO CASE CASE EMPTY(THIS.aDocuments[liRow,1]) * empty first row, nothing to do RETURN CASE EMPTY(THIS.aDocuments[liRow,11]) * document on disk, remove from listbox ADEL(THIS.aDocuments,liRow) IF liCount > 1 liCount = liCount - 1 DIME THIS.aDocuments[liCount,11] ELSE THIS.aDocuments[1,1] = "" ENDIF OTHERWISE * metatable entry, un-mark in listbox THIS.aDocuments[liRow,1] = SUBSTR(THIS.aDocuments[liRow,1],; FAVORITEPICKER_PICKED_LEN+1) ENDCASE THIS.lstDocuments.Requery() IF liRow > liCount THIS.lstDocuments.Value = liCount ELSE THIS.lstDocuments.Value = liRow ENDIF THIS.RefreshFavoriteIDs() ENDPROC PROCEDURE Resize DODEFAULT() LOCAL lnMargin lnMargin = THIS.Height - (THIS.lstDocuments.Top+THIS.lstDocuments.Height) THIS.cmdBrowse.Top = THIS.Height - (THIS.cmdBrowse.Height + lnMargin) STORE THIS.cmdCancel.Left TO THIS.cmdBrowse.Left, THIS.cmdRemove.Left ENDPROC PROCEDURE setdialogsizeparameters DODEFAULT() THIS.MinHeight = MAX(THIS.MinHeight, ; THIS.cmdCancel.Top + THIS.cmdCancel.Height + ; THIS.cmdBrowse.Height + ; THIS.lstDocuments.Top * 2) THIS.Height = MAX(THIS.Height, THIS.MinHeight) THIS.MaxHeight = MAX(THIS.Height, THIS.MaxHeight) ENDPROC PROCEDURE cmdBrowse.Click LOCAL lcFile lcFile = GETFILE() IF EMPTY(lcFile) RETURN ENDIF IF FILE(lcFile) THISFORM.ExecDocument(lcFile) ENDIF IF NOT THISFORM.lNew THISFORM.Release() ENDIF ENDPROC PROCEDURE cmdOK.Click IF THISFORM.lNew THISFORM.ExecDocument() ELSE DODEFAULT() ENDIF ENDPROC PROCEDURE cmdRemove.Click THISFORM.RemoveDocument() ENDPROC PROCEDURE lstDocuments.DblClick THISFORM.ExecDocument() IF NOT THISFORM.lNew THISFORM.Release() ENDIF ENDPROC PROCEDURE lstDocuments.InteractiveChange THISFORM.RefreshButtons() ENDPROC PROCEDURE lstDocuments.ProgrammaticChange THIS.InteractiveChange() ENDPROC PROCEDURE lstDocuments.When THIS.InteractiveChange() ENDPROC ENDDEFINE DEFINE CLASS _formmediator AS _mediatedsession OF "_framewk.vcx" && member object to framework-enable any form *< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" /> #INCLUDE "_framewk.h" * *p: ccontextmenufile && Holds the name of a context menu you wish to attach to this mediator's host document. *p: ccontextmenupad && Holds the pad name of the context menu so it can be removed when the host document destroys. *p: ccontextmenupopup && Holds the pad name of the context menu popup so it can be released when the host document destroys. *p: ctoolbarclass && Holds the name of a context toolbar class you wish to attach to this mediator's host document. *p: ctoolbarclasslib && Holds the name of a class library containing the context toolbar class you wish to attach to this mediator's host document. *p: icontextmenuindex && Provided to the mediator by the app when it invokes a context menu for the mediator's host document, passed back to the app by the mediator so the app can refresh its context menu collection when this host document destroys. *p: itoolbarindex && Provided to the mediator by the app when it invokes a context toolbar for the mediator's host document, passed back to the app by the mediator so the app can refresh its context toolbar collection when this host document destroys. *p: laddappicon && Specifies that the mediator should apply the application's standard Icon to the form's Icon property, if this property has been left empty. Defaults to .T.; turn it off if you want a borderless form! *p: lgomenu && Specifies whether or not the host document has been assigned a navigation menu by the application and its metatable entry. *p: lnavtoolbar && Specifies whether or not the host document has been assigned a navigation toolbar by the application and its metatable entry. * * ccontextmenufile = ("") ccontextmenupad = ("") ccontextmenupopup = ("") ctoolbarclass = ("") ctoolbarclasslib = ("") icontextmenuindex = 0 itoolbarindex = 0 laddappicon = .T. lsetdocumenttonewonappload = .T. Name = "_formmediator" * PROCEDURE Destroy DODEFAULT() LOCAL loApp loApp = THIS.GetAppRef() IF ISNULL(loApp) RETURN ENDIF IF NOT EMPTY(THIS.iContextMenuIndex) loApp.ReleaseContextMenu(THIS.iContextMenuIndex) ENDIF IF NOT EMPTY(THIS.iToolbarIndex) loApp.ReleaseToolbar(THIS.iToolbarIndex) ENDIF loApp = .NULL. ENDPROC PROCEDURE loadapp LPARAMETERS tcAppRef IF DODEFAULT(tcAppRef) LOCAL loApp loApp = THIS.GetAppRef() IF NOT (EMPTY(THIS.cContextMenuFile) OR ; EMPTY(THIS.cContextMenuPad) OR ; EMPTY(THIS.cContextMenuPopup)) THIS.iContextMenuIndex = ; loApp.DoContextMenu(THIS.cContextMenuFile, THIS.cContextMenuPad, THIS.cContextMenuPopup) ENDIF IF NOT EMPTY(THIS.cToolbarClass) THIS.iToolbarIndex = ; loApp.DoToolbar(THIS.cToolbarClassLib, THIS.cToolbarClass) ENDIF IF THIS.lAddAppIcon AND ; EMPTY(THISFORM.Icon) AND ; NOT THISFORM.TitleBar = 0 THISFORM.Icon = loApp.cIcon ENDIF loApp = NULL ELSE RETURN .F. ENDIF ENDPROC ENDDEFINE DEFINE CLASS _mediatedsession AS _custom OF "..\ffc\_base.vcx" * *Mediator object to framework-enable a datasession. Drop on form to handle the datasession of the form/formset, or pass Init(tlCreateSession,tcSessionClass, tcSessionClassLib) to create and wrap a non-visual session. * *< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" /> * *m: cleanupoutputalias && Abstract, see PrepareOutputAlias(). If you have created a temporary cursor for the purposes of DoTableOutput(), here's your chance to destroy it. *m: coutputalias_assign *m: coutputcaption_access *m: createsession && Creates the session object if .T. passed to the class upon instantiation *m: csessionclasslib_access *m: csessionclass_access *m: datachanged && Wraps application QueryDataChanged method, using iChangeMode specific to this object. *m: datasessionid_access *m: datasessionid_assign *m: datasessionname_access *m: datasessionname_assign *m: datasession_access *m: datasession_assign *m: dosessionsets && If lSessionSettings is .T., invokes app SetDataSessionEnvironment() method for this session If lUserSessionSettings is .T., invokes app ApplyUserOptsForSession() method for this session. *m: getappref && RETURNs an object reference to the app. *m: loadapp && Applies app attributes, including session settings. Sets new or open status if lSetDocumentToNewOnAppLoad is .T.. *m: output && Wraps the app DoTableOutput() method. *m: outputonerecord && Wraps the app DoTableOutput() method with a scope of one record. *m: pickrecordtoworkon && Abstract, available to evaluate whether form has been invoked in "new" or "open" mode, and for you to add record browsing/navigation/APPEND BLANK/whatever based on this information. *m: prepareoutputalias && Abstract, will be invoked by app's DoTableOutput() so you can SELECT a focus table, or put together a cursor, filter data, or otherwise prepare appropriate "focussed" table information when the user chooses to get quick output from any form. *m: queryunload && Invokes the app's QueryDataSessionUnload for this Session. If used with a form, should be called in the form's QueryUnload() to handle any data changes, updates, or reverts before the form is closed. *m: setdocumenttonew && Stores the app's lAddingNewDocument flag at the time the app attributes are loaded, so the form can evaluate what record to work on. *m: writesessionclassdefinition && Not currently used; designed to provide a model for generation of a class definition file if desired. Would be called by the cSessionClassLib access method. *p: cappref && Holds the name of the reference variable for the running app so the mediator can evaluate it to an object reference when necessary. The mediator does not store any object references, for safety. *p: coutputalias && Allows you to indicate the right alias to "focus on" when the app DoTableOutput method runs, without any additional work in PrepareOutputAlias() and CleanupOutputAlias(). *p: coutputcaption && Will be passed by the app's DoTableOutput() to the _outputdialog, if used. *p: csessionclass && The programmatic class definition to instance if .T. is passed to the class. By default, an instance of the session baseclass is created. *p: csessionclasslib && The programmatic classlibrary holding the cSessionClass class definition you wish to instantiate. By default, an instance of the session baseclass is created. *p: datasession && Wraps the Datasession property of the session object, if this mediator created one *p: datasessionid && Wraps the DatasessionID property of the session object, if this mediator created one *p: datasessionname && Wraps the Name property of the session object, if this mediator created one *p: ichangemode && Sent on to the app's cusDataSession object to detemine what constitutes data change. 0 - anything changed. 1 - ignore view fields not in Updatefields list. 2- ignore views not set to send updates. *p: ladding && Stores information about whether the framework invoked a session for "new" or "open" editing. *p: lsessionsettings && Specifies whether the mediator should load session settings using the application's defaults. *p: lsetdocumenttonewonappload && If .T., specifies that mediator should invoke SetDocumentToNew() in LoadApp. *p: lusersessionsettings && Specifies whether the mediator should load data-session-specific user settings using the application's defaults. *p: osession && If .T. is passed to the _mediator class when it's instanced, holds the session object for this mediator. Otherwise the mediator looks for its parent form's session. * * cappref = ("") coutputalias = coutputcaption = csessionclass = csessionclasslib = datasession = 1 datasessionname = ichangemode = 0 lusersessionsettings = .T. Name = "_mediatedsession" osession = .NULL. * PROCEDURE cleanupoutputalias && Abstract, see PrepareOutputAlias(). If you have created a temporary cursor for the purposes of DoTableOutput(), here's your chance to destroy it. ENDPROC PROCEDURE coutputalias_assign LPARAMETERS tvNewVal IF VARTYPE(tvNewVal) = "C" AND USED(tvNewVal) THIS.cOutputAlias = tvNewVal ENDIF ENDPROC PROCEDURE coutputcaption_access IF EMPTY(THIS.cOutputCaption) AND (NOT EMPTY(THIS.cOutputAlias)) RETURN PROPER(THIS.cOutputAlias) ELSE RETURN THIS.cOutputCaption ENDIF ENDPROC PROCEDURE createsession && Creates the session object if .T. passed to the class upon instantiation lcClass = THIS.cSessionClass lcClassLib = THIS.cSessionClassLib IF EMPTY(lcClassLib) RETURN CREATEOBJECT("Session") ELSE RETURN NEWOBJECT(lcClass, lcClassLib) ENDIF ENDPROC PROCEDURE csessionclasslib_access LOCAL lcVal IF VARTYPE(THIS.cSessionClassLib) # "C" OR EMPTY(THIS.cSessionClassLib) *!* * to generate: *!* lcVal = ADDBS(GETENV("TEMP"))+"C"+SYS(2015)+".PRG" lcVal = "" ELSE lcVal = FORCEEXT(THIS.cSessionClassLib,"FXP") IF NOT FILE(lcVal) && either on disk or bound *!* * to generate: *!* IF NOT DIRECTORY(JUSTPATH(lcVal)) *!* lcVal = FORCEPATH(lcVal,ADDBS(GETENV("TEMP"))) *!* ENDIF *!* lcVal = FORCEEXT(lcVal,"PRG") *!* IF EMPTY(SYS(2000,lcVal)) *!* THIS.WriteSessionClassDefinition(lcVal) *!* ENDIF *!* lcVal = FORCEEXT(lcVal,"FXP") lcVal = FORCEEXT(lcVal,"PRG") IF EMPTY(SYS(2000,lcVal)) && on disk lcVal = "" ELSE COMPILE (lcVal) lcVal = FORCEEXT(lcVal,"FXP") ENDIF ENDIF ENDIF THIS.cSessionClassLib = lcVal RETURN THIS.cSessionClassLib ENDPROC PROCEDURE csessionclass_access IF VARTYPE(THIS.cSessionClass) # "C" ; OR EMPTY(THIS.cSessionClass) ; OR VARTYPE(THIS.cSessionClassLib) # "C" ; OR EMPTY(THIS.cSessionClassLib) * THIS.cSessionClass = "Session"+SYS(2015) THIS.cSessionClass = "Session" ENDIF RETURN THIS.cSessionClass ENDPROC PROCEDURE datachanged && Wraps application QueryDataChanged method, using iChangeMode specific to this object. LOCAL loApp, llReturn, loSession loApp = THIS.GetAppRef() IF ISNULL(loApp) RETURN ENDIF IF ISNULL(THIS.oSession) IF TYPE("THISFORM") # "O" RETURN ELSE loSession = THISFORM ENDIF ELSE loSession = THIS.oSession ENDIF llReturn = NOT ISNULL(loSession) IF llReturn llReturn = loApp.QueryDataChanged(loSession,THIS.iChangeMode) ENDIF STORE .NULL. TO loApp, loSession RETURN llReturn ENDPROC PROCEDURE datasessionid_access IF ISNULL(THIS.oSession) RETURN SET("DATASESSION") ELSE RETURN THIS.oSession.DataSessionID ENDIF ENDPROC PROCEDURE datasessionid_assign LPARAMETERS tvNewVal * don't allow assignment ENDPROC PROCEDURE datasessionname_access IF ISNULL(THIS.oSession) RETURN "" ELSE RETURN THIS.oSession.Name ENDIF ENDPROC PROCEDURE datasessionname_assign LPARAMETERS vNewVal * readonly, don't allow assignment ENDPROC PROCEDURE datasession_access IF ISNULL(THIS.oSession) IF TYPE("THISFORMSET.BaseClass") = "C" RETURN THISFORMSET.DataSession ELSE RETURN THISFORM.DataSession ENDIF ELSE RETURN THIS.oSession.DataSession ENDIF ENDPROC PROCEDURE datasession_assign LPARAMETERS vNewVal * don't allow assignment ENDPROC PROCEDURE Destroy DODEFAULT() THIS.oSession = NULL ENDPROC PROCEDURE dosessionsets && If lSessionSettings is .T., invokes app SetDataSessionEnvironment() method for this session If lUserSessionSettings is .T., invokes app ApplyUserOptsForSession() method for this session. LPARAMETERS toApp LOCAL loApp loApp = NULL IF VARTYPE(toApp) = "O" * called from LoadApp * or something else that knows * the app already loApp = toApp ELSE loApp = THIS.GetAppRef() ENDIF IF ISNULL(loApp) RETURN ENDIF IF THIS.lSessionSettings DO CASE CASE NOT ISNULL(THIS.oSession) loApp.SetDataSessionEnvironment(THIS.oSession.DataSessionID) CASE TYPE("THISFORMSET.DataSession") = "N" AND ; THISFORMSET.DataSession # 1 loApp.SetDataSessionEnvironment(THISFORMSET.DataSessionID) CASE THISFORM.DataSession # 1 loApp.SetDataSessionEnvironment(THISFORM.DataSessionID) OTHERWISE * a form or formset in the default session, don't touch ENDCASE ENDIF IF THIS.lUserSessionSettings IF NOT ISNULL(THIS.oSession) loApp.ApplyUserOptsForSession(THIS.oSession) ELSE loApp.ApplyUserOptsForSession(THISFORM) ENDIF ENDIF loApp = NULL ENDPROC PROCEDURE getappref && RETURNs an object reference to the app. IF EMPTY(THIS.cAppRef) RETURN .NULL. ENDIF LOCAL ARRAY laCheck[1] IF TYPE(THIS.cAppRef+".BaseClass") = "C" ; AND ACLASS(laCheck,EVAL(THIS.cAppRef)) > 0 AND ; ASCAN(laCheck,"_APPLICATION") > 0 RETURN EVAL(THIS.cAppRef) ELSE RETURN .NULL. ENDIF ENDPROC PROCEDURE Init LPARAMETERS tlCreateSession, tcSessionClass, tcSessionClassLib IF DODEFAULT() IF tlCreateSession IF NOT (EMPTY(tcSessionClass) OR EMPTY(tcSessionClassLib)) THIS.cSessionClass = tcSessionClass THIS.cSessionClassLib = tcSessionClassLib ENDIF THIS.oSession = THIS.CreateSession() IF VARTYPE(THIS.oSession) # "O" RETURN .F. ENDIF ELSE IF TYPE("THISFORM") # "O" RETURN .F. ENDIF ENDIF ELSE RETURN .F. ENDIF ENDPROC PROCEDURE loadapp && Applies app attributes, including session settings. Sets new or open status if lSetDocumentToNewOnAppLoad is .T.. LPARAMETERS tcAppRef THIS.cAppRef = tcAppRef LOCAL loApp loApp = THIS.GetAppRef() IF ISNULL(loApp) RETURN .F. ENDIF THIS.DoSessionSets(loApp) IF THIS.lSetDocumentToNewOnAppLoad THIS.SetDocumentToNew(loApp) ENDIF loApp = .NULL. ENDPROC PROCEDURE output && Wraps the app DoTableOutput() method. LOCAL loApp, llReturn loApp = THIS.GetAppRef() IF ISNULL(loApp) RETURN ENDIF llReturn = loApp.DoTableOutput() loApp = .NULL. RETURN llReturn ENDPROC PROCEDURE outputonerecord && Wraps the app DoTableOutput() method with a scope of one record. LOCAL loApp, llReturn loApp = THIS.GetAppRef() IF ISNULL(loApp) RETURN ENDIF llReturn = loApp.DoTableOutput(.T.) loApp = .NULL. RETURN llReturn ENDPROC PROCEDURE pickrecordtoworkon && Abstract, available to evaluate whether form has been invoked in "new" or "open" mode, and for you to add record browsing/navigation/APPEND BLANK/whatever based on this information. ENDPROC PROCEDURE prepareoutputalias && Abstract, will be invoked by app's DoTableOutput() so you can SELECT a focus table, or put together a cursor, filter data, or otherwise prepare appropriate "focussed" table information when the user chooses to get quick output from any form. ENDPROC PROCEDURE queryunload && Invokes the app's QueryDataSessionUnload for this Session. If used with a form, should be called in the form's QueryUnload() to handle any data changes, updates, or reverts before the form is closed. LPARAMETERS tlDataChangeAlreadyConfirmed LOCAL loApp, llReturn, loSession loApp = THIS.GetAppRef() IF ISNULL(loApp) RETURN ENDIF IF ISNULL(THIS.oSession) IF TYPE("THISFORM") # "O" RETURN ELSE loSession = THISFORM ENDIF ELSE loSession = THIS.oSession ENDIF llReturn = NOT ISNULL(loSession) IF llReturn llReturn = loApp.QueryDataSessionUnload(tlDataChangeAlreadyConfirmed,loSession) ENDIF STORE .NULL. TO loApp, loSession RETURN llReturn ENDPROC PROCEDURE setdocumenttonew && Stores the app's lAddingNewDocument flag at the time the app attributes are loaded, so the form can evaluate what record to work on. LPARAMETERS toApp LOCAL loApp loApp = NULL IF VARTYPE(toApp) = "O" * called from LoadApp * or something else that knows * the app already loApp = toApp ELSE loApp = THIS.GetAppRef() ENDIF IF ISNULL(loApp) RETURN ENDIF THIS.lAdding = loApp.lAddingNewDocument loApp = .NULL. ENDPROC PROCEDURE writesessionclassdefinition && Not currently used; designed to provide a model for generation of a class definition file if desired. Would be called by the cSessionClassLib access method. LPARAMETERS tcFileName * not currently used, * for generation purposes LOCAL lcFileName, llSafety IF EMPTY(tcFileName) RETURN ELSE lcFileName = tcFileName ENDIF llSafety = (SET("SAFETY") == "ON") IF llSafety SET SAFETY OFF ENDIF lcFileName = FORCEEXT(lcFileName,"PRG") STRTOFILE("DEFINE CLASS "+THIS.cSessionClass+" AS Session"+CHR(13)+CHR(10),lcFileName) STRTOFILE("DataSession = 2"+CHR(13)+CHR(10),lcFileName,.T.) STRTOFILE("ENDDEFINE"+CHR(13)+CHR(10),lcFileName,.T.) COMPILE (lcFileName) ERASE (lcFileName) THIS.cSessionClassLib = FORCEEXT(lcFileName,"FXP") IF llSafety SET SAFETY ON ENDIF ENDPROC ENDDEFINE DEFINE CLASS _navtoolbar AS _modalawaretoolbar OF "..\ffc\_ui.vcx" && superclass for framework-supplied default navigation toolbar (application object makes a nav toolbar class available to any form designated as using a nav toolbar in the metatable) *< CLASSDATA: Baseclass="toolbar" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="_separator1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdTop" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdPrev" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdNext" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdBottom" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="spnGo" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdSortUp" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdSortDown" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="_separator2" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdFilter" UniqueID="" Timestamp="" /> * *p: oapp * * Caption = "Navigate" ControlBox = .F. Height = 30 Left = 0 Name = "_navtoolbar" oapp = .NULL. Top = 0 Width = 234 * ADD OBJECT '_separator1' AS _separator WITH ; Height = 30, ; Left = 5, ; Name = "_separator1", ; Top = 3, ; Width = 103 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="separator" /> ADD OBJECT '_separator2' AS _separator WITH ; Height = 29, ; Left = 205, ; Name = "_separator2", ; Top = 3, ; Width = 58 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="separator" /> ADD OBJECT 'cmdBottom' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 74, ; Name = "cmdBottom", ; Picture = graphics\bottom.bmp, ; SpecialEffect = 2, ; Top = 3, ; Width = 24, ; ZOrderSet = 4 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdFilter' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 205, ; Name = "cmdFilter", ; Picture = graphics\filter.bmp, ; SpecialEffect = 2, ; Top = 3, ; Width = 24, ; ZOrderSet = 8 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdNext' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 51, ; Name = "cmdNext", ; Picture = graphics\next.bmp, ; SpecialEffect = 2, ; Top = 3, ; Width = 24, ; ZOrderSet = 3 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdPrev' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 28, ; Name = "cmdPrev", ; Picture = graphics\previous.bmp, ; SpecialEffect = 2, ; Top = 3, ; Width = 24, ; ZOrderSet = 2 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdSortDown' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 174, ; Name = "cmdSortDown", ; Picture = graphics\sortdes.bmp, ; SpecialEffect = 2, ; Top = 3, ; Width = 24, ; ZOrderSet = 7 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdSortUp' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 151, ; Name = "cmdSortUp", ; Picture = graphics\sortasc.bmp, ; SpecialEffect = 2, ; Top = 3, ; Width = 24, ; ZOrderSet = 6 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdTop' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 5, ; Name = "cmdTop", ; Picture = graphics\top.bmp, ; SpecialEffect = 2, ; Top = 3, ; Width = 24, ; ZOrderSet = 1 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'spnGo' AS _spinner WITH ; Height = 24, ; Left = 97, ; Name = "spnGo", ; SpecialEffect = 2, ; Top = 3, ; Width = 55, ; ZOrderSet = 5 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="spinner" /> PROCEDURE Destroy DODEFAULT() THIS.oApp = .NULL. ENDPROC PROCEDURE Refresh LOCAL llEnable IF NOT THIS.lDisabledForModal NODEFAULT DO CASE CASE TYPE("_SCREEN.ActiveForm.Parent") = "O" SET DATASESSION TO _SCREEN.ActiveForm.Parent.DataSessionID CASE TYPE("_SCREEN.ActiveForm") = "O" SET DATASESSION TO _SCREEN.ActiveForm.DataSessionID OTHERWISE * we're wherever we should be... ENDCASE llEnable = (RECCOUNT() > 1) IF llEnable * everything has been enabled WITH THIS.spnGo STORE 1 TO .SpinnerLowValue, .KeyBoardLowValue STORE RECCOUNT() TO ; .SpinnerHighValue, .KeyBoardHighValue .Value = RECNO() .Value = MIN(.Value,.SpinnerHighValue) && EOF() ENDWITH ELSE THIS.SetAll("Enabled", .F.) ENDIF ENDIF RETURN llEnable ENDPROC PROCEDURE cmdBottom.Click IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.GoBottom() ENDIF ENDPROC PROCEDURE cmdFilter.Click IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.ShowTableSetFilterDialog() ENDIF ENDPROC PROCEDURE cmdNext.Click IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.GoNext() ENDIF ENDPROC PROCEDURE cmdPrev.Click IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.GoPrevious() ENDIF ENDPROC PROCEDURE cmdSortDown.Click IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.DoSort(,,,.T.) ENDIF ENDPROC PROCEDURE cmdSortUp.Click IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.DoSort(,,,.F.) ENDIF ENDPROC PROCEDURE cmdTop.Click IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.GoTop() ENDIF ENDPROC PROCEDURE spnGo.InteractiveChange IF NOT ISNULL(THIS.Parent.oApp) THIS.Parent.oApp.GoToRecord(THIS.Value) ENDIF ENDPROC ENDDEFINE DEFINE CLASS _newopen AS _documentpicker OF "_framewk.vcx" && superclass for framework-supplied default dialog to add or edit a document *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> #INCLUDE "_framewk.h" * DoCreate = .T. Name = "_newopen" lstDocuments.Name = "lstDocuments" cmdOK.Name = "cmdOK" cmdCancel.Name = "cmdCancel" * PROCEDURE execdocument LOCAL liRow liRow = THISFORM.lstDocuments.Value IF EMPTY(liRow) RETURN ENDIF DO CASE CASE NOT EMPTY(THIS.aDocuments[liRow,9]) && alt-exec LOCAL lcStatement lcStatement = ALLTR(THIS.aDocuments[liRow,9]) &lcStatement CASE THIS.aDocuments[liRow,8] && wrapped DO (ALLTRIM(THIS.aDocuments[liRow,2])) OTHERWISE && form or form class THIS.oApp.DoForm(ALLTRIM(THIS.aDocuments[liRow,2]), ; ALLTRIM(THIS.aDocuments[liRow,3]), ; THIS.aDocuments[liRow,4], ; THIS.aDocuments[liRow,5], ; THIS.aDocuments[liRow,6], ; THIS.aDocuments[liRow,7]) ENDCASE ENDPROC PROCEDURE filldocumentsarray LPARAMETERS tcMetaTableName DIME THIS.aDocuments[1,9] * array has 9 columns to match meta data info * First is visible description, plus 6 columns of DoForm params, * and then "wrapped" column meaning "this is a program not a class" * followed by "alt-exec" column, which gets macro-evaluated if used * LPARAMETERS tcFileName,tcClass,tlNoMultipleInstances,tlNoShow, tlGoMenu, tlNavToolbar * are the doform params... IF EMPTY(tcMetaTableName) RETURN .F. ENDIF LOCAL lcConditions IF THIS.lNew lcConditions = " AND DOC_NEW " ELSE lcConditions = " AND DOC_OPEN " ENDIF lcConditions = lcConditions + " AND NOT DELETED() " IF THIS.lSorted lcConditions = lcConditions + " ORDER BY 1 " ENDIF SELECT DOC_DESCR, DOC_EXEC, DOC_CLASS, ; DOC_SINGLE, DOC_NOSHOW, ; DOC_GO, DOC_NAV, ; DOC_WRAP, ALT_EXEC ; FROM (tcMetaTableName) ; WHERE DOC_TYPE = PJX_META_DOC_FORM_TYPE ; &lcConditions ; INTO ARRAY THIS.aDocuments RETURN ( _TALLY # 0) ENDPROC PROCEDURE Init LPARAMETERS toApp, tlNew IF NOT DODEFAULT(toApp,tlNew) RETURN .F. ENDIF IF tlNew THIS.Caption = NEWOPEN_CAPTION_NEW_LOC ELSE THIS.Caption = NEWOPEN_CAPTION_OPEN_LOC ENDIF ENDPROC ENDDEFINE DEFINE CLASS _options AS _dialog OF "_framewk.vcx" && superclass for framework-supplied default dialog to edit, apply, or save user options *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="shpGlobalItems" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="shpDocumentItems" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdApply" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdSetDefault" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdResetToDefault" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="chkConfirm" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="chkShowTips" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblTextDisplay" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cboTextDisplayFont" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblBell" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblDocumentOptions" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblGlobalOptions" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblHours" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="opgBell" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="opgHours" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="txtBell" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdPickWav" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: displaycurrentuseroptions *m: displayoptions *m: displayuserdefaultoptions *m: saveuseroptionsfromdisplay *m: setfromdisplay *m: setuseroptionsfromdisplay *p: oapp * * BufferMode = 2 Caption = "Options" DoCreate = .T. Height = 190 KeyPreview = .T. Name = "_options" oapp = .NULL. Width = 345 * ADD OBJECT 'cboTextDisplayFont' AS _combobox WITH ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 21, ; Left = 101, ; Name = "cboTextDisplayFont", ; Style = 2, ; TabIndex = 8, ; Top = 114, ; Value = (""), ; Width = 229, ; ZOrderSet = 8 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="combobox" /> ADD OBJECT 'chkConfirm' AS _checkbox WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Confirm entry when leaving text fields", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Left = 16, ; Name = "chkConfirm", ; TabIndex = 2, ; Top = 24, ; ZOrderSet = 5 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="checkbox" /> ADD OBJECT 'chkShowTips' AS _checkbox WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Show tool tips in forms", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 15, ; Left = 16, ; Name = "chkShowTips", ; TabIndex = 3, ; Top = 41, ; Width = 123, ; ZOrderSet = 6 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="checkbox" /> ADD OBJECT 'cmdApply' AS _commandbutton WITH ; Caption = "\ ADD OBJECT 'cmdPickWav' AS _commandbutton WITH ; AutoSize = .T., ; Caption = "...", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Left = 303, ; Name = "cmdPickWav", ; TabIndex = 12, ; Top = 147 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdResetToDefault' AS _commandbutton WITH ; AutoSize = .F., ; Caption = "\ ADD OBJECT 'cmdSetDefault' AS _commandbutton WITH ; AutoSize = .F., ; Caption = "\ ADD OBJECT 'lblBell' AS _label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Warning sound:", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Left = 15, ; Name = "lblBell", ; TabIndex = 9, ; Top = 137, ; ZOrderSet = 7 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'lblDocumentOptions' AS _label WITH ; AutoSize = .T., ; Caption = "Document options", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Left = 13, ; Name = "lblDocumentOptions", ; TabIndex = 1, ; Top = 8, ; ZOrderSet = 7 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'lblGlobalOptions' AS _label WITH ; AutoSize = .T., ; Caption = "Global options", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Left = 13, ; Name = "lblGlobalOptions", ; TabIndex = 6, ; Top = 100, ; ZOrderSet = 7 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'lblHours' AS _label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Hours display:", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Left = 15, ; Name = "lblHours", ; TabIndex = 4, ; Top = 62, ; ZOrderSet = 7 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'lblTextDisplay' AS _label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Text display font:", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Left = 15, ; Name = "lblTextDisplay", ; TabIndex = 7, ; Top = 117, ; ZOrderSet = 7 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'opgBell' AS _optiongroup WITH ; BackStyle = 0, ; BorderStyle = 0, ; ButtonCount = 3, ; Height = 21, ; Left = 9, ; Name = "opgBell", ; TabIndex = 10, ; Top = 149, ; Width = 145, ; OPTION1.AutoSize = .T., ; OPTION1.BackStyle = 0, ; OPTION1.Caption = "Off", ; OPTION1.FontName = "MS Sans Serif", ; OPTION1.FontSize = 8, ; OPTION1.Left = 5, ; OPTION1.Name = "OPTION1", ; OPTION1.Top = 3, ; OPTION2.AutoSize = .T., ; OPTION2.BackStyle = 0, ; OPTION2.Caption = "Default", ; OPTION2.FontName = "MS Sans Serif", ; OPTION2.FontSize = 8, ; OPTION2.Left = 42, ; OPTION2.Name = "OPTION2", ; OPTION2.Top = 3, ; Option3.AutoSize = .T., ; Option3.BackStyle = 0, ; Option3.Caption = "Play:", ; Option3.FontName = "MS Sans Serif", ; Option3.FontSize = 8, ; Option3.Height = 15, ; Option3.Left = 99, ; Option3.Name = "Option3", ; Option3.Top = 3, ; Option3.Width = 41 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="optiongroup" /> ADD OBJECT 'opgHours' AS _optiongroup WITH ; AutoSize = .T., ; BackStyle = 0, ; BorderStyle = 0, ; Height = 25, ; Left = 96, ; Name = "opgHours", ; TabIndex = 5, ; Top = 57, ; Width = 74, ; OPTION1.AutoSize = .T., ; OPTION1.BackStyle = 0, ; OPTION1.Caption = "12", ; OPTION1.FontName = "MS Sans Serif", ; OPTION1.FontSize = 8, ; OPTION1.Left = 5, ; OPTION1.Name = "OPTION1", ; OPTION1.Top = 5, ; OPTION2.AutoSize = .T., ; OPTION2.BackStyle = 0, ; OPTION2.Caption = "24", ; OPTION2.FontName = "MS Sans Serif", ; OPTION2.FontSize = 8, ; OPTION2.Height = 15, ; OPTION2.Left = 39, ; OPTION2.Name = "OPTION2", ; OPTION2.Top = 5, ; OPTION2.Width = 30 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="optiongroup" /> ADD OBJECT 'shpDocumentItems' AS _shape WITH ; BackStyle = 0, ; Height = 74, ; Left = 6, ; Name = "shpDocumentItems", ; SpecialEffect = 0, ; Top = 14, ; Width = 220, ; ZOrderSet = 1 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="shape" /> ADD OBJECT 'shpGlobalItems' AS _shape WITH ; BackStyle = 0, ; Height = 74, ; Left = 6, ; Name = "shpGlobalItems", ; SpecialEffect = 0, ; Top = 106, ; Width = 332, ; ZOrderSet = 0 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="shape" /> ADD OBJECT 'txtBell' AS _textbox WITH ; Alignment = 1, ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 22, ; Left = 154, ; Name = "txtBell", ; ReadOnly = .T., ; TabIndex = 11, ; Top = 148, ; Width = 144 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="textbox" /> PROCEDURE applyappattributes LPARAMETERS toApp LOCAL llSuccess llSuccess = DODEFAULT(toApp) IF llSuccess IF USED(toApp.cUserTableAlias) THIS.Caption = toApp.cCaption + " " + OPTIONS_LOC THIS.oApp = toApp THIS.DisplayCurrentUserOptions() IF EMPTY(EVAL(toApp.cUserTableAlias+".UserOpts")) WAIT WINDOW NOWAIT LEFT(OPTIONS_NOT_STORED_LOC,254) THIS.cmdResetToDefault.Enabled = .F. ENDIF ELSE llSuccess = .F. ENDIF ENDIF IF NOT (llSuccess AND THIS.oApp.IsErrorFree()) THIS.Release() ENDIF ENDPROC PROCEDURE Destroy DODEFAULT() THIS.oApp = .NULL. ENDPROC PROCEDURE displaycurrentuseroptions * show values from user options array in the dialog THIS.DisplayOptions("CURRENT") ENDPROC PROCEDURE displayoptions LPARAMETERS tcWhichSet IF VARTYPE(tcWhichSet) # "C" OR ; (NOT INLIST(tcWhichSet,"CURRENT","SAVED")) RETURN .F. ENDIF LOCAL llCurrent, lvValue llCurrent = (tcWhichSet = "CURRENT") IF NOT llCurrent RESTORE FROM MEMO (THIS.oApp.cUserTableAlias+".UserOpts") ADDITIVE * local array laOptions now exists ENDIF IF llCurrent lvValue = THIS.oApp.GetUserOptionSetting("BELL") ELSE lvValue = THIS.oApp.GetUserOptionSetting("BELL", @laOptions) ENDIF IF VARTYPE(lvValue) # "C" lvValue = SET("BELL") ENDIF IF lvValue = "OFF" THIS.opgBell.Value = 1 ELSE THIS.opgBell.Value = 2 ENDIF IF llCurrent lvValue = THIS.oApp.GetUserOptionSetting("BELL TO") ELSE lvValue = THIS.oApp.GetUserOptionSetting("BELL TO", @laOptions) ENDIF IF VARTYPE(lvValue) = "C" lvValue = STRTRAN(UPPER(lvValue),",0","") lvValue = STRTRAN(lvValue,"[","") lvValue = ALLTRIM(STRTRAN(lvValue,"]","")) IF (NOT EMPTY(lvValue)) AND FILE(lvValue) THIS.opgBell.Value = 3 THIS.txtBell.Value = lvValue ELSE THIS.txtBell.Value = SET("BELL",1) ENDIF ELSE THIS.txtBell.Value = SET("BELL",1) ENDIF IF llCurrent lvValue = THIS.oApp.GetUserOptionSetting("CONFIRM") ELSE lvValue = THIS.oApp.GetUserOptionSetting("CONFIRM", @laOptions) ENDIF IF VARTYPE(lvValue) # "C" THIS.chkConfirm.Value = (SET("CONFIRM") = "ON") ELSE THIS.chkConfirm.Value = (lvValue = "ON") ENDIF IF llCurrent lvValue = THIS.oApp.GetUserOptionSetting("SHOWTIPS") ELSE lvValue = THIS.oApp.GetUserOptionSetting("SHOWTIPS", @laOptions) ENDIF IF VARTYPE(lvValue) # "L" THIS.chkShowTips.Value = THIS.ShowTips ELSE THIS.chkShowTips.Value = lvValue ENDIF IF llCurrent lvValue = THIS.oApp.GetUserOptionSetting("cTextDisplayFont") ELSE lvValue = THIS.oApp.GetUserOptionSetting("cTextDisplayFont", @laOptions) ENDIF IF VARTYPE(lvValue) # "C" THIS.cboTextDisplayFont.Value = THIS.oApp.cTextDisplayFont ELSE THIS.cboTextDisplayFont.Value = lvValue ENDIF IF llCurrent lvValue = THIS.oApp.GetUserOptionSetting("HOURS") ELSE lvValue = THIS.oApp.GetUserOptionSetting("HOURS", @laOptions) ENDIF IF VARTYPE(lvValue) # "C" lvValue = TRANSFORM(SET("HOURS")) ENDIF IF THIS.opgHours.Buttons(1).Caption $ lvValue THIS.opgHours.Value = 1 ELSE THIS.opgHours.Value = 2 ENDIF ENDPROC PROCEDURE displayuserdefaultoptions * show values from default record in the dialog THIS.DisplayOptions("SAVED") ENDPROC PROCEDURE KeyPress LPARAMETERS nKeyCode, nShiftAltCtrl IF nKeyCode = 27 THIS.Release() ENDIF ENDPROC PROCEDURE saveuseroptionsfromdisplay THIS.SetFromDisplay("SAVE") ENDPROC PROCEDURE setfromdisplay LPARAMETERS tcWhichSet IF VARTYPE(tcWhichSet) # "C" OR ; (NOT INLIST(tcWhichSet,"CURRENT","SAVE")) RETURN .F. ENDIF LOCAL llCurrent, lcArray, loForm, loMediator llCurrent = (tcWhichSet = "CURRENT") IF llCurrent lcArray = "THIS.oApp.aCurrentUserOpts" ELSE LOCAL ARRAY laOptions[1,4] lcArray = "laOptions" ENDIF DIME &lcArray.[6,4] * change depending on how many options you have... * and fill the array any way you want, just * so long as your usage matches * what you put in the array! &lcArray.[1,1] = "SHOWTIPS" &lcArray.[1,2] = THIS.chkShowTips.Value &lcArray.[1,3] = .F. && form or form member property &lcArray.[1,4] = .F. && private to datasessions/enabled forms, ; && and applied only on that level as requested && by form mediator object &lcArray.[2,1] = "CONFIRM" &lcArray.[2,2] = IIF(THIS.chkConfirm.Value,"ON","OFF") &lcArray.[2,3] = .T. && SET, not form or form member property &lcArray.[2,4] = .F. &lcArray.[3,1] = "HOURS" &lcArray.[3,2] = "TO "+THIS.opgHours.Buttons(THIS.opgHours.Value).Caption &lcArray.[3,3] = .T. && SET, not form or form member property &lcArray.[3,4] = .F. &lcArray.[4,1] = "cTextDisplayFont" &lcArray.[4,2] = IIF(EMPTY(THIS.cboTextDisplayFont.Value), ; THIS.oApp.cTextDisplayFont, ; THIS.cboTextDisplayFont.Value) &lcArray.[4,3] = .F. && application or application member property &lcArray.[4,4] = .T. && set on a global level, not form/session private &lcArray.[5,1] = "BELL" &lcArray.[5,2] = IIF(THIS.opgBell.Value = 1, "OFF","ON") &lcArray.[5,3] = .T. && SET, not app or app member property &lcArray.[5,4] = .T. &lcArray.[6,1] = "BELL TO" * I could have placed the word either in the first or * second part of the 'SET phrase', as you * can see from the SET HOURS entry, but in this case * putting it in the first one allows me to identify the * two SET BELL items uniquely later, when I use the * application.GetUserOptionSetting() method to find them. &lcArray.[6,2] = " " IF THIS.opgBell.Value = 3 AND (NOT EMPTY(ALLTRIM(THIS.txtBell.Value))) &lcArray.[6,2] = &lcArray.[6,2]+"["+ALLTR(THIS.txtBell.Value)+"],0" ENDIF &lcArray.[6,3] = .T. &lcArray.[6,4] = .T. IF llCurrent THIS.oApp.ApplyGlobalUserOptions() IF _SCREEN.FormCount > 0 * I am deliberately using * _SCREEN rather than THIS.oApp.aForms * here to account for collaborators or * a modal dialog under this one -- * anything that has a mediator, * not just anything in the aForms modeless * collection, should have properties applied. * It's faster, too, and I don't have to * distinguish between forms and formsets in * the _SCREEN collection FOR EACH loForm IN _SCREEN.Forms loMediator = THIS.oApp.GetFormMediatorRef(loForm) IF VARTYPE(loMediator) = "O" loMediator.DoSessionSets() loForm.Refresh() ENDIF ENDFOR ENDIF ELSE REPLACE (THIS.oApp.cUserTableAlias+".UserOpts") WITH "" && this may avoid some bloat SAVE ALL LIKE laOptions TO MEMO (THIS.oApp.cUserTableAlias+".UserOpts") THIS.cmdResetToDefault.Enabled = .T. ENDIF ENDPROC PROCEDURE setuseroptionsfromdisplay THIS.SetFromDisplay("CURRENT") ENDPROC PROCEDURE cboTextDisplayFont.Init LOCAL ARRAY laFonts[1] LOCAL lcFont IF NOT EMPTY(AFONT(laFonts)) FOR EACH lcFont IN laFonts THIS.AddItem(lcFont) ENDFOR ENDIF ENDPROC PROCEDURE cmdApply.Click THISFORM.SetUserOptionsFromDisplay() WAIT WINDOW NOWAIT LEFT(OPTIONS_APPLIED_LOC,254) ENDPROC PROCEDURE cmdPickWav.Click LOCAL lcFile lcFile = UPPER(ALLTRIM(GETFILE("wav"))) IF EMPTY(lcFile) OR (NOT FILE(lcFile)) THISFORM.txtBell.Value = "" IF THISFORM.opgBell.Value = 3 THISFORM.opgBell.Value = 2 ENDIF ELSE THISFORM.txtBell.Value = lcFile THISFORM.opgBell.Value = 3 ENDIF ENDPROC PROCEDURE cmdResetToDefault.Click * get values from current record THISFORM.DisplayUserDefaultOptions() WAIT WINDOW NOWAIT LEFT(OPTIONS_DEFAULTS_SHOWN_LOC,254) ENDPROC PROCEDURE cmdSetDefault.Click * save values from this dialog to * to current record -- not to current values THISFORM.SaveUserOptionsFromDisplay() WAIT WINDOW NOWAIT LEFT(OPTIONS_DEFAULTS_SAVED_LOC,254) ENDPROC PROCEDURE opgBell.InteractiveChange IF THIS.Value = 3 AND EMPTY(THISFORM.txtBell.Value) THISFORM.cmdPickWav.Click() ENDIF ENDPROC ENDDEFINE DEFINE CLASS _reportpicker AS _documentpicker OF "_framewk.vcx" && superclass for framework-supplied dialog to execute or modify (in New mode -- not yet implemented) a report document *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> #INCLUDE "_framewk.h" * Caption = "Choose a report to run" DoCreate = .T. Name = "_reportpicker" lstDocuments.Name = "lstDocuments" cmdOK.Name = "cmdOK" cmdCancel.Name = "cmdCancel" * PROCEDURE execdocument LOCAL liRow liRow = THISFORM.lstDocuments.Value IF EMPTY(liRow) RETURN ENDIF DO CASE CASE NOT EMPTY(THIS.aDocuments[liRow,4]) && alt-exec LOCAL lcStatement lcStatement = ALLTR(THIS.aDocuments[liRow,4]) &lcStatement CASE THIS.aDocuments[liRow,3] && wrapped DO (ALLTRIM(THIS.aDocuments[liRow,2])) OTHERWISE && report THIS.oApp.DoReport(ALLTRIM(THIS.aDocuments[liRow,2]), ; ALLTRIM(THIS.aDocuments[liRow,1])) ENDCASE ENDPROC PROCEDURE filldocumentsarray LPARAMETERS tcMetaTableName DIME THIS.aDocuments[1,4] IF EMPTY(tcMetaTableName) RETURN .F. ENDIF LOCAL lcConditions IF THIS.lNew lcConditions = " AND DOC_NEW " ELSE lcConditions = " AND DOC_OPEN " ENDIF lcConditions = lcConditions + " AND NOT DELETED() " IF THIS.lSorted lcConditions = lcConditions + " ORDER BY 1 " ENDIF SELECT DOC_DESCR, DOC_EXEC, ; DOC_WRAP, ALT_EXEC ; FROM (tcMetaTableName) ; WHERE DOC_TYPE = PJX_META_DOC_REPORT_TYPE ; &lcConditions ; INTO ARRAY THIS.aDocuments RETURN ( _TALLY # 0) ENDPROC PROCEDURE Init LPARAMETERS toApp, tlAdd IF NOT DODEFAULT(toApp,tlAdd) RETURN .F. ENDIF * note: the editing capability isn't implemented yet. IF tlAdd THIS.Caption = REPORTPICKER_CAPTION_MODIFY_LOC ELSE THIS.Caption = REPORTPICKER_CAPTION_RUN_LOC ENDIF ENDPROC ENDDEFINE DEFINE CLASS _splash AS _form OF "..\ffc\_base.vcx" && superclass for framework-supplied default splash screen *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="imgApplication" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblApplicationName" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="lblCredits" UniqueID="" Timestamp="" /> * *p: cauthor *p: ccaption *p: ccompany *p: ccopyright *p: cimage *p: ctrademark * * AlwaysOnTop = .T. AutoCenter = .T. BorderStyle = 2 Caption = ("") cauthor = ccaption = ccompany = ccopyright = cimage = Closable = .F. ControlBox = .F. ctrademark = cversion = Desktop = .T. DoCreate = .T. Height = 285 KeyPreview = .T. MaxButton = .F. MinButton = .F. Name = "_splash" ShowWindow = 2 TitleBar = 0 Width = 305 * ADD OBJECT 'imgApplication' AS _image WITH ; BackStyle = 0, ; Height = 120, ; Left = 80, ; Name = "imgApplication", ; Stretch = 1, ; Top = 12, ; Width = 144 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="image" /> ADD OBJECT 'lblApplicationName' AS _label WITH ; Alignment = 2, ; AutoSize = .F., ; Caption = "Application Name", ; FontName = "MS Sans Serif", ; Height = 17, ; Left = 14, ; Name = "lblApplicationName", ; Top = 156, ; Width = 276 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'lblCredits' AS _label WITH ; Alignment = 2, ; AutoSize = .F., ; Caption = "Credits", ; FontName = "MS Sans Serif", ; Height = 84, ; Left = 14, ; Name = "lblCredits", ; Top = 180, ; Width = 274 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> PROCEDURE Init LPARAMETERS tcCaption, tcVersion, tcAuthor, tcCompany, tcCopyright, tcTrademark, tcImage LOCAL liPCount liPCount = PCOUNT() IF DODEFAULT() IF liPCount > 0 AND VARTYPE(tcCaption) = "C" THIS.cCaption = tcCaption ENDIF IF liPCount > 1 AND VARTYPE(tcVersion) = "C" THIS.cVersion = tcVersion ENDIF IF liPCount > 2 AND VARTYPE(tcAuthor) = "C" THIS.cAuthor = tcAuthor ENDIF IF liPCount > 3 AND VARTYPE(tcCompany) = "C" THIS.cCompany = tcCompany ENDIF IF liPCount > 4 AND VARTYPE(tcCopyright) = "C" THIS.cCopyright = tcCopyright ENDIF IF liPCount > 5 AND VARTYPE(tcTrademark) = "C" THIS.cTrademark = tcTrademark ENDIF IF liPcount > 6 AND VARTYPE(tcImage) = "C" THIS.cImage = tcImage ENDIF THIS.cImage = ALLTR(THIS.cImage) IF AT(".",THIS.cImage) = 0 THIS.cImage = THIS.cImage+".bmp" ENDIF THIS.cImage = FULLPATH(THIS.cImage) IF (FILE(THIS.cImage)) THIS.imgApplication.Visible = .T. THIS.imgApplication.Picture = THIS.cImage ELSE THIS.imgApplication.Visible = .F. ENDIF IF NOT EMPTY(THIS.cCaption) THIS.lblApplicationName.Caption = TRANS(THIS.cCaption) ENDIF. THIS.lblCredits.Caption = TRANS(THIS.cAuthor) THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; TRANS(THIS.cCompany) THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; TRANS(THIS.cCopyright) THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; TRANS(THIS.cTrademark) THIS.lblCredits.Caption = THIS.lblCredits.Caption + ; CHR(13)+ ; TRANS(THIS.cVersion) THIS.Titlebar = 0 ELSE RETURN .F. ENDIF ENDPROC ENDDEFINE DEFINE CLASS _standardtoolbar AS _modalawaretoolbar OF "..\ffc\_ui.vcx" && superclass for framework-supplied default startup toolbar (exists throughout the life of the application, if used) *< CLASSDATA: Baseclass="toolbar" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="_separator3" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdNew" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdOpen" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdSave" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdRevert" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="_separator2" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdPrint" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="_separator1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdCut" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdCopy" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdPaste" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="_separator4" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="cmdHelp" UniqueID="" Timestamp="" /> * *p: lprintonerecord *p: oapp * * Caption = "Standard" ControlBox = .F. Height = 30 Left = 0 Name = "_standardtoolbar" oapp = .NULL. Top = 0 Width = 242 * ADD OBJECT '_separator1' AS _separator WITH ; Height = 24, ; Left = 136, ; Name = "_separator1", ; Style = 1, ; Top = 3, ; Width = 3 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="separator" /> ADD OBJECT '_separator2' AS _separator WITH ; Height = 35, ; Left = 105, ; Name = "_separator2", ; Style = 1, ; Top = 3, ; Width = 5 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="separator" /> ADD OBJECT '_separator3' AS _separator WITH ; Height = 0, ; Left = 5, ; Name = "_separator3", ; Top = 3, ; Width = 0 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="separator" /> ADD OBJECT '_separator4' AS _separator WITH ; Height = 31, ; Left = 213, ; Name = "_separator4", ; Style = 1, ; Top = 3, ; Width = 3 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="separator" /> ADD OBJECT 'cmdCopy' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 159, ; Name = "cmdCopy", ; Picture = graphics\copy.bmp, ; SpecialEffect = 2, ; ToolTipText = "Copy", ; Top = 3, ; Width = 24, ; ZOrderSet = 9 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdCut' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 136, ; Name = "cmdCut", ; Picture = graphics\cut.bmp, ; SpecialEffect = 2, ; ToolTipText = "Cut", ; Top = 3, ; Width = 24, ; ZOrderSet = 8 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdHelp' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 213, ; Name = "cmdHelp", ; Picture = graphics\help.bmp, ; SpecialEffect = 2, ; ToolTipText = "Help", ; Top = 3, ; Width = 24, ; ZOrderSet = 12 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdNew' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 5, ; Name = "cmdNew", ; Picture = graphics\new.bmp, ; SpecialEffect = 2, ; ToolTipText = "New", ; Top = 3, ; Width = 24, ; ZOrderSet = 1 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdOpen' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 28, ; Name = "cmdOpen", ; Picture = graphics\open.bmp, ; SpecialEffect = 2, ; ToolTipText = "Open", ; Top = 3, ; Width = 24, ; ZOrderSet = 2 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdPaste' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 182, ; Name = "cmdPaste", ; Picture = graphics\paste.bmp, ; SpecialEffect = 2, ; ToolTipText = "Paste", ; Top = 3, ; Width = 24, ; ZOrderSet = 10 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdPrint' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 105, ; Name = "cmdPrint", ; Picture = graphics\print.bmp, ; SpecialEffect = 2, ; ToolTipText = "Print", ; Top = 3, ; Width = 24, ; ZOrderSet = 6 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdRevert' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 74, ; Name = "cmdRevert", ; Picture = graphics\revert.bmp, ; SpecialEffect = 2, ; ToolTipText = "Revert", ; Top = 3, ; Width = 24, ; ZOrderSet = 4 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> ADD OBJECT 'cmdSave' AS _commandbutton WITH ; Caption = "", ; Height = 24, ; Left = 51, ; Name = "cmdSave", ; Picture = graphics\save.bmp, ; SpecialEffect = 2, ; ToolTipText = "Save", ; Top = 3, ; Width = 24, ; ZOrderSet = 3 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="commandbutton" /> PROCEDURE Destroy DODEFAULT() THIS.oApp = .NULL. ENDPROC PROCEDURE Refresh LOCAL llActiveEditingControl IF THIS.lDisabledForModal RETURN ENDIF * .T. TO THIS.cmdNew.Enabled, ; * THIS.cmdOpen.Enabled, ; * THIS.cmdHelp.Enabled is already handled * automatically, now for specific button behavior: LOCAL ARRAY laTempx[1] LOCAL liSession IF TYPE("_SCREEN.ActiveForm") = "O" WITH _SCREEN.ActiveForm llActiveEditingControl = (TYPE(".ActiveControl.SelText") = "C") STORE llActiveEditingControl AND ; (NOT EMPTY(.ActiveControl.SelLength)) TO ; THIS.cmdCut.Enabled, THIS.cmdCopy.Enabled STORE llActiveEditingControl AND ; (NOT EMPTY(_CLIPTEXT)) TO ; THIS.cmdPaste.Enabled ENDWITH IF VARTYPE(THIS.oApp) # "O" STORE .F. TO THIS.cmdSave.Enabled, ; THIS.cmdRevert.Enabled, ; THIS.cmdPrint.Enabled, ; THIS.cmdHelp.Enabled ELSE liSession = IIF(UPPER(TYPE("_SCREEN.ActiveForm.Parent.BaseClass")) == ; "FORMSET", _SCREEN.ActiveForm.Parent.DataSessionID, ; _SCREEN.ActiveForm.DataSessionID) IF EMPTY(AUSED(laTempx, liSession)) STORE .F. TO THIS.cmdSave.Enabled, ; THIS.cmdRevert.Enabled, ; THIS.cmdPrint.Enabled ENDIF IF EMPTY(THIS.oApp.cHelpFile) STORE .F. TO THIS.cmdHelp.Enabled ENDIF ENDIF ELSE * no active form but may be system window ready for editing * etc... STORE .F. TO THIS.cmdSave.Enabled, ; THIS.cmdRevert.Enabled, ; THIS.cmdPrint.Enabled IF VARTYPE(THIS.oApp) # "O" OR EMPTY(THIS.oApp.cHelpFile) STORE .F. TO THIS.cmdHelp.Enabled ENDIF IF NOT EMPTY(WONTOP()) STORE .T. TO THIS.cmdCut.Enabled, ; THIS.cmdCopy.Enabled STORE (NOT EMPTY(_CLIPTEXT)) TO ; THIS.cmdPaste.Enabled ELSE STORE .F. TO THIS.cmdCut.Enabled, ; THIS.cmdCopy.Enabled, ; THIS.cmdPaste.Enabled ENDIF ENDIF ENDPROC PROCEDURE cmdCopy.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DoMenuItemInFrame("COPY") ENDIF ENDPROC PROCEDURE cmdCut.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DoMenuItemInFrame("CUT") ENDIF ENDPROC PROCEDURE cmdHelp.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DoHelp() ENDIF ENDPROC PROCEDURE cmdNew.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DoNewOpen(.T.) ENDIF ENDPROC PROCEDURE cmdOpen.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DoNewOpen() ENDIF ENDPROC PROCEDURE cmdPaste.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DoMenuItemInFrame("PASTE") ENDIF ENDPROC PROCEDURE cmdPrint.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DoTableOutPut(THIS.Parent.lPrintOneRecord) ENDIF ENDPROC PROCEDURE cmdRevert.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DataRevert() ENDIF ENDPROC PROCEDURE cmdSave.Click IF VARTYPE(THIS.Parent.oApp) = "O" THIS.Parent.oApp.DataUpdate() ENDIF ENDPROC ENDDEFINE DEFINE CLASS _topform AS _form OF "..\ffc\_base.vcx" && superclass for "frame" or "parent window", for MDI applications existing outside _screen *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> #INCLUDE "_framewk.h" * *p: cmenuname && Holds a unique menu name for association with this form so that it can be RELEASEd EXTENDED when the form is destroyed. *p: oapp * * AutoCenter = .T. Caption = "Top Form Frame window" cmenuname = ("") DoCreate = .T. Height = 454 Name = "_topform" oapp = .NULL. ShowWindow = 2 Width = 631 * PROCEDURE Destroy DODEFAULT() THIS.oApp = .NULL. IF NOT EMPTY(THIS.cMenuName) RELEASE MENU (THIS.cMenuName) EXTENDED ENDIF ENDPROC PROCEDURE Load IF DODEFAULT() THIS.cMenuName = "M"+SYS(2015) ELSE RETURN .F. ENDIF ENDPROC PROCEDURE QueryUnload LOCAL loTemp, llReturn IF VARTYPE(THIS.oApp) = "O" llReturn = THIS.oApp.OnShutDown(.T.) IF llReturn loTemp = THIS.oApp THIS.oApp = .NULL. loTemp.oFrame = .NULL. loTemp.Release() ENDIF ELSE llReturn = .T. ENDIF IF NOT llReturn NODEFAULT ENDIF RETURN llReturn ENDPROC ENDDEFINE DEFINE CLASS _userlogin AS _dialog OF "_framewk.vcx" && superclass for framework-supplied default dialog for user login *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder *< OBJECTDATA: ObjPath="txtName" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="txtPassword" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="_label1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="_label2" UniqueID="" Timestamp="" /> #INCLUDE "_framewk.h" * *m: addusernow *m: checkpasswordinfo *m: faillogin *m: incrementfailedattempts *m: oktoadduser && Abstract in the base, allows you to indicate what conditions are required to add a new user rather than simply validating existing users. *m: storenewpasswordinfo *p: itries && Number of tries before the user login fails. *p: itriesallowed *p: laddinguser *p: lvalidpassword *p: lvaliduser *p: oapp * PROTECTED itriesallowed * AlwaysOnTop = .T. BufferMode = 1 Caption = "User Login" DoCreate = .T. Height = 100 itries = 0 itriesallowed = 3 KeyPreview = .T. Name = "_userlogin" Width = 375 * ADD OBJECT '_label1' AS _label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Name:", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 15, ; Left = 8, ; Name = "_label1", ; Top = 24, ; Width = 33 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT '_label2' AS _label WITH ; AutoSize = .T., ; BackStyle = 0, ; Caption = "Password:", ; FontName = "MS Sans Serif", ; FontSize = 8, ; Height = 15, ; Left = 8, ; Name = "_label2", ; Top = 60, ; Width = 51 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="label" /> ADD OBJECT 'txtName' AS _textbox WITH ; FontBold = .T., ; FontName = "Courier New", ; Height = 24, ; Left = 68, ; Name = "txtName", ; SelectOnEntry = .T., ; Top = 19, ; Width = 294 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="textbox" /> ADD OBJECT 'txtPassword' AS _textbox WITH ; FontBold = .T., ; FontName = "Courier New", ; Height = 24, ; Left = 68, ; Name = "txtPassword", ; PasswordChar = "*", ; SelectOnEntry = .T., ; Top = 55, ; Width = 294 *< END OBJECT: ClassLib="..\ffc\_base.vcx" BaseClass="textbox" /> PROCEDURE addusernow LOCAL lcName THIS.lAddingUser = .F. IF THIS.OKToAdduser() IF (MESSAGEBOX(LOGIN_ADD_USER_LOC , ; MB_ICONEXCLAMATION+MB_YESNO, ; LOGIN_USER_NOT_FOUND_LOC) = IDYES) lcName = ALLTRIM(THIS.txtName.Value) INSERT INTO (THIS.oApp.cUserTableAlias) ; ((THIS.oApp.cUserTableIDField)) ; VALUES (lcName) THIS.lAddingUser = .T. MESSAGEBOX(LOGIN_NEW_USER_INFO_LOC,0,THIS.Caption) ENDIF ENDIF RETURN THIS.lAddingUser ENDPROC PROCEDURE applyappattributes LPARAMETERS toApp LOCAL llSuccess llSuccess = DODEFAULT(toApp) IF llSuccess IF VARTYPE(toApp.cUserTableAlias) # "C" OR NOT USED(toApp.cUserTableAlias) llSuccess = .F. ELSE THIS.Caption = toApp.cCaption + " " + LOGIN_CAPTION_LOC IF NOT EMPTY(toApp.cCurrentUser) IF toApp.SeekCurrentUser() THIS.txtName.Value = toApp.cCurrentUser THIS.lValidUser = .T. ELSE THIS.lValidUser = .F. ENDIF ELSE THIS.lValidUser = .F. ENDIF THIS.lValidPassword = .F. THIS.oApp = toApp ENDIF ENDIF IF NOT llSuccess THIS.Release() ENDIF ENDPROC PROCEDURE checkpasswordinfo LPARAMETERS tcValueToCheck RETURN (THIS.oApp.CheckPassword(tcValueToCheck)) ENDPROC PROCEDURE Destroy THIS.oApp = .NULL. ENDPROC PROCEDURE faillogin * this is the equivalent of a failed * SEEK in the table IF RECCOUNT(THIS.oApp.cUserTableAlias) > 0 GO BOTTOM IN (THIS.oApp.cUserTableAlias) SKIP IN (THIS.oApp.cUserTableAlias) ENDIF ENDPROC PROCEDURE incrementfailedattempts THIS.iTries = THIS.iTries + 1 IF THIS.iTries >= THIS.iTriesAllowed MESSAGEBOX(LOGIN_TRIES_EXCEEDED_LOC,MB_ICONSTOP,THIS.Caption) THIS.FailLogIn() THIS.Release() ENDIF ENDPROC PROCEDURE KeyPress LPARAMETERS nKeyCode, nShiftAltCtrl IF nKeyCode = 27 THIS.FailLogIn() THIS.Release() ENDIF ENDPROC PROCEDURE oktoadduser && Abstract in the base, allows you to indicate what conditions are required to add a new user rather than simply validating existing users. * abstract in the base, would be done * according to any conditions you like. * certainly there has to be some way of adding * new users at startup, * if no currently-valid user exists. RETURN .T. ENDPROC PROCEDURE QueryUnload IF THIS.ReleaseType = 1 && box hit IF THIS.lValidUser AND THIS.lValidPassword IF THIS.lAddingUser THIS.StoreNewPasswordInfo(ALLTR(THIS.txtPassword.Value)) ELSE IF NOT THIS.CheckPasswordInfo(ALLTR(THIS.txtPassword.Value)) WAIT WINDOW LEFT(LOGIN_WRONG_PASSWORD_LOC,254) TIMEOUT 2 THIS.txtPassword.SetFocus() NODEFAULT ENDIF ENDIF ELSE THIS.FailLogIn() ENDIF ENDIF ENDPROC PROCEDURE storenewpasswordinfo LPARAMETERS tcValueToStore ASSERT VARTYPE(tcValueToStore) = "C" THIS.oApp.StorePassword(tcValueToStore) ENDPROC PROCEDURE txtName.Valid LOCAL llSuccess THISFORM.lValidPassword = .F. IF EMPTY(THIS.Value) THISFORM.lValidUser = .F. RETURN ENDIF llSuccess = THISFORM.oApp.SeekCurrentUser(THIS.Value) IF NOT llSuccess * do they want a new user? llSuccess = THISFORM.AddUserNow() ENDIF THISFORM.lValidUser = llSuccess IF NOT llSuccess IF SET("BELL") = "ON" ?? CHR(7) ENDIF WAIT WINDOW LEFT(LOGIN_USER_NOT_FOUND_LOC,254) TIMEOUT 2 THISFORM.IncrementFailedAttempts() ENDIF IF llSuccess AND (NOT THISFORM.lAddingUser) AND (NOT EMPTY(THISFORM.txtPassword.Value)) IF THISFORM.CheckPasswordInfo(ALLTR(THISFORM.txtPassword.Value)) THISFORM.Release() ENDIF ENDIF RETURN llSuccess ENDPROC PROCEDURE txtPassword.Valid ASSERT (NOT EOF(THISFORM.oApp.cUserTableAlias)) LOCAL llSuccess, lcPassword lcPassword = ALLTRIM(THIS.Value) IF THISFORM.lAddingUser && (AND NOT EMPTY(lcPassword)) THISFORM.StoreNewPasswordInfo(lcPassword) THISFORM.lAddingUser = .F. THISFORM.lValidUser = .T. llSuccess = .T. ENDIF DO CASE * CASE EMPTY(lcPassword) * THISFORM.lValidPassword = .F. CASE THISFORM.lValidUser llSuccess = THISFORM.CheckPasswordInfo(lcPassword) THISFORM.lValidPassword = llSuccess OTHERWISE THISFORM.lValidPassword = .F. ENDCASE IF llSuccess THISFORM.Release() ELSE IF SET("BELL") = "ON" ?? CHR(7) ENDIF IF THISFORM.lValidUser * WAIT WINDOW TIMEOUT 2 ; * LEFT(IIF(EMPTY(lcPassword),; * LOGIN_EMPTY_PASSWORD_LOC,; * LOGIN_WRONG_PASSWORD_LOC ),254) WAIT WINDOW TIMEOUT 2 ; LEFT(LOGIN_WRONG_PASSWORD_LOC,254) THISFORM.IncrementFailedAttempts() IF EMPTY(lcPassword) RETURN 0 ENDIF ENDIF ENDIF ENDPROC ENDDEFINE