Paradox Community
Search:

 Welcome |  What is Paradox |  Paradox Folk |  Paradox Solutions |
 Interactive Paradox |  Paradox Programming |  Internet/Intranet Development |
 Support Options |  Classified Ads |  Wish List |  Submissions 


Paradox Newsgroups  |  Paradox Web Sites  |  Paradox Book List  |  FAQs From The Corel FAQ Newsgroup  



Subject: TIP:PdoxWin:Recommended ways of Exchanging 
Information:2000.03.25

Version 1.0 (2000.03.25)
edited by Paradox FAQ Team
Reposted by Mike Irwin: 2001.02.10

====================
0. Introduction
====================
This FAQ addresses the frequent request for an example of a
standardised technique for passing information from place 
to place within a Paradox program. This code was originally 
written in 1993 and has been in use, in various guises, 
ever since.

Recently, there have been a number of threads in the 
newsgroups where correspondents have recommended other 
techniques, such as using code in one form to take values 
off the face of another form. While these methods 
undoubtedly work, one should, ar least, read this FAQ 
before deciding on a technique to use.

-------------------------------
 0.1 Legal Info and Disclaimers
-------------------------------
Paradox is a trademark of Corel.
Borland Database Engine (BDE) is a trademark of Inprise.
The information provided in this FAQ is provided "as is" 
and is not warranted in any way. The information provided 
in this FAQ is not endorsed or authorized by Corel or 
Inprise in any shape, form, or manner. 

The editors claim NO responsibility for ANY illegal 
activity regarding this file, or as a result of someone 
reading this file.

You may distribute this file, as long as the copies are
complete, unaltered, and are in electronic form only.
-------------
 0.2 Feedback
-------------
Please send feedback in a Corel Paradox newsgroup or the
news:comp.databases.Paradox newsgroup to any of the
FAQ Team mentioned in the "FAQ: FAQ FAQ"
document.

Please preface the subject of your post with the string
"PDXWIN FAQ" to alert Team members to the function of
the message.

Please specify the FAQ name and section number the
comment applies to, if any.

-------------
 0.3 Attachment
-------------

Attached to this FAQ is the file InfoLib.Exe. This is
a self-extracting Zip file created with WinZip 6. Running 
it will bring up a "Save As" dialog where d:\temp is 
offered as the default location. Change this to your 
Paradox :work: directory and let it extract the three 
files:

test.fsl    Form to do testing with
test.rsl    Report to send an environment string to
InfoLib.lsl Library to store named values

You can run the exe file to obtain a Zip file, or run it 
directly to extract the three files to a subdirectory. 
There is no need to actually have an unzipping program.

The code is all written and tested using Paradox 9 
(9.00.512), but should be completely compatible with all 
versions of Paradox for Windows.

======================
1. General Information
======================

When writing a program in an environment like 
Paradox/Windows, there is often a need to pass information 
from one part of the program to another.

Theoretical Computer Science has determined that programs 
that are made up of parts that are tightly bound to one 
another are significantly more fragile and more difficult 
to maintain than are those that are comprised of loosely 
interconnected modules.

One result of this is the elimination of global variables 
from many languages. Paradox is one such, although one can 
argue that tables are, themselves, global variables. 
ObjectPAL does, in fact, have a global variable area, and 
we'll discuss that later, as it is essential for certain 
operations.
-------------------------------
1.1 When do you need to move information ?
-------------------------------
Some examples should be of use here. Please note that this 
is not intended to be an exhaustive list !

a. Passing the key to a table from a master to a detail 
form
b. Returning a selected value from a lookup form
c. Storing a global setting, such as "print to screen" that 
has been set by the user
d. Setting values on a called form from the calling form
e. Obtaining values from another form before it closes
f. Passing information to and from a Script, Form, or 
Library.
g. Passing information into a report

-------------------------------
1.2 Ways of moving data - an overview
-------------------------------
There are many ways of moving information around. Here are 
some examples. Each one is designed to fulfill the need 
expressed in the equivalent example in section 1.1.

a. Open a form and then call a method of that form to 
provide it with the information
b. Use formReturn(), placing the data as a parameter to
   formReturn()
