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