Contributed samples and applications by Dr. Claudio Soto
A simple way to modify the cursor …
Retrieve memory variables from a memory (.mem) file
Syntax
RESTORE FROM <xcMemFile> [ADDITIVE]
Arguments
<xcMemFile> is the memory (.mem) file to load from disk. If an extension is not specified, the extension .mem is assumed. The file name may be specified as a literal string or as a character expression enclosed in parentheses.
ADDITIVE causes memory variables loaded from the memory file to be added to the existing pool of memory variables.
Description
RESTORE is a memory variable command that recreates public and private variables previously SAVEd to a memory (.mem) file and initializes them with their former values. The scope of the variable is not SAVEd with the variable, but is instead established when the variable is RESTOREd. Arrays and local variables cannot be SAVEd or RESTOREd.
When memory variables are RESTOREd, they are recreated as private variables with the scope of the current procedure or user-defined function unless they exist as public variables and you specify the ADDITIVE clause. If ADDITIVE is specified, public and private variables with the same names are overwritten unless hidden with PRIVATE. If ADDITIVE is not specified, all public and private variables are released before the memory file is loaded.
Local and static variables are unaffected by RESTORE. If a local or static variable has been declared in the current procedure or user- defined function and a variable with the same name is RESTOREd, only the local or static variable is visible unless references to the RESTOREd variable are prefaced with the MEMVAR alias.
Examples
. This example demonstrates a typical application of SAVE and RESTORE. Here memory variables containing screens are SAVEd TO and RESTOREd FROM memory files: // Create and use a pseudoarray of screens SAVE SCREEN TO cScreen1 SAVE ALL LIKE cScreen* TO Screens // <statements>... // RESTORE FROM Screens ADDITIVE nNumber = "1" RESTORE SCREEN FROM ("cScreen" + nNumber)
Seealso
LOCAL, PRIVATE, PUBLIC, SAVE
SAVE Save variables to a memory (.mem) file ------------------------------------------------------------------------------ Syntax SAVE TO <xcMemFile> [ALL [LIKE | EXCEPT <skeleton>]] Arguments <xcMemFile> is the memory (.mem) file to SAVE to disk. You may specify the file name as a literal string or as a character expression enclosed in parentheses. If you specify no extension, the file is created with a .mem extension. ALL [LIKE|EXCEPT <skeleton>] defines the set of visible private and public memory variables to save to <xcMemFile>. <skeleton> is the wildcard mask that characterizes a group of memory variables to SAVE. The wildcard characters supported are * and ?. Description SAVE copies public and private memory variables visible within the current procedure or user-defined function to a memory (.mem) file. Arrays and local and static variables, however, cannot be SAVEd. When variables are SAVEd, they are copied without any reference to scope. Variables hidden by PRIVATE or LOCAL declarations are not SAVEd. If you specify the ALL LIKE clause, variable names matching the <skeleton> mask are saved. By contrast, if you specify ALL EXCEPT, variable names not matching the <skeleton> are saved. You can specify a <skeleton> that includes wildcard characters. The * wildcard character matches any group of adjacent characters ending a variable name and can be specified only at the end of the <skeleton>. The ? wildcard character matches any single character and can be specified anywhere within the <skeleton>. Examples . This example saves all visible private and public variables to Temp.mem: PRIVATE cOne := "1" SAVE ALL TO Temp . This example saves all visible private and public variables with names beginning with "c" to Myvars.mem: SAVE ALL LIKE c* TO MyVars . This example saves all visible private and public variables with names that do not begin with "c" to Myvars2.mem: SAVE ALL EXCEPT c* TO MyVars2 Files Library is CLIPPER.LIB.
See Also: LOCAL PRIVATE PUBLIC RESTORE
We are continuing with Viva_HMG.hbp, Main.prg and Main.fmg. We have assign real actions other than MsgBox() to our two buttons now : Open File and Edit Record. Open File not required GUI controls ( at least for now ), so we can begin with it: For Open File we need a file ( a table ) first: it’s here; a table with four field: Clients.dbf :
No: Field Name Type Width Dec --- --------- ---- ----- --- 1 CLI_ID N 5 0 2 CLI_SNAM C 12 0 3 CLI_NAME C 12 0 4 CLI_TLF C 11 0
And then add a little routine to Main.prg for open (USE) it:
PROCEDURE OpenTable()
IF FILE( "CLIENTS.DBF" )
USE CLIENTS
ELSE
MsgStop( "Clients.dbf file not found !")
ENDIF
RETURN // OpenTable()
And assign this procedure to ACTION of Open File button.
Now, we can begin Edit Record task. For this task we need a separate form, a sub form. Then let’s begin. “New form” from tool-bar and assign a name : EditReco. Assign a title : “Edit Record”, a type : MODAL. Our table has four fields, so we need four LABEL first:
Names : lblCLI_ID, lblCLI_SNAM, lblCLI_NAME, lblCLI_TLF;
Values ( Captions ) : ID, Surname, Name, Tlf
Rows : 60, 100, 140, 180 Col : 60
Cols : 60, 60, 60, 60
Widths : 70, 70, 70, 70
Alignement : RIGHT, RIGHT, RIGHT, RIGHT
We can see our job at work:
Now we need a place for display the current data and accept user input. The control for this purpose is text box. So we need to define four text boxes for each field in the table.
The button of text box in the IDE tool bar is :
Names : txbCLI_ID, txbCLI_SNAM, txbCLI_NAME, txbCLI_TLF;
Rows : 55, 95, 135, 175
Col : 140
DataTypes : First : NUMERIC, others : CHARACTER
We can see our job at work:
Well …
But where are table data ?
To see table data we need assign field values to text boxes as values.
Again, a little procedure:
PROCEDURE ReadData() EditReco.txbCLI_ID.Value := CLIENTS->CLI_ID EditReco.txbCLI_SNAM.Value := CLIENTS->CLI_SNAM EditReco.txbCLI_NAME.Value := CLIENTS->CLI_NAME EditReco.txbCLI_TLF.Value := CLIENTS->CLI_TLF RETURN // ReadData()
and a call command for this procedure to ON INIT event of EditReco form.
The result :
Everything is OK ?
No !
This is only first record of table; how we will see others ?
Yes, we need now yet another feature: navigation; that is travelling between records of table.
But before navigation, we have a problem: Open Table must be processed before Edit Record.
Otherwise a run time error will occurs: Alias does not exist.
What we can do?
– Discard Open Table button, open the table automatically; at beginning of program or at beginning of editing.
– Before editing, check the table, if doesn’t open,
– a) open automatically or
– b) warn user and don’t load Edit Table form.
Probably most convenient is : disable Edit Record button until table is open.
First a mini procedure :
PROCEDURE Initialize()
Main.btnEditRec.Enabled := .F.
RETURN // Initialize()
And then add this procedure ON INIT event of form main:
Last point: enable it after USE table:
PROCEDURE OpenTable()
IF FILE( "CLIENTS.DBF" )
USE CLIENTS
Main.btnEditRec.Enabled := .T.
ELSE
MsgStop( "Clients.dbf file not found !")
ENDIF
RETURN // OpenTable()
Run and see:
Before Open File :
After Open File:
Now we can pass to navigation:
We need seven buttons: Go Top, Go Next, Go Previous, Go Last, Save, Discard, Exit.
Name: btnGoTop, Caption : Top, Col : 50, Row: 220, Height: 28, Width: 60
Name: btnGoNext, Caption : Next, Col : 130, Row: 220, Height: 28, Width: 60
Name: btnPrevious, Caption : Previous, Col : 200, Row: 220, Height: 28, Width: 60
Name: btnGoLast, Caption : Last, Col : 270, Row: 220, Height: 28, Width: 60
Name: btnSave Caption : Save, Col : 380, Row: 60, Height: 28, Width: 100
Name: btnDiscard, Caption : Discard, Col : 380, Row: 140, Height: 28, Width: 100
Name: btnExit, Caption : Exit, Col : 380, Row: 220, Height: 28, Width: 100
Common: Font Name: Tahoma, Font Size: 9
Actions :
btnGoTop: ( DBGOTOP(), ReadData() )
btnGoNext: ( DBSKIP(), ReadData() )
btnPrevious: ( DBSKIP( -1 ), ReadData() )
btnGoLast: ( DBGOBOTTOM(), ReadData() )
btnSave: SaveData()
btnDiscard: ReadData()
btnExit: ThisWindow.Release
Note that actions of four first buttons include two actions, separated by comma and enclosed by parenthesis. With this notation we can define more than one action together.
SaveData() is the inverse of ReadData(): copy values of text boxes to table fields.
PROCEDURE SaveData() // Save data from text boxes to table
CLIENTS->CLI_ID := EditReco.txbCLI_ID.Value
CLIENTS->CLI_SNAM := EditReco.txbCLI_SNAM.Value
CLIENTS->CLI_NAME := EditReco.txbCLI_NAME.Value
CLIENTS->CLI_TLF := EditReco.txbCLI_TLF.Value
RETURN // SaveData()
Discard is simply re-reading data from table.
The result:
To be continued …
Place keyboard input into a memory variable
ACCEPT [<expPrompt>] TO <idVar>
Close files and release public and private variables
CLEAR ALL
Release all public and private variables
CLEAR MEMORY
Create and initialize private memory variables and arrays
DECLARE <identifier> [[:= <initializer>], ... ]
Declare database field names
FIELD <idField list> [IN <idAlias>]
Enter the result of an expression into a variable
INPUT [<expPrompt>] TO <idVar>
Declare and initialize local variables and arrays
LOCAL <identifier> [[:= <initializer>], ... ]
Declare private and public variable names
MEMVAR <idMemvar list>
Return a set-get code block for a given memory variable
MEMVARBLOCK(<cMemvarName>) --> bMemvarBlock
Create private parameter variables
PARAMETERS <idPrivate list>
Create and initialize private memory variables and arrays
PRIVATE <identifier> [[:= <initializer>], ... ]
Create and initialize public memory variables and arrays
PUBLIC <identifier> [[:= <initializer>], ... ]
Delete public and private memory variables
RELEASE <idMemvar list>
RELEASE ALL [LIKE | EXCEPT <skeleton>]
Retrieve memory variables from a memory (.mem) file
RESTORE FROM <xcMemFile> [ADDITIVE]
Save variables to a memory (.mem) file
SAVE TO <xcMemFile> [ALL [LIKE | EXCEPT <skeleton>]]
Declare and initialize static variables and arrays
STATIC <identifier> [[:= <initializer>], ... ]
Assign a value to one or more variables
STORE <exp> TO <idVar list>
<idVar> = <exp>
<idVar> := [ <idVar2> := ...] <exp>
The ‘data-version’ of these controls required the use of the following properties / methods to bound them to a database field:
Field Property: Stablishes the field that control is bounded to.
Refresh Method: Updates control content based on current field content.
Save method: Updates database file according control content.
#include "hmg.ch" Function Main DEFINE WINDOW Win_1 ; AT 0,0 ; WIDTH 640 ; HEIGHT 480 ; TITLE 'Tutor 21: Data-Bound Controls Test' ; MAIN ; ON INIT OpenTables() ; ON RELEASE CloseTables() DEFINE TOOLBAR ToolBar_1 BUTTONSIZE 100,30 FLAT RIGHTTEXT BORDER BUTTON TOP ; CAPTION '&Top' ; PICTURE 'primero.bmp' ; ACTION ( DbGoTop() , Refresh() ) BUTTON PREVIOUS ; CAPTION '&Previous'; PICTURE 'anterior.bmp' ; ACTION ( DbSkip(-1) , Refresh() ) BUTTON NEXT ; CAPTION '&Next'; PICTURE 'siguiente.bmp' ; ACTION ( DbSkip(1) , if ( eof() , DbGoBottom() , Nil ) , Refresh() ) BUTTON BOTTOM ; CAPTION '&Bottom' ; PICTURE 'ultimo.bmp' ; ACTION ( DbGoBottom() , Refresh() ) BUTTON SAVE ; CAPTION '&Save' ; PICTURE 'guardar.bmp' ; ACTION ( Save() , Refresh() ) BUTTON UNDO ; CAPTION '&Undo' ; PICTURE 'deshacer.bmp' ; ACTION ( Refresh() ) END TOOLBAR @ 50,10 LABEL LABEL_1 VALUE 'Code:' @ 80,10 LABEL LABEL_2 VALUE 'First Name' @ 110,10 LABEL LABEL_3 VALUE 'Last Name' @ 140,10 LABEL LABEL_4 VALUE 'Birth Date:' @ 170,10 LABEL LABEL_5 VALUE 'Married:' @ 200,10 LABEL LABEL_6 VALUE 'Bio:' @ 50,200 TEXTBOX TEXT_1; FIELD TEST->CODE ; NUMERIC ; MAXLENGTH 10 @ 80,200 TEXTBOX TEXT_2; FIELD TEST->FIRST ; MAXLENGTH 30 @ 110,200 TEXTBOX TEXT_3; FIELD TEST->LAST ; MAXLENGTH 30 @ 140,200 DATEPICKER DATE_4 ; FIELD Test->Birth @ 170,200 CHECKBOX CHECK_5 ; CAPTION '' ; FIELD Test->Married @ 200,200 EDITBOX EDIT_6 ; FIELD Test->Bio ; HEIGHT 100 END WINDOW Win_1.Text_1.SetFocus ACTIVATE WINDOW Win_1 Return Nil Procedure Refresh Win_1.Text_1.Refresh Win_1.Text_2.Refresh Win_1.Text_3.Refresh Win_1.Date_4.Refresh Win_1.Check_5.Refresh Win_1.Edit_6.Refresh Win_1.Text_1.SetFocus Return Procedure Save Win_1.Text_1.Save Win_1.Text_2.Save Win_1.Text_3.Save Win_1.Date_4.Save Win_1.Check_5.Save Win_1.Edit_6.Save Return Procedure OpenTables USE TEST Return Procedure CloseTables USE Return