c. Call a method in the form that invoked the lookup to 
return the information
d. Obtain a Form variable connected to the form and set the
   values directly, thus populating or manipulating objects 
on the form directly.
e. Read and write Profile Strings, or use the textStream 
methods.
f. Pass the value as part of a name-value pair to a 
library. The receiving code obtains the value by asking for 
it and specifying the appropriate name.
g. Use the Paradox Environment Strings. These are Paradox'
   equivalent of global variables.
-------------------------------
1.3 Ways of moving data - recommended ones
-------------------------------
 We can recommend two ways.

1. Pass the value as part of a name-value pair to a 
library. The receiving code obtains the value by asking for 
it and specifying the appropriate name. This is recommended 
because:
   a. you can use the same code to exchange information 
between any two pieces of ObjectPAL in your system, with no 
regard to where they are located (Form, Library, or 
Script). For this reason alone it is very easy to move your 
code, or copy/paste it, with a minimum of alterations.
   b. The technique is simple, obvious, and elegant to 
read.
   c. The technique is simple to implement, will work 
without alteration for all versions of Paradox for Windows, 
and can be easily extended if new data types become 
available.
   d. When a form is reworked to add features or to remove 
bugs, perhaps months or years in the future, perhaps by 
another programmer, it is obvious how information is being 
moved. Using other methods, such as explicitly manipulating 
fields on one form from another, is an activity that is not 
obvious to the programmer, and something that produces 
"mysterious" behaviour. 

2. For passing information into a report, we recommend 
using the Paradox Environment Strings. The advantages here 
are
   a. Aside from modifying the data tables, and making them
      totally dependent on the report, there is no other 
way to pass information into a report.
   b. They are simple and easy to use when obviously 
associated with a report, because they are name-value 
pairs, just as are the data values in #1 above.

   However, Environment Strings are sometimes used by 
people as global variables. This is definitely NOT 
recommended, as it makes much code dependent on one single 
point of failure, which is always a bad idea.
   As a maintenance programmer, you will not appreciate 
trying to find where an Environment String was set; adding 
diagnostics to a library is much easier !

==========
2. Examples
==========
Please note that there is an EXE file attached to this TIP.
It was created using WinZip, and includes three files only:

test.fsl    Form to do testing with
test.rsl    Report to send an environment string to
InfoLib.lsl Library to store named values

You can run the exe file to obtain a Zip file, or run it 
directly to extract the three files to a subdirectory. 
There is no need to actually have an unzipping program.

The code is all written and tested using Paradox 9 
(9.00.512), but should be completely compatible with all 
versions of Paradox for Windows.
-------------------------------
2.1 Environment Strings
-------------------------------
There are three methods for dealing with Environment 
Strings. Courtesy of Corel's Paradox 9 docs, these are:

-------------------------------
2.1.1 readEnvironmentString()
-------------------------------
Reads an item from the Paradox copy of the OS environment.

Syntax

readEnvironmentString ( const key String ) String

Description

readEnvironmentString() returns a string containing 
information about the OS environment variable specified by 
key. When you launch Paradox it makes a copy of the OS 
environment. 

readEnvironmentString() reads that copy and compiles 
information in a string. Changes made to the OS environment 
variables after Paradox is launched are not reflected by 
information returned by this procedure.
-------------------------------
2.1.2 writeEnvironmentString()
-------------------------------
Sets a variable in the Paradox copy of the OS environment.

Syntax

writeEnvironmentString(const key String, const value 
String)Logical

Description

writeEnvironmentString() sets a variable in the Paradox 
copy of the OS environment. When Paradox launches, a copy 
of the OS environment is made. writeEnvironmentString() 
writes to that copy but changes are not written to the 
underlying OS environment.
-------------------------------
2.1.3 enumEnvironmentStrings()
-------------------------------
Lists all of the items from the OS environment.

Syntax

enumEnvironmentStrings ( var values DynArray[ ] String ) 
Logical

Description

enumEnvironmentStrings() lists all of the items from the OS
environment. This method writes the items to a dynamic 
array, values, which you declare and pass as an argument.
-------------------------------
2.1.4 Using readEnvironmentString() in a Report
-------------------------------
To use this technique of passing information from a form, 
put the following code in the pushButton() method of a 
button on a new form:

var
   reTest         Report
