![]() |
![]() |
|
![]() |
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. ![]() |
![]() |
|