803.TXT
     =====================================================================
     Using BLOBs
     =====================================================================
     PRODUCT:  R:BASE                  VERSION:  5.X
     =====================================================================
     AREA   :  Other                   CATEGORY: General Information
     =====================================================================
 
     The most exciting new feature of R:BASE 5.0 is the ability to store 
     and display binary files_Binary Large OBjects or BLOBs. This term 
     refers to binary data as opposed to ASCII data. The new data types 
     VARBIT and BITNOTE have been added for storing binary files within 
     an R:BASE database. In addition, the VARCHAR data type lets you 
     store large ASCII data files (Large OBjects or LOBs). The data for 
     VARBIT and VARCHAR data types is stored in the new R:BASE data file, 
     dbname.rb4. As with the other three database files, dbname.rb4 is 
     linked with a timestamp and can be stored on a different drive.
 
     The VARBIT data type stores binary files_data such as bitmaps, 
     charts, graphs, and logos. Any file can be stored in a VARBIT. The 
     VARBIT data type is defined with a fixed length or as a variable 
     length by using LONG VARBIT. A VARBIT can store a file up to 256MB in 
     size per row. In general, it is easier to use the LONG VARBIT data 
     type, which automatically deals with any size binary file. For very 
     small binary files (less than 4,088 bytes), you can use the BITNOTE 
     data type. A BITNOTE stores binary data in the dbname.rb2 file 
     similar to the way NOTE data is stored. 
 
     The VARCHAR data type stores large ASCII files_files with more data 
     than can be placed in a NOTE data type. A document file from a word 
     processing program such as Word or WordPerfect is a binary file, not 
     an ASCII file. The document file contains formatting characters and 
     must be saved as a text or ASCII file to be stored in R:BASE as a 
     VARCHAR data type. A document file can be stored in a VARBIT data 
     type, but is not readable within R:BASE. As with the VARBIT data 
     type, a VARCHAR data type is defined with a length, or as a LONG 
     VARCHAR to be variable length. 
 
     Working with VARBIT and VARCHAR data types is different than working 
     with other R:BASE data types. Normally, you think of loading data 
     from one file into many columns and many rows in a table. With VARBIT 
     and VARCHAR data, you are loading a file into one column in one row in 
     a table. Once you have loaded a file into a VARBIT or VARCHAR data 
     type, you can delete the original file from disk. The data file is 
     now stored within the database.
 
     Because you are loading a file into a column, it is often easiest to 
     store VARBIT and VARCHAR data in a separate table linked to the data 
     table with an ID column. The table storing the BLOB data can then 
     include a column for the original file name and a column for a 
     description of the BLOB data file.
 
     The original file can be recreated at any time using the WRITE 
     command. This command has been modified in R:BASE 5.0 to write binary 
     or large ASCII data to a file. The data is read from the table into a 
     variable, then the variable written to a file. This process recreates 
     the file exactly. 
 
     SET VAR vbinarydata LONG VARBIT = varbitcolumn IN table WHERE .... 
     WRITE .vbinarydata TO filename
 
     Data is loaded into a VARBIT or VARCHAR column directly from a file 
     with either the LOAD or INSERT command. The file name is specified in 
     a special format, ['filename.ext']. This format tells R:BASE 5.0 to 
     find the specified file and treat it as BLOB data. Data in a VARBIT 
     or VARCHAR can be replaced from a file using the UPDATE command, but 
     cannot be directly edited. In addition, VARBIT and VARCHAR data can 
     be loaded and updated through a form. Press [Shift][F10] from a 
     VARBIT or VARCHAR field located on a form to open the Windows common 
     file dialog box. Select the file to be loaded into the field. You do 
     not need to specify the file name in a special format when loading 
     through a form.
 
     Any binary file can be loaded into a VARBIT column; however, only BMP, 
     PCX, TIF, and GIF formats can be displayed within R:BASE. Data in 
     these formats can be displayed on a form or report, or with the SHOW 
     VAR command.
 
     They are many ways to use these new data types within your databases 
     and applications. To help you get started, the following articles 
     show some of the ways to use VARBIT or VARCHAR data types. These 
     articles have examples of the commands that load and display these 
     data types.
 
       Print a Logo on a Report
       Display a Graphical Logo in Your Application
       Zoom In On a Bitmap on a Form
       Store Application Files in a Database
       Create an Application with Push Buttons
 
     In addition, some sample bitmaps and command files are included with 
     R:BASE 5.0 to demonstrate using check boxes, radio buttons and other 
     graphical interface images in your applications.
 
 
     Print a Logo on a Report
 
     Printing a logo on a report is one of the easiest ways to use a VARBIT 
     data type. No programming is required. Store the bitmap file 
     containing the logo in a table in your database, or place it into a 
     variable before printing the report. By storing the bitmap in a table, 
     the bitmap is always available. Create a simple, three-column table 
     to hold various bitmaps. Use the Database Designer, RBDefine, or the 
     following commands from the R> prompt window to create the table.
 
     CREATE TABLE BitMaps (BitID INTEGER, FileName TEXT 12, BitData LONG 
     VARBIT)
     AUTONUM BitID IN BitMaps USING 1,1
 
     The BitID column is autonumbered and holds an identifying number for 
     the row. The FileName column holds the name of the original file. 
     Storing the name of the original file is handy if you ever need to 
     recreate the file on disk. The BitData column holds the bitmap data. 
     Data is loaded into the table with either the INSERT or LOAD 
     commands. For example,
 
     INSERT INTO BitMaps VALUES ('ccclogo.bmp',['ccclogo.bmp'])
 
     You can also load data into the BitMaps table using a form. Follow 
     the steps below to build a form and load bitmap data. 
 
     1.Create a new, quick form on the BitMaps table and select all three 
     columns to place on the form.
     2.Change Field Settings for the BitID field so the data cannot be 
     modified; it is automatically numbered. 
     3.Resize the BitData field to make it larger so more of the image 
     displays.
     4.Run the form and choose to enter data.
     5.Enter the file name containing the image in the FileName field. 
     6.Press [Shift][F10] from the BitData field to open the Windows common 
     file dialog box. 
     7.Select the bitmap file. The image displays on the form. 
     8.Choose Add row from the Forms menu to save the row to the BitMaps 
     table.
 
     The example below shows how the data appears in the table. The 
     BitData column displays the type of binary data that is stored, 
     usually the file extension.
 
      BitID      FileName     BitData
      ---------- ------------ --------
               1 ccclogo.bmp  [BMP]
 
     Now you are ready to place the logo on a report. Follow these steps: 
 
     1.Start the Report Designer and create a new report.
     2.Select the table from which the report will use data; don't select 
     the BitMaps table as the report table.
     3.Define a lookup variable to retrieve the logo graphic. You can use 
     either the BitID column or the FileName column to retrieve the data. 
     For example,
 
          vlogo = BitData IN BitMaps WHERE BitID = 1
 
       The variable is automatically data typed as VARBIT.
     4.Place the variable in the Page Header section and resize it. You 
     might need to print the report and resize the variable a couple of 
     times to get the correct field size.
 
     Each page of the report contains the company logo at the top. This 
     method works great for printing invoices or statements.
 
     Display a Graphical Logo in Your Application
 
     Displaying a logo screen when your application starts up is as easy 
     as printing a logo on a report. Create the logo using any graphics 
     program, for example, the PaintBrush program that comes with 
     Windows. We recommend saving the file in BMP format. You can also 
     save it as PCX, TIF, or GIF. Load the file into a BitMaps table, or 
     directly into a variable.
 
     Using the Application Designer, edit the Startup block of the 
     application and add the following commands if the bitmap is loaded 
     into a table:
 
     SET VARIABLE vLogoScreen = BitData IN BitMaps WHERE BitID =2
     SHOW VAR vLogoScreen=40,20 AT 5,5
     PAUSE FOR 10
 
     Use these commands if the bitmap is loaded from the file directly 
     into a variable:
 
     SET VAR vLogoScreen LONG VARBIT = ['ccclogo.bmp']
     SHOW VAR vLogoScreen=40,20 AT 5,5
     PAUSE FOR 10
 
     To display VARBIT data using the SHOW VARIABLE command, give width 
     and height parameters for the display and a screen location. As with 
     locating a bitmap on a report or form, you might need to adjust the 
     parameters a couple times to get the best display of the image. Test 
     the SHOW VARIABLE command at the R> prompt to determine the correct 
     width and height parameters. The screen location specifies the upper
     left corner of the display area.
 
     Placing the commands to display the logo in the Startup block clears 
     the screen before the main menu of the application is displayed. The 
     application itself contains commands (NEWPAGE) to clear the screen. 
     To always display the logo when the main application menu is 
     displayed, you must edit the .APP file.
 
     Place the SET VARIABLE and SHOW VARIABLE commands immediately prior 
     to the CHOOSE command that displays the main menu.
 
     SET VARIABLE vLogoScreen = BitData IN BitMaps WHERE BitID = 2
     SHOW VAR vLogoScreen=40,20 AT 5,5 
     CHOOSE PICK1 FROM MENU0000 IN appname.APX
 
     Then, use CodeLock to rebuild the .APX file. Select the last option 
     from the CodeLock dialog box, "Convert an ASCII Application File to a 
     Binary Procedure File." At the first file selection dialog box, name 
     the ASCII file, appname.APP. At the second file selection box, name 
     the procedure file, appname.APX. When you return to the CodeLock 
     dialog box, click either the Cancel or OK button.
 
     The logo is now displayed in the background whenever the main 
     application menu is displayed. If you modify the application in the 
     Application Designer, edit the appname.APP file again to add the SET 
     VARIABLE and SHOW VARIABLE commands, and repeat the CodeLock 
     procedure.
 
     Zoom In On a Bit Map on a Form
 
     A graphical image stored in a VARBIT data type can be directly 
     located on a form as either a column or a variable. However, the 
     image might take up too much of the form page. Instead of directly 
     locating the image, locate a TEXT variable or small image instead. 
     Run an entry/exit procedure (EEP) from that field and use the SHOW 
     VARIABLE command to zoom in on the image display. The image display 
     is cleared with a single keystroke.
 
     Modify an old form or create a new one. Define a form expression, 
     vid = custid. This expression places the linking id number in a 
     variable so the EEP can retrieve the correct image. The image 
     matching the row of data being edited in the form is looked up from 
     a table. You only need five lines of code in the entry/exit 
     procedure. The SET VARIABLE and SHOW VARIABLE commands retrieve and 
     display the image. The SKIP TO fieldname command resets the cursor 
     position.
 
     -- retrieve the image from the lookup table
     SET VAR vbmp LONG VARBIT = ImageData IN Images WHERE custid = .vid
     -- display the image
     SHOW VAR vbmp=45,10 AT 10,27
     -- pause to display the image until a key is pressed
     -- the image displays for 6 minutes if a key is not pressed
     PAUSE FOR 360
     CLS
     -- move the cursor back to the id field
     SKIP TO custid
 
     callouts
 
     The image displayed by the EEP. Press any key to clear the image from 
     the screen.
 
     The located field with a field entry EEP to zoom in on the matching 
     image. Click on the field to see the image.
 
 
     Store Application Files in a Database
 
     Using the new VARBIT data type, you can now store application files 
     within the database itself, making it easier to distribute and 
     backup applications. In addition, a description of each application 
     file can be stored with the file for easy and convenient 
     documentation of applications. CodeLocked application files, ASCII 
     application files, and EEPs can be stored. While you could store the 
     ASCII files in a VARCHAR data type column, and the CodeLocked files 
     in a VARBIT data type column, the VARBIT data type accommodates both 
     ASCII and binary (CodeLocked) files.
 
     Add a table to the database to store the application files. 
 
     CREATE TABLE AppTable (AppID INTEGER, AppName TEXT 8, FileName TEXT +
     12, Description NOTE, Modified = (.#DATE) DATE, FileData LONG VARBIT)+
     AUTONUM AppID IN AppTable USING 1,1
 
       AppID_An INTEGER autonumber column provides a unique identifier for 
        each row. 
       AppName_The application name. Different applications can be stored 
        in the same table. 
       FileName_The application file name for the data loaded into the 
        FileData column on this row. The name is used to recreate the 
        application file for execution. 
       Description_A description of the application file. 
       Modified_A computed date column that is automatically updated 
       whenever data in the row changes. This lets you know if the most 
       recent copies of the application files are stored.
       FileData_The application file data
 
     You can load the table using INSERT commands from the R> prompt, from 
     a form, or by running a short command file. Using a form is 
     convenient for applications with few files; you can enter all the 
     fields at one time. Build a new form for AppTable. You can even use a 
     quick form. Set a field color on the FileData field to make the field 
     visible on the form; no data displays in the field when the form is 
     run. Run the form and choose to enter data. At the FileData field, 
     press [Shift][F10] to open the Windows common file dialog box where 
     you can select the file to load for that row.
 
     Using a command file is more efficient for applications made up of 
     many files. The command file quickly loads all the files and file 
     names. The sample command file, loadfile.rmd, prompts for a file 
     extension, and automatically loads all selected files. It loads data 
     into the FileName and FileData columns only. The AppID and Modified 
     columns are automatically loaded. The other columns are edited after 
     the files are loaded. The command file uses a CHOOSE command to 
     select the files and return a comma-delimited list. A WHILE loop 
     retrieves the files one by one, formats the name for loading into a 
     VARBIT data type, and loads the file.
 
     *(loadfile.rmd)
     CLS
     SET MESSAGE OFF
     SET ERROR MESSAGE OFF
     SET ERROR VAR vError
     SET VAR vExt TEXT = NULL, vAllNames TEXT = NULL
     -- prompt for the file extension to load. For example,
     --.RMD, .CMD, or .AP*. Wild cards can be used
     DIALOG 'Enter file extension:' vExt=3 vKey 1
     -- create a file reference to use in the CHOOSE command
     SET VAR vExt1 = ('*.'+ .vExt)
     -- the playback file contains [Shift][F6][Enter]. It automatically
     -- selects all the files from the menu
     PLAYBACK menu.pla
     -- bring up a menu of all files in the current directory
     -- matching the specified extension.
     CHOOSE vAllNames FROM #LFILES IN &vExt1 CHKBOX
     -- exit if nothing selected or no files found
     IF vError <> 0 OR vAllNames = '[Esc]' THEN
     RETURN
     ENDIF
 
     -- get the first file name
     SET VAR vCount INTEGER = 1
     SET VAR vFName1 = (SSUB(.vAllNames, .vCount))
     -- format the file name for loading into a VARBIT column
     -- the file name needs to be surrounded by square brackets and quotes
     SET VAR vFName2 = ('[''' + .vFName1 + ''']')
     PAUSE 3 USING 'Processing files' AT CENTER,CENTER DEFAULT
     WHILE vFName1 IS NOT NULL THEN
     -- load the file name and the file data, you must reference the
     -- formatted file name as an ampersand variable
     INSERT INTO AppTable (FileName, FileData) VALUES +
     (.vFName1, &vFName2)
     -- get the next file name
 
       SET VAR vCount = (.vCount + 1)
       SET VAR vFName1 = (SSUB(.vAllNames, .vCount))
       SET VAR vFName2 = ('[''' + .vFName1 + ''']')
     ENDWH
     CLS
     RETURN
 
     After all the application files have been loaded, edit the table, 
     AppTable, and fill in the data for the remaining columns, AppName 
     and Description. Data in the table might look like the following:
 
      AppID  AppName  FileName     Descr               Modified  FileData
      ------ -------- ------------ ------------------  ------------------
      1 Concomp  CONCOMP.APP  ASCII application   03/01/95       [APP]
                              file created by
                              Application Express
      2 Concomp  CONCOMP.API  Internal file used  03/01/95       [API]
                              by Application
                              Express. Delete
                              this row and can't
                              use Apps Express
                              for this app
      3 Concomp  CONCOMP.APX  The run file        03/01/95       [APX]
                              created by
                              App Express
                                                                 
     Once the table has been loaded with all the application files, the 
     database is ready for testing and distribution. Distribute a small 
     command file with the database to recreate the application files as 
     disk files. The application files remain stored in the database. 
     Then, at any time, the files can be easily restored.
 
     *(bldfile.rmd)
     -- a cursor on AppTable walks through each row, making a disk
     -- file for each file that has been loaded
     DROP CURSOR c1
     DECLARE C1 CURSOR FOR SELECT FileName, FileData FROM AppTable
     OPEN c1
     -- place the file name and the file data into variables
     FETCH c1 INTO vFileName i1, vFileData i2
     WHILE SQLCODE <> 100 THEN
     -- place the data back into a disk file. The file is recreated
     -- exactly
     WRITE .vFileData TO .vFileName
     -- get the next file
     FETCH c1 INTO vFileName i1, vFileData i2
     ENDWH
     CLOSE c1
     DROP CURSOR C1
     CLS
     RETURN
 
     The command file can be enhanced to prompt for an application name, or 
     to prompt for a specific file. The process is the same; put the file 
     data into a variable, and then write the data to a file.
 
     Use a command file to update the application files with new files 
     from disk or update the table through a form. In the form, press 
     [Shift][F10] to prompt for the file name when in the FileData column. 
     Be sure to color the FileData field on the form; no data displays for 
     the field when the form is run_only BMP, PCX, TIF, and GIF formats 
     display for a VARBIT data type. ASCII files loaded into a VARCHAR 
     data type are displayed on a form, but are not editable. You must 
     always replace the file to update the data.
 
     *(updfile.rmd)
     -- prompt for the file name 
     SET VAR vFileName = NULL
     DIALOG 'Enter file name to update' vFileName=12 vKey 1
     -- set a variable to the data in the file
     SET VAR vFileData TEXT = ('[''' + .vFileName + ''']')
     -- you must use an ampersand variable when the variable
     -- contains the name of a file to be loaded
     UPDATE AppTable SET FileData = &vFileData WHERE FileName =.vFileName
     CLS
     RETURN
 
 
 
     Create an Application with Push Buttons
 
     Create great looking applications in R:BASE 5.0 using graphical 
     images. You can add push buttons that go up and down, a customized 
     tool bar, radio buttons, and check boxes. The VARBIT data type is 
     used to hold the image, then an R:BASE command file controls the 
     display of the image on the screen, traps the mouse click, and 
     performs an action. You can even program in hot keys.
 
     First, create the images. You can draw your own icons or buttons, 
     or copy them from other programs. Use Print Screen or Alt Print 
     Screen to copy a screen containing an icon, button, or other image 
     to the Windows clipboard. Then open up Windows PaintBrush and paste 
     the image from the clipboard. Cut out the desired portion of the 
     screen and paste to a new window in PaintBrush. Edit the image as 
     necessary. Save the modified image as a .BMP file. For up and down 
     buttons or icons you need two images. Generally, an up image has 
     light edges on the top and left, and dark edges on the bottom and 
     right. The down image is reversed, light on the bottom and right 
     edges, and dark on the top and left edges. Try your hand at making 
     some buttons and other images; you'll find it much easier than you 
     think. Some sample image files are included with the R:BASE 5.0 
     sample files; look in the Buttons directory.
 
     Next, create the command file to display the image files and execute 
     actions when a button, for example, is selected. The basic program 
     structure is the same regardless of the type of graphical image you 
     display. The image files are placed into variables, then displayed 
     on the screen using the SHOW VARIABLE command. A WHILE loop allows 
     movement between images. The GETKEY function within the WHILE loop 
     captures the mouse click or keystroke. GETKEY differentiates between
     a left mouse button, [MOUSEBUTTON1], and a right mouse button, 
     [MOUSEBUTTON2]. You can then add different actions for the left and 
     right mouse buttons to your program. The right mouse button can run 
     a custom help file, for example. When a key is pressed, GETKEY 
     returns the keystroke, [Alt]P, for example. The ISTAT functions 
     return the location of the mouse click so you can tell which button 
     was pressed. File button.rmd demonstrates the basic program structure 
     by displaying a single button on the screen and printing a report 
     when the button is clicked. 
 
 
     *(button.rmd)
     CLS
     SET MESSAGE OFF
     SET ERROR MESSAGE OFF 
     SET TIME FORMAT HH:MM:SS.SSS
     -- Define variables
     SET VAR vkeyhit TEXT = '[Enter]'
     SET VAR vmousecol INTEGER, vmouserow INTEGER, v1 TIME
 
     -- Place the image files into variables. An up and a down 
     -- button image requires two variables.
     SET VAR vbutton_up LONG VARBIT = ['button.bmp']
     SET VAR vbutton_dn LONG VARBIT = ['buttond.bmp']
     PAUSE FOR 1
     -- Display the up button image. The screen location is used
     -- later in the program in conjunction with the display size of
     -- the image to determine if a mouse click occurred on the button.
     -- The screen location (10,10) is the location of the upper left
     -- corner of the image. The display size (10,3) is approximately
     -- 10 columns wide and 3 rows deep.
     SHOW VAR vbutton_up=10,3 AT 10,10
     
     -- Set up a loop to check mouse actions. You can keep selecting
     -- the button until the Esc key is pressed
     WHILE vkeyhit <> '[Esc]' THEN
     -- check for a key hit/mouse click
     SET VAR vkeyhit = (GETKEY(0))
     -- A left mouse click returns [MOUSEBUTTON1], a keystroke
     -- returns that key, for example, [Alt]P
     
     -- Retrieve the location of the mouse click into variables.
     SET VAR vmousecol = (ISTAT('mousecol'))
     SET VAR vmouserow = (ISTAT('mouserow'))
 
 
     -- Check the screen column and screen row location of the mouse
     -- click. They must be checked together, it is the combination of
     -- row and column that makes a valid mouse click. The column must
     -- be between the column display parameter (10) and the variable
     -- display width (10) from the SHOW VAR command The row must 
     -- be between the row display parameter (10) and the variable
     -- display height (3) from the SHOW VAR command 
     IF vmousecol BETWEEN 10 AND 20 AND vmouserow BETWEEN 10
     AND 13 THEN
     -- If the mouse click was on the button, display the image of
     -- the down button.
     SHOW VAR vbutton_dn=10,3 AT 10,10
     -- The following WHILE loop provides a time delay before
     -- the up button is displayed again. Without the time delay
     -- you don't see the down movement of the button. Setting the
     -- time format makes sure the time delay is in milliseconds, not 
     --seconds
 
           SET VAR v1 = (.#TIME + 200)
           WHILE #TIME < .v1 THEN
           ENDWH
          -- Redisplay the up button image
          SHOW VAR vbutton_up=10,3 AT 10,10
     -- Print the report
           PRINT customer
 
       ENDIF
     -- Redisplay the up button image and wait for another mouse click
     CLS
     SHOW VAR vbutton_up=10,3 AT 10,10
     ENDWH
     -- Reset the environment
     CLS
     SET MESSAGE ON
     SET ERROR MESSAGE ON
     RETURN
     
     Command file button2.rmd has been modified to check for either a 
     mouse click on the button or the keystroke [Alt]P. The same action 
     is executed in either case. To reduce code duplication in the 
     program, you can place common code in another file and run it from 
     different CASE statements; or you can do as in this example, set a 
     flag variable and then execute the common code after the 
     CASE...SWITCH block.
 
     *(button2.rmd)
     CLS
     SET MESSAGE OFF
     SET ERROR MESSAGE OFF 
     
     -- Define variables
     SET VAR vkeyhit TEXT = '[Enter]'
     SET VAR vmousecol INTEGER, vmouserow INTEGER, v1 TIME, vgoodkey+ 
     INTEGER
 
     -- Place the image files into variables. An up and a down
     -- button image requires two variables
     SET VAR vbutton_up LONG VARBIT = ['button.bmp']
     SET VAR vbutton_dn LONG VARBIT = ['buttond.bmp']
 
     -- Display the up button image.
     SHOW VAR vbutton_up=10,3 AT 10,10
     
     -- Set up a loop to check actions. You can keep selecting
     -- the button until the Esc key is pressed
     WHILE vkeyhit <> '[Esc]' THEN
     -- check for a key hit/mouse click
     SET VAR vkeyhit = (GETKEY(0))
     
     -- The CASE...SWITCH block checks for either a valid key stroke
     -- or a mouse click in the right location
     SWITCH (.vkeyhit)
     
     CASE '[Alt]p'
     -- The correct key was pressed, set the flag variable to 1
     -- You could have a RUN statement here to execute common code
     -- in another file
     SET VAR vgoodkey = 1
     BREAK
     -- Execute the following case block if either mouse button is pressed
     -- You can check for multiple values by stacking the CASE statements
         CASE '[mousebutton1]'
         CASE '[mousebutton2]'
         SET VAR vmousecol = (ISTAT('mousecol'))
         SET VAR vmouserow = (ISTAT('mouserow'))
 
     -- Check the screen column and row location of the mouse click.
         IF vmousecol BETWEEN 10 AND 20 AND vmouserow BETWEEN 10
     AND 13 THEN
     -- The mouse was clicked in the right location, set the flag
     -- variable to 1.
     -- You could have a RUN statement here to execute common code
     -- in another file
         SET VAR vgoodkey =1
         ENDIF
         BREAK
       DEFAULT
     -- An incorrect key or mouse click, the flag variable is set to 0
         SET VAR vgoodkey = 0
       ENDSW
     -- Execute the common code if a valid key was pressed or the mouse
     -- clicked in the right location
       IF vgoodkey = 1 THEN
         SHOW VAR vbutton_dn=10,3 AT 10,10
         SET VAR v1 = (.#TIME + 200)
         WHILE #TIME < .v1 THEN
         ENDWH
         SHOW VAR vbutton_up=10,3 AT 10,10
         PRINT customer
     -- reset the flag variable
         SET VAR vgoodkey = 0
         CLS
         SHOW VAR vbutton_up=10,3 AT 10,10
       ENDIF
     ENDWH
     -- reset the environment
     CLS
     SET MESSAGE ON
     SET ERROR MESSAGE ON
 
     This same basic program structure is used for displaying and working 
     with other types of graphical image files. The R:BASE 5.0 sample 
     files include command files to display images of radio buttons, check 
     boxes, and buttons within a frame. The sample command files follow the 
     same basic structure outlined in button.rmd. Review the R:BASE 5.0 
     sample files in the Buttons directory to see how to incorporate 
     multiple images.
 
     In an application with push buttons for many different actions, you 
     can accumulate quite a number of image files. Just five buttons is 
     ten files (each button needs an up image and a down image). The image 
     files can be stored in a table in the database, but the dbname.rb4 
     file can grow quite large. Create an application using as many 
     different buttons as you want with just two image files of blank 
     buttons. The application writes the appropriate text on the blank 
     button image. To make an application with push buttons even easier, 
     store the button information (text, screen display location, action 
     to execute) in a table in your database. Define a table with the 
     following structure: 
 
     CREATE TABLE Button (ButtonID INTEGER, ButtonRow INTEGER, ButtonCol +
     INTEGER, ButtonText TEXT 8, ButtonAction TEXT 60)
     AUTONUM ButtonID IN Button USING 1,1
 
       ButtonID_An INTEGER autonumber column provides a unique identifier 
       for each row. 
       ButtonRow_The display row for the upper left corner of the button 
       image.
       ButtonCol_The display column for the upper left corner of the 
       button image.
       ButtonText_The text to display on the button.
       ButtonAction_The action to execute when the button is pressed. This 
       can be a single R:BASE command or the name of a command file to run.
 
     The data in the Button table looks like the following:
 
      ButtonID   ButtonRow  ButtonCol  ButtonText ButtonAction
      ---------- ---------- ---------- ---------- ---------------
     -----------
               1          4         10 File       RUN newcust.cmd
               2          8         10 Edit       EDIT USING employee
               3         12         10 Print      PRINT customer
               4         16         10 Close      QUIT
               5         20         10 Help       ZIP
               
     c:\windows\winhelp.exe
 
     c:\dbfiles\apphlp
 
     The buttons are displayed in a column, one on top of the other. Click 
     on a button to execute the action specified in the table. It is easy 
     to add additional buttons, just add rows to the table. The button 
     locations do not need to be in any particular order in the table, 
     nor do the buttons need to be displayed in a column. You could 
     display a row of buttons across the top of the screen, for example, 
     or randomly place them. Make sure the locations are placed far enough 
     part so that the buttons will not overlap each other. To store 
     buttons for different applications, add a column to hold the 
     application name. The command file button3.rmd shows how the basic 
     program structure is modified to check the mouse click location 
     against data in a table.
 
 
     *(button3.rmd)
     CONNECT CONCOMP
     -- clear the screen and define environment --
     CLS
     SET MESSAGE OFF
     SET ERROR MESSAGE OFF
     SET TIME FORMAT HH:MM:SS.SSS
 
     -- initialize variables
     CLEAR VAR vKeyHit, vMouseCol, vMouseRow, vButtonUP,
     vButtonDN
     SET VAR vKeyHit TEXT = '[Enter]'
     SET VAR vMouseCol INTEGER = 0, vMouseRow INTEGER = 0, +
       v1 TIME, vAction TEXT
 
     -- define and load variables with the button images
     SET VAR vButtonUP VARBIT = ['button.bmp']
     SET VAR vButtonDN VARBIT = ['buttond.bmp']
 
 
     -- Display the buttons on the screen
     -- The declare cursor and WHILE loop displays all the buttons
     -- from the button table, a where clause on the declare cursor
     -- can be used to limit the buttons displayed
     -- This same code is repeated later in the program to redisplay
     -- the buttons after the specified action is performed
 
     DROP CURSOR c1
     DECLARE c1 CURSOR FOR +
       SELECT ButtonID, ButtonRow, ButtonCol, ButtonText FROM Button
     OPEN c1
     FETCH c1 INTO vButtonID, vRow, vCol, vText
     WHILE SQLCODE <> 100 THEN
     -- Set up the button text, the text is centered in 8 characters
        SET VAR vButtonText TEXT = (CTR(.vText, 8))
        SET VAR vTextCol INTEGER =  (.vCol + 1)
        SET VAR vTextRow INTEGER =  (.vRow + 1)
 
     -- Display the first button and write the text onto the blank button
        SHOW VAR vButtonUP=10,3 AT &vRow, &vCol
        WRITE .vButtonText AT &vTextRow &vTextCol BLACK ON GRAY
 
     -- Fetch data for the next button
     FETCH c1 INTO vButtonID, vRow, vCol, vText
     ENDWH
     DROP CURSOR c1
 
     -- Set up loop to check mouse actions
     WHILE vKeyHit <> '[Esc]' THEN
     -- Fetch the appropriate button information from the table based
     -- on the location of the mouse click
       SET VAR vButtonid = NULL
       SET VAR vButtonid = Buttonid IN Button WHERE +
         .vMouseRow BETWEEN ButtonRow AND (ButtonRow + 2) +
          AND .vMouseCol BETWEEN ButtonCol AND (Buttoncol + 10)
 
       IF vButtonID IS NULL THEN
     -- The first time through the loop this section executes
         SET VAR vRow = NULL , vCol = NULL, vText = NULL, vAction = NULL
         GOTO endloop
       ELSE
         SET VAR vRow = ButtonRow, vCol = ButtonCol, vText = ButtonText, +
                 vAction = ButtonAction IN Button WHERE ButtonID = +
                 .vButtonID
       ENDIF
 
     -- Set up the button text and image for down button display
       SET VAR vButtonText TEXT = (CTR(.vText, 8))
       SET VAR vTextCol INTEGER = (.vCol + 1)
       SET VAR vTextRow INTEGER = (.vRow + 1)
 
       SHOW VAR vButtonDN=10,3 at &vRow &vCol
       WRITE .vButtonText at &vTextRow &vTextCol BLACK ON GRAY
 
     -- This loop forces a time delay so the down action is visible
       SET VAR v1 = (.#TIME + 200)
       WHILE #TIME < .v1 THEN
       ENDWH
     -- Redisplay the up button image
       SHOW VAR vButtonUP=10,3 AT &vRow &vCol
       WRITE .vButtonText AT &vTextRow &vTextCol BLACK ON GRAY
 
     -- Execute the action stored in the table for the selected button
       &vAction
 
     -- Redisplay all the buttons. This is necessary as the executed
     action may have cleared the screen or written other data to the
     screen
     -- This is the same code as earlier in the file. It can be extracted
     -- and placed in a RUN file to avoid code duplication
       CLS
       DROP CURSOR c1
       DECLARE c1 CURSOR FOR + 
        SELECT ButtonID, ButtonRow, ButtonCol, ButtonText FROM Button
       OPEN c1
       FETCH c1 INTO vButtonID, vRow, vCol, vText
       WHILE SQLCODE <> 100 THEN
     -- Set up button text, the text is centered in 8 characters
         SET VAR vButtonText TEXT = (CTR(.vText, 8))
         SET VAR vTextCol INTEGER =  (.vCol + 1)
         SET VAR vTextRow INTEGER =  (.vRow + 1)
     -- Display the first button and write the text on the blank button
         SHOW VAR vButtonUP=10,3 AT &vRow,&vCol
         WRITE .vButtonText AT &vTextRow &vTextCol BLACK ON GRAY
     -- Fetch data for the next button
         FETCH c1 INTO vButtonID, vRow, vCol, vText
       ENDWH
       DROP CURSOR c1
 
       LABEL endloop
     -- Check for another mouse click and get the location
       SET VAR vKeyHit = (GETKEY(0))
       SET VAR vMouseCol = (ISTAT('mousecol'))
       SET VAR vMouseRow = (ISTAT('mouserow'))
 
     ENDWH
     -- reset the environment
     CLS
     SET MESSAGE ON
     SET ERROR MESSAGE ON
     RETURN