endvar
   writeEnvironmentString("Title", "This is the Title")
   writeEnvironmentString("Value", "42")
   reTest.open("Test")


In the same directory, create a new report, called 
Test.rsl.

Somewhere in Test.rsl, place a new field. Right-click on 
the field and select the "Define Field" option to define 
what data it should show.

Check off the checkbox at the bottom left of the dialog,
labeled "Calculated", and place the following line into the 
field provided for entry of the calculation:

readEnvironmentString("Title")

Make another field on the report, and this time put the 
following code into the code window:

"The ultimate answer is " + readEnvironmentString("Value") 
+ ", which is the number of days in " +
String(smallInt(readEnvironmentString("Value")) / 7) + " 
weeks !"

Note that you'll have to make this into just one long line.
I have split it in places where losing a space will not 
matter.

-------------------------------
2.2 Using a library
-------------------------------
To provide a useful example, I have created a complete 
library for free re-use. Called InfoLib, it implements two 
data types (Strings and AnyTypes) in dynArrays, and also 
offers a limited facility for exchange of dynArrays.
-------------------------------
2.2.0 General Internals
-------------------------------
-------------------------------
2.2.1 Initialisation
-------------------------------


You must open the InfoLib library in every form that will 
use it:

if not InfoLib.open(":LibraryAlias:Infolib") then
   foGMySelf.attach()      ;get a form pointer to myself.
   msgStop("Error",
           "Object " + foGMySelf.name() +
           " unable to open library InfoLib")
endif


-------------------------------
2.2.2 Using Strings
-------------------------------
a. To store a string:

   InfoLib.setStVar("Name", "Value")

b. To recover the same string:

var
   stVal   String
endVar
   stVal = InfoLib.getStVar("Name")

c. Exceptions:

   If the supplied name "Name" is not defined when 
requested using getStVar(), the string "Undefined" will be 
returned.
-------------------------------
2.2.3 Using AnyTypes
-------------------------------
a. To store a string:

var
   atVal   AnyType
endVar
   ;set atVal to some value
   InfoLib.setAtVar("Name", atVal)

b. To recover the same string:

var
   atVal   AnyType
endVar
   atVal = InfoLib.getAtVar("Name")

c. Exceptions:

   If the supplied name "Name" is not defined when 
requested using getStVar(), the string "Undefined" will be 
returned.
-------------------------------
2.2.4 Using DynArrays
-------------------------------
a. Assumed type declaration. This must be included in your 
code that uses these methods:

   Type
      UserDynArray = dynArray [] String
   endType

   If you want to change the functionality to, say, 
smallInts, then you should change this appropriately, and 
make the corresponding change within the library

b. To empty a user-defined dynArray already loaded in the
 library. Note that siUserNr is only defined between 1 and 
5, inclusive. You can easily change that in the code, but 
I've never needed more than five. If you specify a user 
number outside the specified range then the request is 
simply ignored.

   InfoLib.emptyUserDynArray(siUserNr)

c. To read a user dynArray from the library:

var
   uaMyDynArray     userDynArray
endvar

   uaMyDynArray = InfoLib.readUserDynArray(siUserNr)

d. To store a dynarray into the library:

var
   uaMyDynArray     userDynArray
endvar
   ;fill the dynArray somehow ....
   writeUserDynArray(siUserNr, uaMyDynArray)

-------------------------------
2.2.5 Other Functionality
-------------------------------
a. Version. A version number is held in Const, and returned 
in the method version(). All user-created libraries should 
provide this functionality, so that the user can easily 
report what versions exist on his or her system when you 
are debugging remotely.

b. Again for debugging, a method showStVars() is provided, 
that offers a view of all the Strings. You can easily add 
the same for the other types.
infolib.exe


Paradox Community Newsgroups


 Feedback |  Paradox Day |  Who Uses Paradox |  I Use Paradox |  Downloads 


 The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation.
 Paradox is a registered trademark of Corel Corporation.


 Modified: 15 May 2003
 Terms of Use / Legal Disclaimer


 Copyright © 2001- 2003 Paradox Community. All rights reserved. 
 Company and product names are trademarks or registered trademarks of their respective companies. 
 Authors hold the copyrights to their own works. Please contact the author of any article for details.