home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
102
/
LANGWN23.ZIP
/
WINHELP.BAS
< prev
Wrap
BASIC Source File
|
1993-03-10
|
108KB
|
2,823 lines
DEFINT A-Z
' ONLINE HELP FOR LANGWIN ROUTINES
' Hit F2 to see list of routines
' (same names as LangWin routines,
' except corresponding help routines end with a period).
' The following routines are documented:
DECLARE FUNCTION ActivateButton. ()
DECLARE FUNCTION BlankWin. ()
DECLARE SUB ChangeButtonFocus. ()
DECLARE FUNCTION ChangeDir. ()
DECLARE FUNCTION ChangeDrive. ()
DECLARE FUNCTION CloseWindow. ()
DECLARE FUNCTION DeactivateButton. ()
DECLARE SUB GetButtonPress. ()
DECLARE FUNCTION GetCurDir.$ ()
DECLARE FUNCTION GetCurDrive.$ ()
DECLARE FUNCTION GetFileNames. ()
DECLARE SUB GetMousePos. ()
DECLARE FUNCTION GetVerNum.$ ()
DECLARE FUNCTION GrowScrollText. ()
DECLARE SUB HideMouseCursor. ()
DECLARE FUNCTION InitMouse. ()
DECLARE FUNCTION IsWinOpen. ()
DECLARE SUB LangWinInit. ()
DECLARE FUNCTION MakeBox. ()
DECLARE FUNCTION MakeCheckBox. ()
DECLARE FUNCTION MakeHorizLine. ()
DECLARE FUNCTION MakeInputField. ()
DECLARE FUNCTION MakePushButton. ()
DECLARE FUNCTION MakeVertLine. ()
DECLARE FUNCTION MouseExists. ()
DECLARE SUB NewFocusWindow. ()
DECLARE FUNCTION OpenScrollWindow. ()
DECLARE SUB RefreshScrollText. ()
DECLARE SUB ReShowInputField. ()
DECLARE SUB ReShowPage. ()
DECLARE SUB ReShowText. ()
DECLARE SUB SetColor. ()
DECLARE SUB SetMousePos. ()
DECLARE SUB SetXLimit. ()
DECLARE SUB SetYLimit. ()
DECLARE SUB ShowMouseCursor. ()
DECLARE FUNCTION ShowTitle. ()
DECLARE FUNCTION ShowWinText. ()
DECLARE SUB WaitTicks. ()
DECLARE FUNCTION WinEvent. ()
END
FUNCTION ActivateButton.
'Purpose:
'--------
' Activate a button by restoring its text.
' When the button was deactivated (see DeactivateButton function),
' it's text was cleared and WinEvent no longer recognized clicks on
' the button. This function is used to reset the text so that WinEvent
' will recognize it and user can again click the button.
' Window containing the button will be given focus before the
' button's text is restored. User has option whether or not
' to return focus to the window that was current when ActivateButton
' was called.
' (New with V2.0)
' (Button's text no longer needed as a parameter with V2.1)
'Routine Type:
'-------------
' Function.
'Parameters:
'-----------
' ButtonHandle - handle of button to be activated
' FocusSw - switch to determine if window that was current when
' ActivateButton was called should be given focus back
' after button has been activated. ActivateButton WILL
' give focus to the window containing the button before
' it updates the text. This could produce one change in
' focus (depending on which window had focus when function
' was called). After the button has been activated, you can
' either leave focus in the window containing the button,
' or give focus back to the original window (may produce
' another focus change on screen). See Notes below for
' more details on using this parameter.
' = 0 do not change focus back to original
' = 1 change focus back to original window
'
'
'Return Values:
'--------------
' 0 - button successfully activated
' 1 - ButtonHandle was not within index range
' of ButtonsData array. Typically, ButtonHandle
' should be between 1 and MaxButtons.
' 2 - ButtonHandle was within range, but it did
' not have a corresponding open window. This
' probably means ButtonHandle was incorrect.
' 3 - ButtonHandle did not correspond to a push
' button.
'Notes:
'------
' With LangWin V2.1, the text of the button being activated is no longer
' required as an input parameter. The button's original text is remembered
' when it is deactivated, and will automatically be displayed when the
' button is activated. If you used the string passed to the V2.0 version
' ActivateButton to change the button's text, then you must now update
' the contents of ButtonsText(han) instead, where han is the button's
' handle. In this case, do not place a string into ButtonsText that
' exceeds the button's length which is found in ButtonsData(han,4).
' Some comments on the use of the FocusSw parameter:
' Typically, ActivateButton is called just after closing a child window to
' re-activate a button in the parent window. In this case, you cannot be
' sure the parent window had focus when you call ActivateButton (after
' closing the child). The close routine gives focus to the next window on
' the stack (which can change dynamically depending upon what window the
' user clicked last before closing the child). If the parent was not the
' last window on the stack, then ActivateButton will have caused one
' change in focus (it automatically gives focus to the window with the
' given button before changing its text). Thus, leaving focus in the window
' with the button (i.e., the parent) will be less disruptive visually.
' Call ActivateButton with the FocusSw set to 0 to leave focus in window
' with the given button.
END FUNCTION
FUNCTION BlankWin.
'Purpose:
'--------
' Open/display an empty window.
' New window is given focus.
'
'
'Routine Type:
'-------------
' Function.
'
'
'V2.0 Changes:
'-------------
' Negative value for WinColor% will make window unmovable.
' New ModeSw% parameter required.
' Negative value for ModeSw% will make window shadowless.
' Return values changed:
' Negative value returned if window not opened successfully.
' Window's number (>0) returned if window is opened successfully.
' 0 is not a valid return code.
' -12 is a new return code.
'Parameters:
'-----------
' StartRow%: starting row (upper left)
' StartCol%: starting column (upper left)
' EndRow%: ending row (bottom right)
' EndCol%: ending column (bottom right)
' WinColor%: color attribute of window (0-15)
' (NEGATIVE value will make window unmovable)
' BorderColor%: color attribute of border (0-15)
' (NEGATIVE value will prevent window from being resized)
' BorderType%: 1=single line; 2=double line
' TextColor%: color attribute for scrollable text in the window (0-15)
' (since BlankWin has no scrollable text, this attribute
' is only used for the close icon if present)
' CloseIcon%: 1=display a close icon; 0=no close icon
' [regardless of whether a close icon is displayed, the ESC
' key will always generate a close action]
' [cannot specify a close icon for a window with ModeSw=4]
' ModeSw% Mode of window (effects how/if/when WinEvent returns
' control after an action has taken place)
' (NEGATIVE value for mode will generate a shadowless window):
' 1 = modeless window (normal). if modeless window has
' focus, user can click on any other visible window
' and it will be given focus by WinEvent. WinEvent will
' continue to process the new window until an action
' is taken in the current window.
' 2 = modal window. if modal window has focus, any attempt
' to click on another window will be ignored by WinEvent.
' this type of window can be used to display a message,
' and force user to close the window before continuing
' (e.g., for error messages).
' 3 = immediate close window. if this type window has focus,
' clicking on another window, or even the wallpaper, will
' cause WinEvent to return a close action (1). This can be
' used for menu windows that should be closed if user
' clicks somewhere else on the screen.
' 4 = wallpaper window. can never be selected, only serves as
' background for other windows (usually of same color
' as the wallpaper window). since wallpaper windows can
' never be given focus, they should not be given any
' objects (buttons, etc) and cannot have a close icon.
'Return Values:
'--------------
' >0: window opened successfully (win number returned)
' -1: not enough storage to open another new window.
' [must increase value of MaxWindows global parameter]
' -2: not enough room for window's rows (+1 for shadow) on screen
' -3: not enough room for window's columns (+2 for shadow) on screen
' -4: window's color attribute out of range (must be 0-15)
' -5: window's border color attribute out of range (must be 0-15)
' -6: invalid value for BorderType (must be -1 or -2)
' -7: text color attribute out of range (must be 0-15)
' -8: window not long enough (must be >=3)
' -9: window not wide enough (must be >=3)
'-10: [not used]
'-11: [not used]
'-12: invalid value for window mode (ModeSw) - must be 1 to 4
'
'Notes:
'------
' You MUST check to see if window opened successfully (return code>0)
' before calling any other LangWin functions or routines.
' Otherwise, you will either get errors (such as Illegal Function Call,
' Subscript Out of Range, etc.) or process the previously opened window
' by mistake.
' BlankWin sets the global variable AnyWinOpen to TRUE.
' this can be used to control a DO/LOOP that executes WinEvent
' as long as there is an open window on the screen. However, if an
' information only window is open, then you must use another criteria to
' end the DO/LOOP because the info only window will always be open.
' In this case, termination should occur when a close action
' occurs in the main window.
END FUNCTION
SUB ChangeButtonFocus.
'Purpose:
'--------
' Change the visual appearance of a given button or check box.
' Either display its text in reverse video (background/foreground) to show
' it has focus, or display its text in normal video (foreground/background).
' This routine only changes the physical appearance of the button/check box,
' it does NOT give it focus logically (see notes below).
' Typical use would be to give a specific button/check box focus
' when a window is first created. In this way, the object could
' serve as the "default" choice (i.e., user could select the
' default by clicking it with the mouse, or by just hitting ENTER
' since the default would already have focus).
' Assumes that window containing the button/check box has focus.
' If it does not, call NewFocusWindow first to give focus to appropriate
' window.
'
'Routine Type:
'-------------
' Subroutine
'Parameters:
'-----------
' Handle: handle of button or check box
' Switch: 0 = give focus (reverse video)
' 1 = clear focus (normal video)
'Notes:
'------
' This routine only changes the visual appearance of the object.
' To change the logical appearance (i.e., so that other LangWin
' routines will recognize whether or not the object has focus),
' you must update the appropriate data structure. In this case,
' WinParms(CurWinPtr, 16) must be set.
' When giving an object focus (i.e., Switch=0), then the object's
' handle must be placed into the data structure as follows:
' WinParms(CurWinPtr,16)=han ' give object logical focus
' CALL ChangeButtonFocus(han, 0) ' give object physical focus
' When clearing focus (i.e., Switch=1), then the data structure must
' be set to show that no object has focus:
' WinParms(CurWinPtr,16)=-1 ' clear logical focus
' CALL ChangeButtonFocus(han, 1) ' clear physical focus
'
END SUB
FUNCTION ChangeDir.
'Purpose:
'--------
' Causes the directory specified in the calling parameter to
' become the default for the drive specified. Does NOT change the default
' drive (see ChangeDrive). If calling parameter has no drive spec, then
' the default drive is assumed.
'
' (New with V2.0)
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' PathName$ - defines the drive (optional) and directory to become current.
' If drive included, then the default directory for that
' drive is set to the directory specified.
' If the drive is omitted, then the default drive is assumed,
' and the default directory for that drive is set.
' Either upper or lower case is acceptable.
' Examples - a:\my\programs (drive a:'s dir is changed)
' B:test (drive b:'s dir is changed)
' \some\stuff (default drive's dir is changed)
'
'Return Values:
'--------------
' 0: Change directory was successful.
' -1: PathName$ parameter was invalid.
' Could be caused by an invalid drive letter,
' or invalid directory specification.
' -2: Some other error occurred.
' OutRegs.ax contains the DOS extended error code.
'
'Notes:
'------
' This function calls DOS interrupt 21h, function 3Bh.
'
' Also see: ChangeDrive, GetCurDir$, GetCurDrive$
'
' ChangeDir will change the defualt directory on the drive specified.
' The default drive is NOT changed (see ChangeDrive). For example,
' if C: is the default drive and ChangeDir("a:\mydir") is executed,
' then the default directory on drive A: becomes \mydir, BUT the default
' drive still remains C:.
' If the specified drive is not ready, your program will get the
' standard "not ready" error condition. You can use an ON ERROR routine
' to trap this condition. The user can be given two alternatives: either
' RETRY (use a RESUME) or IGNORE (use a RESUME NEXT).
END FUNCTION
FUNCTION ChangeDrive.
'Purpose:
'--------
' Change the default drive.
'
' (New with V2.0)
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' DriveLetter$ - Letter to become new default drive.
' Can be either upper or lower case.
' Only the first character in DriveLetter$ string
' will be examined. Cannot be a null string.
'
'
'Return Values:
'--------------
' >0: The number of logical drives specified by the LASTDRIVE
' parameter in CONFIG.SYS. However, if fewer than 5 drives
' is specified in LASTDRIVE, then the value of 5 is returned
' (sorry, this is a DOS quirk, not mine).
' -1: Could not change to the specified drive (drive letter
' specified was probably not a valid drive).
' -2: DriveLetter$ was not a letter.
'
'Notes:
'------
' This function calls DOS interrupt 21h, function 0Eh.
'
' Also see: ChangeDir, GetCurDir$, GetCurDrive$
'
' ChangeDrive will not actually cause I/O to the specified drive.
' Thus, it does not care if the specified drive is ready.
' You can use ChangeDrive to determine the actual drives
' configured on a system. Just loop through every possible
' letter, and issue a ChangeDrive command for it. If return code
' is 0, then drive letter exists (but you don't know if it's ready).
END FUNCTION
FUNCTION CloseWindow.
'Purpose:
'--------
' Close/erase the current window.
' If you want to close a window that is not current,
' call NewFocusWindow to first bring it into focus.
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' None (the current window is automatically closed).
'
'
'Return Values:
'--------------
' 0: window closed successfully
' 1: there were no windows currently open when this routine was called
'Notes:
'-------
' When the last window is closed, the global variable AnyWinOpen
' will be set to FALSE.
' This variable can be used to control a DO/LOOP that executes WinEvent
' as long as there is an open event on the screen. However, if a Mode 4
' window is open, then you must use another criteria to
' end the DO/LOOP because the info only window will always be open.
' In this case, termination should occur when a close action
' occurs in the main window.
' Since CloseWindow only operates on the current window, if you want to
' close a specific window, and are not sure it's current, use the following
' technique (assume the variable win1 contains the number of the window
' to be closed):
' IF IsWinOpen(win1, han) THEN ' if win1 is open, get its handle
' zz = CurWinPtr ' save handle of current window
' CALL NewFocusWindow(han) ' make win1 current
' xx = CloseWindow ' close it
' CALL NewFocusWindow(zz) ' make original win current again
' END IF
' There's another "short-cut" you can use if you just want to close ALL open
' windows (if you want to close a sub-set of all possible windows,
' use the above technique with the numbers of each window to be closed).
' To easily close ALL open windows:
' FOR i = LastWinStack TO 1 STEP -1
' CALL NewFocusWindow(WinStack(i))
' x = CloseWindow
' NEXT
' The WinStack array contains the handles of all open windows, in the order
' in which they appear on the screen. LastWinStack is a global variable
' pointing to the current slot. Thus WinStack(1) contains the handle of the
' first window opened, and WinStack(LastWinStack) contains the handle of the
' window with focus. The above code just closes each window, from the most
' current to the least current.
END FUNCTION
FUNCTION DeactivateButton.
'Purpose:
'--------
' Deactivate a button by setting its text to null (equivalent to
' "fading" the button's text seen in other GUIs). Once the button is
' cleared, user can no longer click on it (WinEvent will not recognize
' the click). This can be used to prevent a user from re-clicking
' a button until the button's corresponding activity has been completed
' and your program has re-activated it (see ActivateButton function).
' Window containing the button will be given focus before the
' button's text is cleared. User has option whether or not
' to return focus to the window that was current when DeactivateButton
' was called.
' (New with V2.0)
'Routine Type:
'-------------
' Function.
'Parameters:
'-----------
' ButtonHandle - handle of button to be activated
' FocusSw - switch to determine if window that was current when
' DeactivateButton was called should be given focus back
' after button has been cleared. DeactivateButton WILL
' give focus to the window containing the button before
' it clears the text. This could produce one change in
' focus (depending on which window had focus when function
' was called). After the button has been cleared, you can
' either leave focus in the window containing the button,
' or give focus back to the original window (may produce
' another focus change on screen). See Notes below for
' more details on using this parameter.
' = 0 do not change focus back to original
' = 1 change focus back to original window
'
'Return Values:
'--------------
' 0 - button successfully cleared.
' 1 - ButtonHandle was not within index range
' of ButtonsData array. Typically, ButtonHandle
' should be between 1 and MaxButtons.
' 2 - ButtonHandle was within range, but it did
' not have a corresponding open window. This
' probably means ButtonHandle was incorrect.
' 3 - ButtonHandle did not correspond to a push
' button.
'Notes:
'------
' Some comments on the use of the FocusSw parameter:
' Typically, DeactivateButton is called after a button is clicked to
' clear the button's text. Once the text is cleared, WinEvent will no
' longer recognize clicks on the button and it will be deactivated.
' If DeactivateButton is called immediately after detecting the button
' click action (3) returned by WinEvent, and before any other window
' is open, then value of FocusSw does not matter (since window that
' had focus before the button was deactivated is the same as the window
' containing the button). In this case, regardless of which value
' (0 or 1) you assign to the FocusSw parameter, focus will remain in the
' window containing the button just cleared. You can then go open a child
' window (or whatever) based upon the meaning of the button clicked.
' Alternatively, you could detect the button click, open a child window
' (which would have focus after it's opened), call DeactivateButton to
' go back and clear the button, and set FocusSw=1 in the call to
' DeactivateButton to cause focus to be given back to the child.
' This will produce two focus changes (from newly opened child back
' to parent to clear the button, then from parent back to child).
' If windows overlap, this will be visually disturbing; I'm not sure
' why anyone would want to use this alternative. In any case, I've provided
' the FocusSw just in case you need it.
END FUNCTION
SUB GetButtonPress.
'Purpose:
'--------
' Returns the current status (up/down) of ALL mouse buttons.
' For the button specified by input parameter, this routine also
' returns the number of presses and position of the mouse at the last
' press (in pixel coordinates). Number of presses is maintained by the
' mouse driver. It is reset by calling GetButtonPress. Other routines
' will also cause the count to be reset (see Notes below).
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' Button%: on INPUT, specifies the button to be checked
' [0 = left, 1 = right, 2 = center]
' : on OUTPUT, specifies CURRENT status of ALL mouse buttons
' [bits set as follows (shown left to right, bits 2 to 0)]:
'
' ..0 left button up
' ..1 left button down
' .0. right button up
' .1. right button down
' 0.. center button (if present) up
' 1.. center button (if present) down
'
' Count%: number of times the button specified by input parameter
' (Button) was pressed since the last time the count was
' reset (by a previous call to this routine or others that
' reset the count - see Notes below).
'
' Horiz%: horizontal pixel coordinate of mouse when button specified
' by input parameter (Button) was last pressed.
'
' Vert%: vertical pixel coordinate of mouse when button specified
' by input parameter (Button) was last pressed.
'
'
'Notes:
'------
' This subroutine calls BIOS interrupt 33h, function 05h.
'
' The input parameter: Button will be MODIFIED by this
' routine. On input, Button specifies the button to checked for
' position and press count. On output, Button specifies the
' up/down status of ALL buttons. Your program must NOT assume that
' the input parameter (Button) remains unchanged.
'
' Horizontal/vertical coordinates returned are in PIXELS. If screen
' positions are desired, use integer division by width/depth of a
' screen character in pixels to get column/row.
'
' Calling ShowMouseCursor and HideMouseCursor will also reset
' the count of button presses (maintained by the mouse driver).
' So, calling the "show" or "hide" routines while waiting for
' button press information can result in an inaccurate count
' (anyway, there should be no need to "hide" the mouse if you are
' counting the button presses).
'
' The difference between GetButtonPress and GetMousePos is that
' GetButtonPress returns the coordinates for the mouse button specified
' by the input parameter (Button), at the point in time when that button
' was last pressed (count of presses is also returned).
' GetMousePos returns the CURRENT coordinates of the mouse, at the point
' in time when GetMousePos is called (regardless of whether or not any
' button was ever pressed).
' GetMousePos is used to "poll" the mouse in real-time to obtain its
' CURRENT position.
' GetButtonPress is used to get the mouse's position corresponding to
' the last time a specific button was pressed (and how many times it
' was pressed - useful for determining if a double click occurred).
' Both routines return CURRENT status (up/down) of all buttons.
END SUB
FUNCTION GetCurDir.$
'Purpose:
'--------
' Determine the default directory on a specified drive.
'
' (New with V2.0)
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' DriveLetter$ - Letter of the drive to be checked.
' If null, then default drive is assumed.
' DriveLetter$ can be either upper or lower case.
' If DriveLetter$ is non-null, then only the first
' character in the string will be examined.
'
'Return Values:
'--------------
' If successful, string with: Fully qualified directory name.
' If unsuccessful, STRING with:
' "-1" - DriveLetter$ did not contain a letter.
' "-2" - Drive letter was invalid (not on the system).
' "-3" - Other error (DOS extended error code will
' be in OutRegs.ax).
'
'Notes:
'------
' This function calls DOS interrupt 21h, function 47h.
'
' Also see: ChangeDir, ChangeDrive, GetCurDrive$
'
' To determine success, test first character of returned string.
' If it was a "\", then function was successful, and returned string
' contains the fully qualified current directory on specified drive,
' If first character was a "-", then an error occurred; check rest of string
' to determine which error.
' If the specified drive is not ready, your program will get the
' standard "not ready" error condition. You can use an ON ERROR routine
' to trap this condition. The user can be given two alternatives: either
' RETRY (use a RESUME) or IGNORE (use a RESUME NEXT).
END FUNCTION
FUNCTION GetCurDrive.$
'Purpose:
'--------
' Determine the current drive's letter.
'
' (New with V2.0)
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' None.
'Return Values:
'--------------
' If successful, then string with: The current drive's letter.
' The trailing colon (:) is NOT
' included (length of string is 1).
'
' If unsuccessful, then string with:
' "-1" DOS returned an invalid letter.
'
'
'Notes:
'------
' This function calls DOS interrupt 21h, function 19h.
'
' GetCurDrive does not actually do I/O to the drive (the current drive
' letter is obtained from an internal DOS data structure). Thus, the
' drive need not be ready when this function is used (any you can not assume
' that the drive is ready after this function has been used).
' Also see: ChangeDir, ChangeDrive, GetCurDir$
'
END FUNCTION
FUNCTION GetFileNames.
'Purpose:
'--------
' To extraxct file names or sub-dir names from the current or specified dir,
' and place them into the passed string array.
' (New with V2.0)
' (Modified V2.3)
' - Text$ array is dynamically REDIMed to the correct size
' - TypeSrch=3 option added
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' TypeSrch: type of search:
' = 1: directory names extracted that match filespec$
' (read-only, hidden, or system dir names NOT extracted)
' = 2: file names extracted that match filespec$
' (read-only, hidden, or system file names NOT extracted)
' = 3: ALL names that match filespec$ extracted.
' The first byte of the name is prefixed with
' a string whose decimal value corresponds to the
' file/dir's attribute. See Notes for examples.
' filespec$: specification for dir or file name (wildcards allowed).
' examples: "*.*", "*.bas"; "sample??.*" "c:\mylib\*.exe"
' Text$: String array to hold all file/dir entries matching filespec$.
' This array MUST be DYNAMIC. It will be REDIMed to the
' exact size to hold all names extracted, hence it can of
' any size when this function is called. LBOUND will be 1.
' UBOUND will be the number of files/dirs extracted.
' ORIGINAL CONTENTS OF Text$ ARRAY WILL BE DISTROYED.
' If TypeSrch=3, then LEFT$(Text$(i),1) will be set to the
' dir/file's attribute and the remaining characters will be
' the actual name. You'll have to test the attribute byte
' to determine what type of file/dir it is (and remove
' the attribute byte from the name before displaying it).
' See Notes for examples.
'
'Return Values:
'--------------
' >0 ==> normal exit - number of names extracted
' -1 ==> invalid value for TypeSrch (must be 1 or 2)
' -2 ==> no files/dirs matched filespec$
' -3 ==> NOT USED
' -4 ==> NOT USED
' -5 ==> path not found (filespec$ could be invalid)
' -6 ==> other error (OutRegs.ax has DOS extended error code)
'
'
'
'
'Notes:
'------
' This function calls DOS interrupts 21h, function 4Eh, 4Fh, and 1Ah.
' GetFileNames can be used to extract file and/or dir names from the
' current dir (for subsequent display in a scrollable text window).
'
' The string array passed to this function (Text$) will hold all
' names extracted. It will be REDIMed to the correct size. It MUST
' be DYNAMIC in the calling program. NOTE: THE ORIGINAL CONTENTS OF THE
' STRING (Text$) ARRAY WILL BE DISTROYED.
' If the Text$ array is not DYNAMIC, you'll get a "duplicate definition"
' error when you compile or run a program in the QB environment
' that calls the GetFileNames function.
' An array can be made DYNAMIC by inclucing a variable name in its
' original DIM statement
' (for example: DIM Text$ (1 to x) where x has been previously defined).
' Alternatively, you can make ALL arrays dynamic by including the
' meta-command '$DYNAMIC at the beginning of your main module.
'
' If this function returns a value > 0, then Text$ contains the files
' or dirs (depending upon value of TypeSrch) that matched filespec$.
' Note that if you ask for all dirs (*.*), then two dir names you'll always
' get (except when in the root directory) are "." and ".." (i.e., the
' shorthand symbols for the current and parent directory).
' You can sort the Text$ array, and use RefrestScrollText to place
' new list into the current window.
'
' To save string space, you can REDIM the Text$ array
' as 1 TO 1 prior to calling GetFileNames. GetFileNames will expand this
' array as necessary to hold all names that match the search criteria.
' After returning from GetFileNames, ERASE the Text$ array as soon as
' you are finished with it to save space.
' Example:
' '$DYNAMIC ' make all arrays dynamic
' REDIM Text$(1 TO 1) ' minimum size to save space
' .
' .
' rc=GetFileNames(2,"*.*",Text$()) ' get all file names
' IF rc < 0 THEN ' test for errors
' .
' END IF
' .
' .
' FOR i = 1 to rc ' rc contains number of files in array
' PRINT Text$(i) ' print file names
' NEXT
' .
' ERASE Text$ ' clear the array to save space
' Use TypeSrch=3 if you want to get ALL names in the current or specified
' directory that match filespec$. In this case, each name is prefixed with
' a one-byte string whose decimal value is the file/dir's attribute.
' Attribute bits can take the following values:
' BITS DECIMAL MEANING
' .... ...1 1 Read Only
' .... ..1. 2 Hidden
' .... .1.. 4 System
' .... 1... 8 Volume Label
' ...1 .... 16 Sub-Directory
' ..1. .... 32 Archive
' .1.. .... x UNUSED
' 1... .... x UNUSED
' Attribute bits can occur in combinations. For example, a file that is
' marked as Read Only and Hidden will have a decimal attribute byte of 3.
' "Regular" files will usually have a decimal attribute byte of 0 or 32.
' "Regular" directories will usually have a decimal attribute byte of 16.
' When TypeSrch=3 is used, you must test the first byte of each file name
' to determine its type, then remove the first byte if you are going to
' display the names:
' REDIM Text$(1 to 1)
' rc=GetFileNames(3,"*.bas",Text$) ' get all names that match *.bas
' IF rc < 0 THEN
' process the error
' END
' END IF
' test the attributes
' FOR i = 1 TO rc
' att=ASC(LEFT$(Text$(i),1)) ' get attribute byte
' IF att = zz THEN .... ' process the attribute byte
' x=LEN(Text$(i) ' get length
' Text$(i)=RIGHT$(Text$(i),x-1) ' strip attribute byte
' NEXT
' z=OpenScrollWindow( ........., Text$, .........) ' open scroll window
' ERASE Text$ ' save some string space
END FUNCTION
SUB GetMousePos.
'Purpose:
'--------
' Returns the current status (up/down) of all mouse buttons
' and current position (in pixel coordinates).
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' Button%: the CURRENT status of all mouse buttons.
' [bits set as follows (shown left to right, bits 2 to 0)]:
'
' ..0 left button up
' ..1 left button down
' .0. right button up
' .1. right button down
' 0.. center button (if present) up
' 1.. center button (if present) down
'
' Horiz%: current horizontal pixel coordinate of mouse.
' Vert%: current vertical pixel coordinate of mouse.
'
'
'Notes:
'------
' This subroutine calls BIOS interrupt 33h, function 03h.
'
' Horizontal/vertical coordinates returned are in PIXELS. If screen
' positions are desired, use integer division by width/depth of
' character in pixels to get column/row.
'
' The difference between GetButtonPress and GetMousePos is that
' GetButtonPress returns the coordinates for the mouse button specified
' by the input parameter (Button), at the point in time when that button
' was last pressed (count of presses is also returned).
' GetMousePos returns the CURRENT coordinates of the mouse, at the point
' in time when GetMousePos is called (regardless of whether or not any
' button was ever pressed).
' GetMousePos is used to "poll" the mouse in real-time to obtain its
' CURRENT position.
' GetButtonPress is used to get the mouse's position corresponding to
' the last time a specific button was pressed (and how many times it
' was pressed - useful for determining if a double click occurred).
' Both routines return CURRENT status (up/down) of all buttons.
END SUB
FUNCTION GetVerNum.$
'Purpose:
'--------
' Returns version number of LangWin.
' [CTRL-A from any window will also display version number]
'
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' None.
'
'
'Return Values:
'--------------
' String with version number.
END FUNCTION
FUNCTION GrowScrollText.
'Purpose:
'--------
' This function allows you to dynamically add entries to the list of
' scrollable text in the CURRENT window. The text is appended to the
' end of the CURRENT window's scrollable text array, and the array
' is re-displayed in the CURRENT window.
' (New with V2.3)
'Routine Type:
'-------------
' Function.
'Parameters:
'-----------
' Text$ - text string to be added to end of CURRENT window's
' scrollable text array and displayed in the CURRENT
' window's scrollable text area.
'
'Return Values:
'--------------
' 0 - success
' -1 - current window is not a scrollable text window (i.e., it was
' not opened via OpenScrollText).
' -2 - no more room in scrollable text array for another entry.
' there's already MaxTextLines lines of text in the array.
' you'll either have to increase MaxTextLines, or handle
' the case where you allow the user to browse the list
' as it exists, then click a button to close the window, re-open it
' with null text, and continue filling the window's text area.
'Notes:
'------
' If the list of scrollable text in the current window does not fill the
' text area defined when the window was opened, then the text string passed
' to GrowScrollText will be be displayed at the bottom of the visible list.
' If the list of scrollable text fills the text area, then text is scrolled
' up and the new string passed to GrowScrollText is displayed at the bottom
' of the text area. Note that the list of scrollable text could be null, in
' which case the first call to GrowScrollText will create the first line of
' scrollable text in the current window (but a scrollable text window must
' have been opened, otherwise GrowScrollText will not work properly).
' GrowScrollText will operate on the current window with focus. If that
' window is not a scrollable text window, no action is taken and an error
' code (-1) is returned (i.e., even if the scrollable text array is null,
' the window MUST have been opened with OpenScrollText and NOT with
' BlankWin). If the scrollable text array for the current window is already
' full (i.e., it has MaxTextLines lines of text already defined), no action
' is taken and an error code (-2) is returned.
' GrowScrollText can be used to give the user visual feedback as a long
' running task progresses. Suppose you have a routine that searches for
' specific records in a data base, and you want to display these in a
' scrollable list for your user to browse. GrowScrollText can be used to
' show the records being dynamically added to the list as they are found.
' The following pseudo code will implement this example:
' DIM Text(1 to 1) AS STRING ' scrollable text, init as null
' Above array need only have 1 entry (initially null). It's only used by
' OpenScrollText to initialize LangWin's data structure SaveText.
' Thereafter, GrowScrollText will actually "grow" the text in SaveText.
' .
' .
' w1=OpenScrollWindow( ..... ,Text(), .....) scrollable win with null text
' ' put some buttons in the window
' .
' .
' DO WHILE AnyWinOpen ' process windows
' wn=WinEvent(action) ' wait for an action
' ' process actions in windows
' .
' .
' .
'
' ' assume that at this point you determine the need to search a
' ' database for records, and to display the results in a scrollable
' ' window (w1) where the user can browse the results.
'
' ' w1 is the number of the open window that will contain the
' ' scrollable text. at this point, the scrollable text array is null.
' x=IsWinOpen(w1,Han) ' get handle of w1 and save in Han
'
' ' search loop
' DO
' ' first, you must make sure window with text (w1) is current
' CALL NewFocusWindow(Han) ' give focus to text window
'
' rec$=GetNextMatch$(parms) ' get a record
' IF rec$="" THEN EXIT DO ' see if search is done
' ' note: GetNextMatch$ is NOT part of LangWin. it's
' ' a fictitious function used to illustrate a routine
' ' that you might call to get a record and return in text string.
' ' i assume a null value is returned when search is completed.
'
' rc=GrowScrollText(rec$) ' display rec in window
' SELECT CASE rc ' test above return code
' CASE -1 ' current window is not a scrollable text window
' ' process the error
' CASE -2 ' scrollable text array is full
' ' process the error. this might include allowing
' ' the user to browse the scrollable text and waiting
' ' for a CONTINUE button to be clicked. when this
' ' button is clicked, you could close the window,
' ' re-open it (to clear text), and continue the search.
' END SELECT
'
' ' using the time-out techniques from Section 6.22, you could
' ' also include a STOP button to interrupt the search.
' ' assume handle of STOP button is: Stop1
' aa=-999 ' set time out option
' x=WinEvent(aa) ' wait for 0.5 sec for an event
' ' loop until STOP button is clicked
' LOOP UNTIL (aa=3 AND WinParms(CurWinPtr,16)=Stop1)
'
END FUNCTION
SUB HideMouseCursor.
'Purpose:
'--------
' Hides mouse cursor before displaying anything on the screen.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' None.
'
'
'Notes:
'------
' This subroutine calls BIOS interrupt 33h, function 02h.
'
' The mouse cursor must be hidden before writing anything to the screen.
' Otherwise, any character written to the same position as the mouse
' cursor will not be displayed. See ShowMouseCursor for inverse function.
'
' LangWin sets a global flag (HaveMouse) to true if mouse exists.
' This flag should be tested before calling HideMouseCursor:
' IF HaveMouse THEN CALL HideMouseCursor
'
' Also see: ShowMouseCursor, MouseExists, and InitMouse.
END SUB
FUNCTION InitMouse.
'Purpose:
'--------
' Initialize the mouse.
'
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' NumButtons: number of buttons on the mouse
'
'
'Return Values:
'--------------
' TRUE (-1): mouse was successfully initialized
' FALSE (0): mouse was not successfully initialized
'
'
'Notes:
'------
' This function calls BIOS interrupt 33h, function 00h.
'
' Also see: MouseExists.
'
' MouseExists should be called BEFORE InitMouse to insure that
' a mouse exists. Otherwise, calling InitMouse without a mouse could
' crash the system. InitMouse must be called once to initialize the
' mouse before performing any other mouse functions.
END FUNCTION
FUNCTION IsWinOpen.
'Purpose:
'--------
' Given a window number, determine if it is open (TRUE) or closed (FALSE).
' If open, determine the window's handle.
' (New with V2.0)
'
'Routine Type:
'-------------
' Function.
'Parameters:
'-----------
' wn%: - window's number (input)
' wh% - window's handle if it's open, else -1 (output)
'Return Values:
'--------------
' TRUE - window was open
' FALSE - window was not open
'Notes:
'------
' WinNum array is scanned for match on window number.
' If match found, index in WinNum is the window's handle.
' IsWinOpen can be used to determine if a specific child window
' is open before closing the parent.
' All info for open windows are stored in data structures indexed
' by window's handle. If you know a window's number (returned by the
' corresponding "make" routine), then IsWinOpen can be used to determine
' if the window is open, and if so, its handle. The handle can be used
' as an index into the data structures to examine the window's status.
' The handle is also needed if you call NewFocusWindow to bring a new
' window into focus.
END FUNCTION
SUB LangWinInit.
'Purpose:
'--------
' Initialize LangWin's global variables.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' None.
'
'
'Notes:
'------
' Must be called once in main module before performing any of LangWin's
' routines. LangWinInit will also initialize the mouse if it exists.
' if you get a "subscript out of range" error while
' in this routine, be sure you called QB with /ah.
' then try reducing the value of MaxWindows.
' check the WIDTH command; reduce number of columns,
' and/or number of rows.
END SUB
FUNCTION MakeBox.
'Purpose:
'--------
' Draw a box in current window.
'
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' StartBoxRow%: starting row (upper left)
' StartBoxCol%: starting column (upper left)
' EndBoxRow%: ending row (bottom right)
' EndBoxCol%: ending column (bottom right)
' BoxLinType%: 1 (single line); 2 (double line)
' BoxColor%: color attribute of box (0-15)
'
'
'Return Values:
'--------------
' 0: box was successfully displayed
' 1: invalid box line type parameter (not a 1 or 2)
' 2: box would extend beyond current window.
'
'
'Notes:
'------
' Starting/ending rows and columns are relative to the current window.
' Row 0, Column 0, represent the first row/column in the window,
' regardless of where the window is located on the screen
' (first /last row and columns contain the window's border).
' Box will not be drawn if it would extend beyond boundaries of the
' current window (or if it would overlay the boundary itself).
END FUNCTION
FUNCTION MakeCheckBox.
'Purpose:
'--------
' Open/display a check box in the current window.
' Handle of check box will be returned.
'
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' Row%: row where Check Box will be placed
' Col%: starting column
' Foreg%: foreground color attribute (0-15)
' Backg%: background color attribute (0-15)
' Default%: initial default state of Check Box
' [MUST either be CheckOn (box is selected/down),
' or CheckOff (box is not selected/up. CheckOn and
' CheckOff are global variables initialized by LangWinInit]
'
'
'Return Values:
'--------------
' >0: check box successfully created (positive value is handle number)
' -1: check box would extend beyond current window
' -3: length not big enough for default box text
' [should not see this error since box text is pre-defined]
' -4: not enough storage for another button
' [must increase the value of global parameter MaxButtons]
' -5: foreground color attribute invalid (must be 0-15)
' -6: background color attribute invalid (must be 0-15)
' -7: shadow switch value invalid
' [should not see this error since shadow switch is pre-defined]
' -8: default box state not valid
' [it MUST be either CheckOn or CheckOff]
'
'
'Notes:
'------
' MakeCheckBox calls MakePushButton to actually display the Check Box
' (since Check Boxes are really just another type of button).
'
' Row and column are relative to the current window.
' Row 0, Column 0, represent the first row/column in the window,
' regardless of where the window is located on the screen
' (first /last row and columns contain the window's border).
' Check Box will not be opened if it would extend beyond boundaries
' of the current window (or if it would overlay the boundary itself).
'
' The handle value returned must be saved.
' After calling WinEvent to wait for an event in the current window,
' you must determine which event occurred (see WinEvent for details).
' Depending upon the event, you may need to determine the state of
' Check Boxes in the window. Use the saved handles of all appropriate
' Check Boxes to index the ButtonsData array which contains the status
' of all buttons. The 7th entry for each button contains a switch
' that describes whether or not it has a shadow (1=yes; 0=no). For
' Check Boxes, the shadow determines if it was selected
' (1=shadow - box NOT selected; 0=no shadow - box was selected).
'
' If Han represents the handle value of a specific Check Box, the
' following code illustrates how to determine if the box was selected:
'
' IF ButtonsData(Han, 7) = 1 THEN ... the Check Box was NOT selected.
' IF ButtonsData(Han, 7) = 0 THEN ... the Check Box was selected.
END FUNCTION
FUNCTION MakeHorizLine.
'Purpose:
'--------
' Draw a horizontal line across current window.
'
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' Row%: row where line will be placed
' LineType%: type of line (1=single; 2=double)
'
'
'Return Values:
'--------------
' 0: success
' 1: invalid line type parameter (must be 1 or 2)
' 2: line would extend beyond window boundary or
' fall on same row as border.
'
'
'Notes:
'------
' Row where line is placed is relative to the current window.
' Row 0 represent the first row in the window,
' regardless of where the window is located on the screen
' (first /last row contains the window's border).
' Line will not be drawn if it would extend beyond boundaries of the
' current window (or if it would overlay the top/bottom boundary itself).
END FUNCTION
FUNCTION MakeInputField.
'Purpose:
'--------
' Open/display an Input Field in the current window
' [to be used for data entry/modification]
' [can also be used for entering a password - see length field parameter]
'
'Routine Type.
'-------------
' Function.
'
'
'Parameters:
'-----------
' Row%: row where input field will be placed
' Col%: starting column
' Length%: length of input field area
' (if a negative value is used for length, input field will
' be used for password entry - only * will be displayed)
' FieldText$: default text (null if none)
' Foreg%: foreground color attribute (0-15)
' Backg%: background color attribute (0-15)
'
'
'Return Values:
'--------------
' >0: field successfully created (positive value is handle number)
' -1: field would extend beyond current window
' -4: not enough storage for another field
' [must increase value of global parameter MaxButtons]
' -5: foreground color attribute invalid (0-15)
' -6: background color attribute invalid (0-15)
'
'
'Notes:
'------
' Row and column are relative to the current window.
' Row 0, Column 0, represent the first row/column in the window,
' regardless of where the window is located on the screen
' (first /last row and column contain the window's border).
' Input Field will not be opened if it would extend beyond boundaries
' of the current window (or if it would overlay the boundary itself).
'
' The handle value returned must be saved.
' After calling WinEvent to wait for an event in the current window,
' you must determine which event occurred (see WinEvent for details).
' Depending upon the event, you may need to access/modify the contents
' of Input Fields in the window. Use the saved handles of all appropriate
' Input Fields to index the ButtonsText array which contains the
' contents of all fields. You can examine these contents to see their
' current values. If the contents contains numeric data, use VAL to
' extract the numeric value. Then use STR$ if the contents are to be
' updated with new numeric data (the contents of ButtonsText must always
' be STRING). Once the contents of ButtonsText have been modified,
' use the ReShowInputField subroutine to re-display the new contents
' in the current window.
'
' If Han is the handle of an Input Field (returned by MakeInputField),
' the following code adds one to the Input Field and re-displays it:
'
' value=VAL(ButtonsText(Han))+1 ' get value and increment by 1
' ButtonsText(Han)=STR$(value) ' update field's contents
' CALL ReShowInputField(Han) ' re-display input field
' By using a negative value for length, the input field can be used for
' password entry. In this case, regardless of what is entered, only *
' will be displayed. The actual text entered (i.e., the password) will
' be stored in ButtonsText(Han) - just as for any other input field.
' An alternative technique would be to use the same values for
' foreground and background colors. In this case, nothing will be visible
' when text is entered into the field.
END FUNCTION
FUNCTION MakePushButton.
'Purpose:
'--------
' Open/display a Push Button in the current window.
'
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' Row%: row where button will be placed
' Col%: starting column
' Length%: length of button area
' ButtonText$: text contents of button
' Foreg%: foreground color attribute (0-15)
' Backg%: background color attribute (0-15)
' Shadow%: switch: 0=no shadow; 1=shadow
'
'
'Return Values:
'--------------
' >0: button successfully created (positive value is handle number)
' -1: button would extend beyond current window
' -3: length not big enough for all of ButtonText$
' -4: not enough storage for another button
' [must increase value of global parameter MaxButtons]
' -5: foreground color attribute invalid (must be 0-15)
' -6: background color attribute invalid (must be 0-15)
' -7: shadow switch value invalid (must be 0 or 1)
'
'
'Notes:
'------
' Row and column are relative to the current window.
' Row 0, Column 0, represent the first row/column in the window,
' regardless of where the window is located on the screen
' (first /last row and column contain the window's border).
' Push Button will not be opened if it would extend beyond boundaries
' of the current window (on the border is ok - that's how a menu bar
' at top of window can be created).
'
' The handle value returned must be saved.
' After calling WinEvent to wait for an event in the current window,
' you must determine which event occurred (see WinEvent for details).
' If the event was a button click, then WinEvent will return a 3, and
' you will need to determine exactly which button was selected. Compare
' the handle of the button that was clicked to all saved button handles.
' The action taken for each particular button handle is user defined
' based upon the meaning of the button.
'
' If WinEvent returns a value of 3, then WinParms(CurWinPtr,16)
' contains the handle of the push button that caused the click (see
' WinEvent for additional details). The following code shows a technique
' for determining which button was clicked:
'
' Han=WinParms(CurWinPtr,16) ' handle of button that was clicked
' SELECT CASE Han
' CASE b1
' ' action for button whose saved handle is b1
' CASE b2
' ' action for button whose saved handle is b2
' .
' .
' .
' END SELECT
END FUNCTION
FUNCTION MakeVertLine.
'Purpose:
'--------
' Draw a vertical line down current window.
'
'
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' Col%: column where line will be placed
' LineType%: type of line (1=single; 2=double)
'
'
'Return Values:
'--------------
' 0: success
' 1: invalid line type parameter (must be 1 or 2)
' 2: line would extend beyond window boundary
' or fall on same column as border.
'
'
'Notes:
'------
' Column where line is placed is relative to the current window.
' Column 0 represent the first column in the window,
' regardless of where the window is located on the screen
' (first /last column contains the window's border).
' Line will not be drawn if it would extend beyond boundaries of the
' current window (or if it would overlay the side boundaries).
END FUNCTION
FUNCTION MouseExists.
'Purpose:
'--------
' Determines if the mouse driver has been installed.
'
'
'Routine Type:
'-------------
' Function:
'
'
'Parameters:
'-----------
' None.
'
'
'Return Values:
'--------------
' TRUE (-1): mouse driver has been installed
' FALSE (0): mouse driver was not installed
'
'
'Notes:
'------
' This routine does NOT install the mouse driver, it only checks
' to see if it exists.
'
' It first looks in the interrupt vector table (segment 0) which has
' 4 bytes for each interrupt routine. The mouse interrupt (33h) vector
' begins at decimal 204 (33h=51d; 51d * 4 bytes/entry = 204).
'
' If the 4 bytes at 204-207 are zero, the mouse driver not installed.
' Else, the contents of the address specified by the 4 bytes at 204-207
' are compared to the value 207 (i.e., an IRET instruction). If there is
' a match, mouse driver not installed. Otherwise, mouse driver assumed
' to be installed.
'
' This routine is required for computers running DOS V2 or earlier.
' They leave the mouse interrupt (&h33) undefined if no mouse exists,
' and calling the mouse interrupt would crash the system.
'
' Before using mouse functions, first call MouseExists to
' see if the driver has been installed. If it has, then call InitMouse
' to initialize the mouse driver. Once the driver has been successfully
' initialized, you can call other mouse functions.
END FUNCTION
SUB NewFocusWindow.
'Purpose:
'--------
' Change the focus to a new window.
' (New with V2.0)
'Routine Type:
'-------------
' Subroutine.
'Parameters:
'-----------
' NewWinHan: handle of window to be given focus.
'
'
'Notes:
'------
' On entry, CurWinPtr points to current window's handle.
' This window is top one in WinStack (entry with highest index).
' On exit, CurWinPtr will be set to NewWinHan.
' NewWinHan will be removed from WinStack (wherever it is),
' placed on top in WinStack (entry with highest index), and
' remaining handles pushed down.
' WARNING: if the input parameter (NewWinHan) is not a valid handle
' (i.e., NewFocusWindow scans WinStack for the handles of all open windows),
' then an error message is displayed (with the invalid handle's value),
' and the user's program is terminated. Thus, you should be very careful
' when calling NewFocusWindow to insure that you have a valid handle
' associated with an open window. See IsWinOpen which can be used to extract
' the handle of an open window given its window number.
'
' Typical use of NewFocusWindow:
' EXIT button in main window was clicked (so main window has focus).
' Main window could have a child open. Before main window is closed,
' you need to close the child window (if it's open). Assume window number
' of child is saved in variable called ChildNum.
' IF IsWinOpen(ChildNum, han) THEN ' get handle of child
' zz = CurWinPtr ' save handle of main window (it's current)
' CALL NewFocusWindow(han) ' make child win current
' xx = CloseWindow ' close it
' CALL NewFocusWindow(zz) ' make main win current
' END IF
' xx = CloseWindow ' close main
END SUB
FUNCTION OpenScrollWindow.
'Purpose:
'--------
' Open/display window with a scrollable text area.
' New window will be given focus.
'
'
'Routine Type:
'-------------
' Function.
'
'
'V2.0 Changes:
'-------------
' Negative value for WinColor% will make window unmovable.
' New CloseIcon% parameter required.
' New ModeSw% parameter required.
' Negative value for ModeSw% will make window shadowless.
' Return values changed:
' Negative value returned if window not opened successfully.
' Window's number (>0) returned if window is opened successfully.
' 0 is not a valid return code.
' -11 is a new return code.
' -12 is a new return code.
'V2.3 Changes:
'-------------
' In previous versions of LangWin, if OpenScrollWindow was called with
' UBOUND(Text$) > the global variable MaxTextLines, a run-time error would
' immediately terminate your program.
' As of V2.3, if UBOUND(Text$) > MaxTextLines,
' the scrollable text window will be opened, but only lines 1
' through MaxTextLines of the Text$ array will be scrollable. To let you
' know that all of the Text$ array is not available in the scroll window,
' the MaxTextLine entry will appear as: (Incomplete List)
' The original Text$ array will not be altered; Text$(MaxTextLine) remains
' unchanged. The string "(Incomplete List)" only appears in the window's
' scrollable list.
'Parameters:
'-----------
' StartRow%: starting row (upper left)
' StartCol%: starting column (upper left)
' EndRow%: ending row (bottom right)
' EndCol%: ending column (bottom right)
' WinColor%: color attribute of window (0-15)
' (NEGATIVE value will make window unmovable)
' BorderColor%: color attribute of border (0-15)
' (NEGATIVE value will prevent window from being resized)
' BorderType%: 1=single line; 2=double line
' [if BorderType < 0 (i.e., -1 or -2), then no scroll
' bar or arrows will be displayed (even if text too big for
' win). use this option if you know that the number of lines
' of scrollable text is smaller than the lines available
' in the text window, AND you don't want scroll bar & arrows.
' if BorderType > 0, and number of
' lines of scrollable text is smaller than the window,
' then the scroll bar will automatically be omitted,
' but the scroll arrows will still be displayed.]
' TextColor%: color attribute for scrollable text in the window (0-15)
' (also used for close icon, scroll bar,and slider
' if present)
' Text$: array with text to be scrolled. will be placed into
' a vacant slot in SaveText array.
' Text$ MUST have lbound of 1 and NOT 0
' (see above comments about changes in V2.3)
' StartTextRow%: starting row of text area (relative to window)
' StartTextCol%: starting column of text area (relative to window)
' EndTextRow%: ending row of text area (relative to window)
' EndTextCol%: ending column of text area (relative to window)
' CloseIcon%: 1=display a close icon; 0=no close icon
' [regardless of whether a close icon is displayed, the ESC
' key will always generate a close action]
' ModeSw%: Mode of window (effects how/if/when WinEvent returns
' control after an action has taken place)
' (NEGATIVE value for mode will generate a shadowless window):
' 1 = modeless window (normal). if modeless window has
' focus, user can click on any other visible window
' and it will be given focus by WinEvent. WinEvent will
' continue to process the new window until an action
' is taken in the current window.
' 2 = modal window. if modal window has focus, any attempt
' to click on another window will be ignored by WinEvent.
' this type of window can be used to display a message,
' and force user to close the window before continuing
' (e.g., for error messages).
' 3 = if this type window has focus, clicking on another
' window, or even the wallpaper, will cause WinEvent to
' return a close action (1). This can be used for menu
' windows that should be closed if user clicks somewhere
' else on the screen.
' 4 = not valid for OpenScrollWindow (see BlankWin)
'
'
'Values Returned:
'----------------
' >0: window opened successfully (window's number returned)
' -1: not enough storage for another new window.
' [must increase the global parameter MaxWindows]
' -2: not enough room for window's rows (+1 for shadow) on screen
' -3: not enough room for window's columns (+2 for shadow) on screen
' -4: window's color attribute out of range (must be 0-15)
' -5: window's border color attribute out of range (must be 0-15)
' -6: invalid value for BorderType (must be 1, 2, -1, or -2)
' -7: text color attribute out of range (must be 0-15)
' -8: window not long enough (must be >=3)
' -9: window not wide enough (must be >=3)
'-10: defined text area will not fit into window
'-11: no room in SaveText array for another block of text
' (increase value of MaxTextWins).
'-12: invalid value for window mode (ModeSw) - must be 1 to 4
'
'Notes:
'------
' Internally, OpenScrollWindow calls BlankWin to open an empty window.
'
' You MUST check to see if window opened successfully (return code>0)
' before calling any other LangWin functions or routines.
' Otherwise, you will either get errors (such as Illegal Function Call,
' Subscript Out of Range, etc.) or process the previously opened
' window by mistake.
' OpenScrollWindow calls BlankWin which sets the global
' variable AnyWinOpen to TRUE.
' this can be used to control a DO/LOOP that executes WinEvent
' as long as there is an open window on the screen. However, if an
' information only window is open, then you must use another criteria to
' end the DO/LOOP because the info only window will always be open.
' In this case, termination should occur when a close action
' occurs in the main window.
' The Text$ array passed to OpenScrollWindow contains lines of text to be
' displayed in a scrollable window. LBOUND(Text$) MUST be 1; otherwise
' a run-time error will terminate your program when OpenScrollWindow
' is called.
' If your array of scrollable text is generated dynamically at run time and
' its length could exceed MaxTextLines, then you MUST detect this condition
' and design your program to handle it. OpenScrollWindow will only display
' the first MaxTextLines in the string array (Text$) passed. The
' MaxTextLines entry in the scrollable list
' will be displayed as: (Incomplete List)
' So, your user will know that the complete list is not visible.
' However, your program should detect this condition and give the user
' the opportunity to see the missing entries.
' To see if this condition occured, merely compare UBOUND(Text$)
' to MaxTextLines. If UBOUND(Text$) > MaxTextLines, then part of the
' Text$ array will not be visible in the scrollable text window.
' In that case, you could offer the user an option to see more text,
' loop, delete the first MaxTextLines from the Text$ array, and
' open a new scrollable text window with the remaining lines.
' You'd continue this process until the user had the opportunity to
' see all of the original Text$ array. Another (easier) option is to
' give the user the ability to set MaxTextLines at run-time by initializing
' MaxTextLines from a parameter file. Of course, this opens the door
' for abuse: the user could pick a value so large that the program
' runs out of memory. I'll leave the actual solution to you!
' Null lines in the list of scrollable text cannot be given focus. If you
' scroll a list with null lines, the focus will disappear when you get to a
' null line. This can be confusing to the end user. Unless it's absolutely
' necessary, you should not include null lines in the Text$ array passed to
' OpenScrollWindow. OpenScrollWindow will not display any null lines at the
' end of the Text$ array. Null lines within the Text$ array will appear in
' scrollable list, but as previously mentioned, the focus will disappear
' when the user scrolls the highlight to one of these lines.
END FUNCTION
SUB RefreshScrollText.
'Purpose:
'--------
' Redisplay new scrollable text in the current window with focus
' (the entire set of scrollable text is replaced).
' New with V2.0
' -------------
' Modified in V2.3
' ----------------
' In previous versions of LangWin, if RefreshScrollText was called with
' UBOUND(Text$) > the global variable MaxTextLines, a run-time error would
' immediately terminate your program.
' As of V2.3, if UBOUND(Text$) > MaxTextLines,
' the scrollable text window will be redisplayed, but only lines 1
' through MaxTextLines of the Text$ array will be scrollable. To let you
' know that all of the Text$ array is not available in the scroll window,
' the MaxTextLine entry will appear as: (Incomplete List)
' The original Text$ array will not be altered; Text$(MaxTextLine) remains
' unchanged. The string "(Incomplete List)" only appears in the window's
' scrollable list.
'
'Routine Type:
'-------------
' Subroutine.
'Parameters:
'-----------
' Text$ - string array with new scrollable text to be displayed in the
' current window with focus.
' Text$ MUST have LBOUND of 1 and NOT 0
'Notes:
'------
' The Text$ array passed to RefreshScrollText contains lines of text to be
' redisplayed in the current scrollable window. LBOUND(Text$) MUST be 1.
' If this conditions is not met (i.e., LBOUND(Text$) <> 1, then
' a run-time error will occur when RefreshScrollText is called.
' If RefreshScrollText is called and the current window with focus does not
' have scrollable text, then a run-time error will occur.
' Null lines in the list of scrollable text cannot be given focus. If you
' scroll a list with null lines, the focus will disappear when you get to a
' null line. This can be confusing to the end user. Unless it's absolutely
' necessary, you should not include null lines in the Text$ array passed to
' RefreshScrollText. Null lines at the end of Text$ are eliminated.
' RefreshScrollText works only on the current window. if you need to refresh
' text and are not sure if the window to be refreshed is current, then the
' following code can be used (assume you know that the variable win1
' contains the number of the window which is to be refreshed):
' IF IsWinOpen(win1,han) THEN ' if win1 is open, return its handle
' CALL NewFocusWindow(han) ' make win1 current
' CALL RefreshScrollText(Text$) ' update the window
' END IF
END SUB
SUB ReShowInputField.
'Purpose:
'--------
' Re-display contents of an Input Field after it has been changed.
' Assumes that window containing the input field has focus.
' If it does not, call NewFocusWindow first to give focus to appropriate
' window.
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' Handle%: handle of Input Field to be displayed
'
'
'Notes:
'------
' ButtonsText(Han) contains the text from the Input Field whose handle
' is Han. If your program modifies this text, you must re-display it
' in the current window (if you want the current window to reflect the
' change made to ButtonsText(Han)). Call ReShowInputField(Han) to
' accomplish this function.
'
' See MakeInputField for additional details on creating an Input Field
' and the handle assigned to each field.
END SUB
SUB ReShowPage.
'Purpose:
'--------
' Re-display all scrollable text lines that are visible in the current
' window. Useful if you have made changes to several lines of scrollable
' text and need to update the window. If window with scrollable text to
' be re-displayed is not current, first call NewFocusWindow to give
' focus to the appropriate window.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'V2.0 Changes:
'-------------
' text array no longer needed as a parameter. text for all windows is
' saved in SaveText array when window is opened.
'
'Parameters:
'-----------
' None. (V2.0 change)
'
'
'Notes:
'------
' You might define a button that causes action to be taken on selected
' lines of scrollable text (i.e., update all files whose names have been
' previously "selected" by double-clicking on them). After taking the
' necessary action, your code would toggle the "select" character in
' every line of text from on to off (i.e., change an "X" to a blank).
' After this has been done, the scrollable text that is visible in the
' current window must be re-displayed to reflect these changes. Use the
' ReShowPage routine to accomplish this function.
'
' See ReShowText for details on re-displaying single lines of scrollable
' text in the current window (i.e., after a text line has been double-
' clicked and you change the contents of that text).
' See WinEvent for details on responding to events from the current
' window.
'
' In general, you should not change the DIM of the scrollable text array
' while its window is open. Nor should you use ReShowPage to re-display
' a text array other than the one that was defined when the window was
' originally opened.
END SUB
SUB ReShowText.
'Purpose:
'--------
' Re-display the currently highlighted scrollable text entry
' after it has been changed (one line is re-displayed).
' Assumes that window containing the scrollable text has focus.
' If it does not, call NewFocusWindow first to give focus to appropriate
' window.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'V2.0 Changes:
'-------------
' text array no longer needed as a parameter. text for all windows is
' saved in SaveText array when window is opened.
'
'
'Parameters:
'-----------
' none. (v2.0 change)
'
'
'Notes:
'------
' If the currently highlighted line of scrollable text is changed by your
' program in response to some event or process, then use ReShowText to
' re-display the modified line of text in the current window. For
' example, if you detect, via WinEvent, a double-click on a line of
' scrollable text, and you want to mark that line as "selected" before
' going back and waiting on another event, you could change a specific
' character in the selected text line (i.e., change a blank to an X) and
' re-display it with ReShowText. In this example, WinEvent would return a
' value of 2 (signifying that a line of scrollable text was double-
' clicked) and WinParms(CurWinPtr,15) would contain the index, in your
' array of scrollable text, that was selected; that is:
' Text$(WinParms(CurWinPtr,15)) was double-clicked. After making the
' appropriate changes to the selected line in the Text$ array,
' CALL ReShowText(Test$()) to re-display it in the visible window.
'
' You might also have a button whose function is to take action on all
' selected lines of scrollable text. After detecting that this button was
' clicked, via WinEvent, and taking the necessary action, you would
' change all the characters that had been set to denote selection
' (say an X) back to a character that denotes no selection (say a blank)
' and then re-display all lines of scrollable text that are currently
' visible in the window (see ReShowPage).
'
' See WinEvent for details on responding to events from the current
' window.
'
' In general, you should not change the DIM of the scrollable text array
' while its window is open. Nor should you use ReShowPage to re-display
' a text array other than the one that was defined when the window was
' originally opened.
END SUB
SUB SetColor.
'Purpose:
'--------
' Set foreground/background color attributes. When using LangWin,
' SetColor MUST be used instead of BASIC's COLOR command.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' Foreg%: foreground color attribute (0-15)
' Backg%: background color attribute (0-15)
'
'
'Notes:
'------
' LangWin uses BIOS interrupt 10h, function 10h, sub-function 03h to
' disable blinking colors. This allows 16 attribute numbers for window
' (background) colors (rather than just 8). However, with blinking
' disabled, foreground/background attribute numbers MUST be translated
' before calling BASIC's COLOR command. SetColor does this translation.
' If BASIC's COLOR command is called without this translation, you will
' get unexpected colors.
'
' If you need to change colors in any program that uses LangWin's
' routines, use SetColor just as you would use BASIC's COLOR command.
END SUB
SUB SetMousePos.
'Purpose:
'--------
' Sets the current position of the mouse pointer (in pixel coordinates).
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' Horiz%: new horizontal pixel coordinate of mouse.
' Vert%: new vertical pixel coordinate of mouse.
'
'
'Notes:
'------
' This subroutine calls BIOS interrupt 33h, function 04h.
'
' Horizontal/vertical coordinates set are in PIXELS. If you know the
' new column/row position, use integer multiplication by width/depth of
' character in pixels to get pixel coordinates.
'
' Also see: GetMousePos and GetButtonPress
END SUB
SUB SetXLimit.
'Purpose:
'--------
' Set horizontal limits for mouse pointer.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' MinX%: minimum horizontal coordinate (in pixels)
' MaxX%: maximum horizontal coordinate (in pixels)
'
'
'Notes:
'------
' Use this routine to restrain mouse pointer to a specific
' horizontal area. Current mouse pointer will automatically
' be moved into the allowable area if necessary.
'
' BIOS interrupt 33h, function 07h is used.
'
' Also see: SetYLimit
END SUB
SUB SetYLimit.
'Purpose:
'--------
' Set vertical limits for mouse pointer.
'
'
'Routine Type:
' Subroutine.
'
'
'Parameters:
'-----------
' MinY%: minimum vertical coordinate (in pixels)
' MaxY%: maximum vertical coordinate (in pixels)
'
'
'Notes:
'------
' Use this routine to restrain mouse pointer to a specific
' vertical area. Current mouse pointer will automatically
' be moved into the allowable area if necessary.
'
' BIOS interrupt 33h, function 08h is used.
'
' Also see: SetXLimit
END SUB
SUB ShowMouseCursor.
'Purpose:
'--------
' Displays the mouse cursor.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' None.
'
'
'Notes:
'------
' This subroutine calls BIOS interrupt 33h, function 01h.
'
' The mouse cursor must be hidden before writing anything to the screen.
' Otherwise, any character written to the same position as the mouse
' cursor will not be displayed. HideMouseCursor accomplishes this task.
' ShowMouseCursor is then used to re-display the mouse cursor.
'
' LangWin sets a global flag (HaveMouse) to true if mouse exists.
' This flag should be tested before calling ShowMouseCursor:
' IF HaveMouse THEN CALL ShowMouseCursor
'
' Also see: HideMouseCursor, MouseExists, and InitMouse.
END SUB
FUNCTION ShowTitle.
'Purpose:
'--------
' Display a title bar, centered at the top of the current window.
' If appropriate window to contain title does not have focus,
' call NewFocusWindow to make it current.
'
' V2.1 Changes: return code 1 eliminated, return code 4 added.
'Routine Type:
'-------------
' Function.
'
'
'Parameters:
'-----------
' Title$: string with title
' Foreg%: foreground color attribute (0-15)
' Backg%: background color attribute (0-15)
'
'
'Return Values:
'--------------
' 0: title successfully displayed
' 2: background color attribute invalid (must be 0-15)
' 3: foreground color attribute invalid (must be 0-15)
' 4: not enough storage for another title (new with V2.1)
' [must increase value of global parameter MaxButtons]
'Notes:
'------
' With LangWin V2.1, return code 1 is no longer used (this return
' code used to indicate that the title was too wide for the window).
' If the title is too wide, it will be truncated, and code 0 returned.
' Also with LangWin v2.1, resizing has been implemented. Title data is
' saved in data structures so it can be re-displayed when a window is
' resized. Code 4 is returned if there is no more room in the data
' structures (i.e., ButtonsText and ButtonsData). In this case, you'll
' need to increase the value of the global variable MaxButtons.
END FUNCTION
FUNCTION ShowWinText.
'Purpose:
'--------
' Display a line of static (non-scrollable) text in current window.
' If appropriate window to contain text is not current, first call
' NewFocusWindow to make it current.
'
'Routine Type:
'-------------
' Function:
'
'
'Parameters:
'-----------
' Row%: row where text will be placed
' Col%: starting column
' Foreg%: foreground color attribute (0-15)
' Text$ string with static text to be displayed
'
'
'Return Values:
'--------------
' 0: text successfully displayed
' -1: text extends beyond current window
' -3: foreground color not valid (must be 0-15)
' -4: not enough storage for to save this text (new with V2.1)
' [must increase value of global parameter MaxButtons]
'
'
'Notes:
'------
' Row and column are relative to the current window.
' Row 0, Column 0, represent the first row/column in the window,
' regardless of where the window is located on the screen
' (first /last row and column contain the window's border).
' Window text will not be displayed if it would extend beyond boundaries
' of the current window (on the border is ok).
' To display numeric values in a window, use STR$(number) in the Text$
' parameter. For example:
' CALL ShowWinText(2, 3, 15, "Number of Wigits: " + STR$(NumWig))
' With LangWin v2.1, resizing has been implemented. Static text data is
' saved in data structures so it can be re-displayed when a window is
' resized. Code -4 is returned if there is no more room in the data
' structures (i.e., ButtonsText and ButtonsData). In this case, you'll
' need to increase the value of the global variable MaxButtons.
' Static text created by ShowWinText can be modified/changed by calling
' ShowWinText again, with the same row/column but new text. This is
' acceptable when only a few updates are needed. However, if the static text
' is modified based upon some user action (like a button click), then there
' is no way to determine the number of times the text will be modified. Each
' time ShowWinText is called, the text is saved in LangWin's data structures
' (ButtonsText and ButtonsData). These structures have a finite dimension
' (MaxButtons). Each call to ShowWinText requires a new entry in the data
' structures. Thus, repeated calls to modify text can exhaust all available
' slots. In this case, the result would be that subsequent calls to create
' objects (either new buttons, input fields, check boxes, or static text)
' will fail and the object will not appear. Closing a window will free all
' slots occupied by its objects. Increasing the value of MaxButtons will make
' more slots available. However, neither of these is a good solution. A
' better solution is to re-use the same slot whenever existing static text is
' modified. All that is needed is to first determine the slot number (handle)
' of the static text, then to update the contents of the existing slot and
' re -display it.
' Since ShowWinText returns an error code and not the handle of the slot used
' to store text, you'll need to find and save the handle number in order to
' later modify its contents. The best way to do this is to use ShowWinText to
' temporarily place some specific text into the data structures, then
' manually scan the data structure until you find the specific text. The
' following code will accomplish these tasks:
' x = ShowWinText(r, c, colr, "SOME UNIQUE TEXT")
' ' the above will place "SOME UNIQUE TEXT" at row=r, column=c in the
' ' current window using color=colr. the string "SOME UNIQUE TEXT"
' ' will also be placed into the next available slot in ButtonsText
' IF x < 0 THEN
' ' if error condition, process it
' END
' END IF
'
' thandle = -999 ' set a default value for the handle
'
' ' now search ButtonsText for the specific text string
' FOR i = 1 TO MaxButtons
' IF ButtonsText(i) = "SOME UNIQUE TEXT" THEN
' thandle = i ' save handle number
' EXIT FOR ' quit serach
' END IF
' NEXT
'
' ' just in case the "impossible" happens
' IF thandle = -999 THEN
' ' process the error
' END
' END IF
' At this point, the variable: thandle points to the slot in LangWin's data
' structures that contains the temporary static text. The screen itself
' displays the temporary text at the designated row/column. Now, you must
' replace the temporary text with the initial value of the static text (using
' the same slot in the data structures) and display this text on the screen.
' The following code will accomplish these tasks:
' a$ = "initial contents of static text field"
' ButtonsText(thandle) = a$ ' update text in data structure
' CALL ReShowInputField(thandle) ' redisplay text on screen
' ButtonsData(thandle, 4) = LEN(a$)' update length of text area
' You might ask: why is the length of the text in LangWin's data structure
' updated AFTER the text is displayed? Glad you asked that question!
' ReShowInputField (which is really meant to redisplay the contents of an
' input field after it has been modified, but will also redisplay static
' text) first clears the entire contents of the area, then displays the
' new text. The length of the area to clear is obtained from the data
' structure. So, if the length of the new text was smaller than the previous
' text, and the new (smaller) length was first placed into the data structure,
' then only the smaller area would cleared prior to displaying the new text.
' Any characters from the previous (longer) text beyond the end of the new
' (smaller) text would remain on the screen. By calling ReShowInputField
' before the length is updated, the length of the area cleared will
' correspond to the the current text.
' Later in your program, when you determine that new static text must be
' placed into the window at the same position as the old text, the following
' code can be used:
' a$ = "new contents of static text field"
' ButtonsText(thandle) = a$ ' update text in data structure
' CALL ReShowInputField(thandle) ' redisplay text on screen
' ButtonsData(thandle, 4) = LEN(a$)' update length of text area
' These techniques can be used with any number of static text entries. You'll
' just need to save each handle in a unique variable name.
END FUNCTION
SUB WaitTicks.
'Purpose:
'--------
' A timed delay similar to SLEEP but more granular.
'
'
'Routine Type:
'-------------
' Subroutine.
'
'
'Parameters:
'-----------
' Ticks%: number of timer ticks to "sleep".
' this parameter MUST be between 0 and 255.
' each "tick" is approximately (1/18.2) seconds.
'
'Notes:
'------
' Address 0040:006Ch is a 32-bit timer that is incremented approximately
' 18.2 times per second. This routine examines the low byte of this
' timer, and waits for the specified number of increments (ticks)
' to elapse before returning. While any value up to 255 is valid for the
' input parameter (i.e., the maximum value of a byte), in practice, you
' should only need input values from 0 - 18.
' For values greater than 18 (i.e., to wait more than one second),
' use the SLEEP function instead (whose granularity is in seconds).
'
' Use WaitTicks if you need to delay for some period less than a second.
' It is also useful if you need your code to wait a consistent amount of
' time regardless of what speed/model CPU it runs on. A FOR/NEXT delay
' loop will not produce consistent delays across different speed CPUs.
END SUB
FUNCTION WinEvent.
'Purpose:
'--------
' Wait for an event to occur in the current window.
' This routine should be called AFTER opening a window and
' any associated buttons, text, input fields, check boxes, etc.
' This routine will automatically handle mouse clicks on other underlying
' visible windows. If appropriate (see ModeSw in BlankWindow and
' OpenScrollWindow), the underlying window clicked will be given focus.
' When control is returned from WinEvent, its return code will be the
' current window's number. In addition, WinEvent's action parameter
' will be set to one of the following values:
' 1) close was selected; 2) scrollable text entry selected;
' or 3) push button selected. user also can define global hot keys and
' corresponding action codes returned when key is hit.
'
' If an "information only" window has been opened (i.e., one for which
' there are no events that can occur), then WinEvent need not be called.
' The information only window, however, should be closed when it is no
' longer needed.
'
'Routine Type:
'-------------
' Function.
'
'V2.0 Changes:
'-------------
' string array with scrollable text no longer needed as parameter.
' parameter is an action code for event in the window (see below).
' value of WinEvent returned is either -1 (error occurred) or
' the window's number that is current (i.e., that generated the action).
' WinEvent no longer locks the mouse on the current window.
' User can select other visible windows.
'V2.3 Changes:
'-------------
' "Time Out" feature added. If the action% parameter passed is -999, then
' WinEvent will return control to the calling program after 0.5 seconds if
' no events are detected (see Notes for more details).
'Parameters:
'-----------
' action%: a return code representing the action that occurred in the
' current win (if action% is set to -999 upon entry, the "time
' out" feature will be enabled).
' 1 => close event (ESC key, close button double clicked,
' or Mode 2 window was current and user clicked on
' some other window or wallpaper).
' 2 => scrollable text selected (double click in scrollable text,
' or ENTER hit while a specific line of scrollable text had
' FOCUS and no other buttons had FOCUS).
' SaveText(i,j) is text selected; where
' i=WinParms(CurWinPtr,18)
' j=WinParms(CurWinPtr,15)
' 3 => button selected (double click on push button or ENTER hit
' while a specific button had FOCUS).
' handle of button = WinParms(CurWinPtr,16)
' ButtonsText(handle) contains the button's text
' (or null if button is not active)
' ButtonsData(handle,i) contains info on button
' >=4 => user defined hot keys can be associated with an action
' code that is returned whenever a hot key is hit.
' -999 => if action% is set to -999 upon entry to WinEvent, then the
' "time out" feature will be enabled. this feature will cause
' control to be returned to the calling program if no events
' are detected within 0.5 seconds. see Notesd for additional
' details.
'Values Returned:
'----------------
' -1: error occurred
' >0: window number with FOCUS when event occurred.
'
'Notes:
'------
'
' WinEvent is the workhorse of LangWin. After opening a window(s) and
' defining buttons, scrollable text, check boxes, input fields, etc., you
' must call WinEvent to wait for an event/action to occur.
' WinEvent returns two important values: the WinEvent function returns
' the window's number that had FOCUS when the event occurred. The action
' parameter defines what event took place in the current window.
' WinEvent processes all GUI functions in all visible windows. Some events
' are handled entirely within WinEvent (i.e., mouse movements, scrolling,
' changing FOCUS among windows or items in the window, clicking/un-clicking
' check boxes, entering values into input fields). Other events will cause
' WinEvent to return control to your program.
' There are 3 pre-defined generic events/actions that will cause WinEvent to
' return control to the calling program: the close icon (upper right) was
' double clicked (or ESC hit), a line of scrollable text was double
' clicked (or ENTER was hit while the scrollable text had FOCUS and no
' other button had FOCUS), or a push button was single clicked (or ENTER
' was hit while the button had FOCUS). You can also define Hot Keys, and
' corresponding WinEvent action codes. Each user-defined Hot Key is also
' considered a window event. When a Hot Key is selected, WinEvent returns
' control to the calling program with the corresponding user-defined
' action code for that Hot Key.
'
' The value of the WinEvent function corresponds to the window's number
' that generated the above action.
' First, an explanation of the difference between a window's number and its
' handle is necessary. When a window is opened (BlankWindow or
' OpenScrollWindow), it is given a unique number. Data for the window is
' stored in several arrays, and the index to these arrays is called the
' window's handle (CurWinPtr is a global variable containing the handle
' of the window currently in FOCUS). The slots of the arrays are re-used
' as windows are opened and closed, so the window's handle cannot be used
' to uniquely determine the window. The window's number is a sequential
' value which is never re-used. Thus handle number 3 might point to data
' for window number 6 at one point, and after that window is closed and
' another is opened, handle number 3 could then point to data for window
' number 7. This is why WinEvent returns the window's number that generated
' the event. If it returned the handle, you could not be sure exactly which
' window was currently pointed to by the handle (and thus how to handle the
' action from that window). WinNum is a cross reference array containing
' window numbers. WinNum(i) contains the window number that corresponds to
' handle i.
' In general, WinEvent should be placed at the top of a DO/LOOP. After
' returning control to your program, test WinEvent's value to determine
' which window number had FOCUS, then for each possible window number that
' your program could open, process the particular event/action.
' You can determine if any information was entered into input fields,
' if check boxes were selected, if buttons were clicked, etc. in the
' current window.
' the global variable AnyWinOpen can be used to control the DO/LOOP.
' It will be TRUE as long as there is an open window on the screen. However,
' if an information only window is open (i.e., one with text only where
' no events could occur), then you must use another criteria
' to end the DO/LOOP because the info only window will always be open.
' In this case, termination should occur when a close action
' occurs in the main window.
' Prototype code would look like this:
' open some windows and make buttons, etc.
' window numbers saved in variables win1 and win2
' win1=OpenScrollWindow(......)
' make some buttons
' win2=OpenScrollWindow(....)
' make some buttons
' DO WHILE AnyWinOpen
' wnum=WinEvent(action) ' wnum= win number; action= action code
' SELECT CASE wnum
' CASE win1
' SELECT CASE action
' CASE 1 ' close
' process the close action
' CASE 2 ' text selected
' process the selected text
' CASE 3 ' button clicked
' process the button
' END SELECT
' CASE win2
' SELECT CASE action
' CASE 1 ' close
' process the close action
' CASE 2 ' text selected
' process the selected text
' CASE 3 ' button clicked
' process the button
' END SELECT
' END SELECT
' LOOP
'
' A brief description on how to process window events will be
' given here. Refer to LANGWIN.DOC and the sample programs distributed
' with LangWin for more details.
'
' Three data structures contain information necessary to process
' window events: WinParms(CurWinPtr,i): data on current window
' ButtonsData(Handle,i): data on all buttons/fields
' ButtonsText(Handle): text contents of buttons/fields
'
' CurWinPtr: is a global parameter maintained by LangWin.
' It always points to the current window's handle.
' Handle: is the value assigned to the button/box/field when
' it was opened (see: MakePushButton, MakeCheckBox,
' and MakeInputField)
' i: represents an index into the structure
' Suggested processing for the various actions/events returned by WinEvent:
'
' CLOSE EVENT (code = 1):
' Not much to do here.
' CALL CloseWindow to close the current window.
' Then continue processing the DO/LOOP with WinEvent as long
' as other windows are still open.
'
' SCROLLABLE TEXT EVENT (code = 2):
' A line of scrollable text was selected.
' SaveText(i,j) contains the selected text; where
' i=WinParms(CurWinPtr,18)
' j=WinParms(CurWinPtr,15)
'
' Process the selected text line as appropriate.
' For example, if the contents of SaveText(i,j) must be modified (i.e.,
' a "select" character toggled), then update the text line as necessary.
' After updating the text, CALL ReShowText to
' re-display the new text in the current window. The scrollable
' text could consist of parameters that, when selected, will cause
' additional processing (and maybe additional windows to be open).
' Use the values of i and j to determine which line in your scrollable
' parameter list was selected (and thus what additional processing
' and/or windows are needed).
'
' After all processing has been completed for the text line selected,
' continue with the WinEvent loop.
'
' PUSH BUTTON EVENT (code = 3):
' A specific Push Button was selected. WinParms(CurWinPtr,16)
' contains the Handle for that button. Using that Handle, you
' should compare it to the handles of all buttons created for the given
' window that generated the event (all button handles assigned by
' MakeCheckBox and MakeInputField should be saved in variables).
' When you find a match, process the button action as necessary.
' Prototype might look like this (assume button1 & button2 variables
' contain handles of buttons created for the window):
' CASE 3 ' button clicked
' handle=WinParms(CurWinPtr,16)
' SELECT CASE handle
' CASE button1
' code to process button1
' CASE button2
' code to process button2
' END SELECT
' You may need to determine which text line had FOCUS when the Push
' Button was selected, and you may need to determine if any Input
' Fields or Check Boxes were modified prior to the Push Button being
' selected.
'
' If WinParms(CurWinPtr,15) contains a -1, then no scrollable text
' exists in the current window. Otherwise SaveText(i,j) had FOCUS
' when the button was selected. Where:
' i=WinParms(CurWinPtr,18)
' j=WinParms(CurWinPtr,15)
' To determine if any Input Field was modified, examine the contents
' of all Input Fields in the given window using the handles saved
' when you created the Input Field. Knowing the previous contents
' of the Input Field, and its handle, test the value of
' ButtonsText(handle). Take appropriate action if Input Field
' was updated. If your program modifies an input field, then CALL
' ReShowInputField to re-display the new Input Field in the current
' window.
' To determine the state of any Check Boxes in the current window, use
' its Check Box handle (saved when you created the check boxes) and
' examine ButtonsData(Handle,7). If this is a 1, then the Check Box
' corresponding to Handle was not set. If this is a 0, then the box was
' set. Do all necessary processing based upon the state of Check Boxes.
'
' After all processing has been completed for the button selected,
' continue with the WinEvent loop.
' Calling WinEvent with action% set to -999 will enable the "time out"
' feature. This feature will cause WinEvent to return control to the
' calling program if no events are detected after 0.5 seconds. This
' can be used to implement an "interrupt" button for long running tasks.
'In order to interrupt a long running task, place the task in a loop with a
'call to WinEvent (with time out feature enabled). Each time through the loop,
'some portion of the long running task is completed (like reading one record
'from a large file, scanning one directory, whatever portion of the overall
'task that is appropriate). After completing a portion of the long running
'task, call WinEvent with the time out feature. After the call to WinEvent,
'determine what (if any) event occurred. If the event was a click on your
'interrupt button, exit the loop that processed the long running task. If no
'event occurred (i.e., WinEvent timed out after 0.5 seconds), then loop and
'perform more work on the long running task.
'Here's some pseudo code. Assume this code gets control when a "start" button
'is clicked to initiate the long running task. Also assume that prior to this
'point, a MODAL window was opened with start and interrupt buttons for the
'long running task. Finally, assume that the long running task is to read all
'records from a file.
' CASE StartButton
' deactivate "start" button (don't need it now)
' activate "interrupt" button (assume it was previously inactive)
' open a file (assume the long running task is to read a file)
' ' process long running task
' DO
' read a record (assume the long running task is to read a file)
' update screen to show some kind of progress
' if EOF then EXIT DO ' see if task is done
' act=-999 ' to activate time out feature
' wn=WinEvent(act) ' get an action or time out
' LOOP UNTIL interrupt button action detected
' ' long running task completed or interrupted
' deactivate "interrupt" button (not needed now)
' activate the "start" button (if it's needed)
' close file
' process the data
' close the current window (if it's no longer needed)
'Note that you should not attempt to do too much work in your loop before
'periodically giving control to WinEvent (to see if the interrupt button was
'clicked). WinEvent is not aware of mouse clicks made before it is called
'because it must hide and re-show the mouse cursor during initialization
'(which causes the mouse driver to zero the mouse press counter). Thus, if you
'do a lot of processing before calling WinEvent, your user could have been
'attempting to click the interrupt button for awhile with no response. You'll
'have to experiment, and tune your code so that it gets back to WinEvent
'quickly. If you notice that the interrupt button needs to be clicked very
'frequently before it is recognized, then the cause is probably due to an
'excessive amount of time consumed by your task in between iterations of the
'loop where WinEvent is called.
'I strongly recommend that the window you open, with buttons to start and
'interrupt the long running task, be MODAL (i.e., only events in that window
'will be recognized by WinEvent, events in other windows will be ignored). The
'"in-line" call to WinEvent (in the loop that processes your long running task)
'will restrict the events recognized by your program to just those that you
'explicitly test after returning from WinEvent (the code you have elsewhere
'in your program to handle other buttons in other windows will not be given
'control). If the window with the start and interrupt buttons is not modal,
'then your user will be able to mouse to other windows, make them active, and
'click their buttons. This will have visual effects (active windows will move
'to the top, clicked buttons will move); however, unless explicit code to
'handle these events (in other windows) is included in your loop with the long
'running task, the clicks on other buttons will be ignored. This will confuse
'your user. By making the window with the start and interrupt buttons modal,
'your user will not be able to mouse to another window to make it active, and
'clicking objects on other windows will show no visual effect.
'See SAMPLE05.BAS for an example of the technique for using WinEvent's time
'out feature to implement an interrupt button.
END FUNCTION