VERSIONS: P7
SUBJECT: Frequently Asked Questions about ObjectPAL
BY: BORLAND
Beginning ObjectPAL
Q: HOW CAN I DITTO A RECORD (COPY THE CONTENTS OF THE PREVIOUS RECORD TO THE CURRENT
RECORD)?
A: The following example demonstrates how to do this. The code is placed in a pushButton method.
method pushButton(var eventInfo Event)
if isEdit() then
if active.inserting = False and active.atLast() then
;// Insert was not pressed but a blank record
;// was appended to the end of the table
tc.attach(active)
;// Attach TCursor to UIObject
tc.copyToArray(ar)
;// Store record to the array
active.InsertRecord()
;// Initialize the new blank record
active.copyFromArray(ar)
;// Copy array to current record
tc.close() ;// Close the TCursor
else
if active.inserting = true then
active.postRecord()
;// Post the new blank record
tc.attach(active)
;// Attach TCursor to UIObject
tc.priorRecord()
;// Move up one record
tc.copyToArray(ar)
;// Store current TCursor record to the array
active.copyFromArray(ar)
;// Copy array to current record
tc.close()
;// Close the TCursor
else
msgInfo("Ditto Record","Insert a new record")
endIf
endIf
else
msgInfo("Ditto Record","Must be in edit mode to ditto a
record")
endIf
endMethod
Note: The Tab Stop property of the Ditto Record button must be False. To verify this, go into design mode, then right-click the button, choose
Properties if you are using Paradox 7 for Windows 95, then select Run Time. The Tab Stop property should be unchecked.
When you click on the Ditto Record button, it verifies if Insert was pressed. If Insert was pressed, it repeats the previous record. If Insert was
not pressed, the message "Insert a new record" appears.
If you are positioned at the top of the table, you must insert a new record before clicking the Ditto Record button.
Once you have inserted a new record, it copies the data in the fields from the first record of the table into the newly inserted record.
The code in the Ditto Record button does not require you to insert a new record when you are appending records to the end of your
The code in the Ditto Record button does not require you to insert a new record when you are appending records to the end of your
table.
Note: If your table is keyed, you will need to change the key before trying to post the newly copied record.
Q: HOW DO I VIEW A REPORT IN DIFFERENT VIEW MODES SUCH AS FIT WIDTH WHEN I OPEN MY REPORT VIA
OBJECTPAL?
A: If you are using version 5.0 or later, you can use the following code:
var
r Report
endVar
;// Open a report. Substitute your own report name
;// for Rptname.RSL.
r.open("Rptname.RSL")
r.menuAction(MenuPropertiesZoomFitWidth)
For additional menu commands, search ObjectPAL Help for menuCommands.
Q: CAN I USE SETGENFILTER() ON A REPORT?
A: Yes you can. Here is an example:
method pushButton(var eventInfo Event)
var
r Report
dyn DynArray[] String
stField String
stData String
endVar
;// Load the report in design mode.
r.load("Customer.RSL")
;// Filter on the Name field with the value Unisco
stField = "Name"
stData = "Unisco"
dyn[stField] = stData
;// Customer is a tableframe UIObject
r.Customer.setGenFilter(dyn)
;// Prevent Save message from appearing when report
;// is closed.
r.designmodified = False
r.print() ;// Print the report.
r.close() ;// Close the report.
endMethod
Q: HOW CAN I PASS DATA TO A CALCULATED FIELD ON A REPORT?
A: You can pass data to a calculated field on a report by setting a DOS environment variable on a form by using the System type method
writeEnvironmentString(). In the calculated field on the report, you would use readEnvironmentString() to read in the DOS environment variable
you set via writeEnvironmentString(). Here is an example:
On the pushButton method on a form:
writeEnvironmentString("myenvvar", "Hello World")
On a report's calculated field:
readEnvironmentString("myenvvar")
When you run the report, Hello World will show up in the calculated field. You must run the form first so that the DOS environment variable
is set or else nothing will display in the calculated field in the report.
Q: IS THERE A WAY TO KEEP MEMO VIEW ACTIVE, LIKE CTRL-F2 (PERSISTENT FIELD VIEW) KEEPS FIELD VIEW
ACTIVE?
A: There is no PersistentMemoView action constant. But you can add the following code to the arrive method of the memo field to ensure
that you are in Memo View:
dodefault
Self.action(EditEnterMemoView)
With this code, you'll be able to add tabs and returns to your memo, but you may find it difficult to depart from your memo field without
using your mouse. To remedy this situation, you can press F2 to exit Memo View and then press Tab or Return to move to the next field.
Q: HOW CAN I TRAP FOR THE CANCEL BUTTON BEING PRESSED ON THE VIEW() DIALOG BOX?
A: You can not trap for the OK or CANCEL buttons on a View dialog box. What you can do to get around this is to initialize the variable to ""
or some standard value. You would check the value of the variable after the view() is called. If the value is still the initial value that you set, then
the user did not enter a value or pressed CANCEL. You could also use the function isAssigned() to see if the variable was assigned a value or not.
Here again, this will tell you if the user did or did not enter a value or if the CANCEL button was pressed.
If neither of these suggestions is adequate for your situation, then you need to create your own dialog box that returns the value OK or
CANCEL.
Q: HOW DO I MAKE A RADIO BUTTON OR CHECK BOX SELECTED WHEN I OPEN A FORM OR PRESS A BUTTON?
A: The way you set a value for a radio button or a check box is to assign the field the value of the radio button you want selected. For
instance, suppose you have a field with a Display Type of radio button with three buttons labeled, "A", "B", and "C" respectively. Your field's name
is The_Field. You want the "B" button to be selected when you press a button. To do this, you would place the following code in the pushButton
method of the button:
The_Field.value="B"
When the button is pressed, the button labeled "B" will be selected.
This method also works for check boxes. When you set up a check box, you are asked to supply a value for when the field is checked and
when it isn't checked. Setting the value of the field to the Checked Value causes the field to be checked. To uncheck the field, just assign the field
the Unchecked Value.
If you want a field to be checked when the form opens, be sure to use DoDefault before your "check" code. This will ensure that the field is
opened so that its Value property can be modified.
Advanced ObjectPAL
Q: DURING RUNTIME, IF I CREATE AN OBJECT WITH DEFAULT CODE ON IT (AFTER COPYTOTOOLBAR()), THE CODE WILL
NOT EXECUTE. WHY NOT? THE CODE DOES EXIST ON THE OBJECT WHEN I GO INTO DESIGN MODE.
A: Paradox must first compile the code before it can execute it. There are two workarounds:
- Put the form into design mode first, create the object and then run the form. (This is not useful if the form receiving the object is the active
form.)
- Trap for the built-in event at the form level then perform that object's particular code. Tips: Give the object a name and trap for the class of the
object.
Q: HOW DO I HIDE THE PARADOX MENU SO NO MENU OPTIONS ARE SHOWN?
A: Use the following code:
var
main Menu
endVar
main.addText("")
main.show()
This will place an empty menu on the Desktop. If you do not use the addText method to add an empty string, you will get an error message "You
have tried to use an undefined variable. A variable must be assigned a value before you can use it".
Q: HOW DO I SET THE STATUS BAR SO THAT IT DOESN'T DISPLAY MESSAGES?
A: In the status method of the form, type the following code:
eventInfo.setStatusValue("")
This will set all status messages to blank.
Q: HOW CAN A PREVENT A USER FROM RESIZING A FORM?
A: You can place the following code in the menuAction event method of the form (below the else portion) as follows:
method menuAction(var eventInfo MenuEvent)
if eventInfo.isPreFilter() then
;// This code executes for each object on the form
else
;// This code executes only for the form
if eventinfo.id() = menucontrolsize then
disabledefault
endIf
endIf
endMethod
Q: HOW CAN I PREVENT USERS FROM EDITING A DROP-DOWN EDIT FIELD?
A: On the keyChar() method of the drop-down edit field object, type disableDefault.
Q: HOW CAN I EMPTY A DROP-DOWN EDIT OR LIST FIELD?
A: A drop-down edit or list field can be emptied by setting the list.count property of its list object to 0. For example, the following code
empties the list object contained in a field named MyListField:
var
uiList UIObject
endVar
;// attatch to list object inside the field object
uiList.attach(MyListField.first)
uiList.list.count = 0
Q: MY OBJECTPAL CODE USES THE VALUE OF A FIELD ON MY FORM - BUT SEEMS TO ONLY SEE THE OLD VALUE, NOT
THE VALUE JUST ENTERED. HOW DO I MAKE SURE THE NEW VALUE IS USED?
A: Exercise care when you are using the Value property of a field in a ChangeValue event method. The default behavior of this event is to
change the value from it's original unedited value to the new modified value; so timing is important. The expression, self.Value, returns the old
value if accessed before doDefault and it returns the new value after doDefault. The expression, eventInfo.newValue(), always returns the new
value.
Q: I HAVE SEVERAL FORMS THAT NEED TO USE THE VALUE STORED IN A PARTICULAR VARIABLE. HOW CAN I USE A
LIBRARY TO ALLOW ALL FORMS ACCESS TO THAT VALUE?
A: When you need a variable to be global to more than one form, it is necessary to create a library. Use the library's Var window to declare
the variables and create custom methods (declared in the library) to pass these variables to and from forms.
Q: CAN I SELECT A DIFFERENT PRINTER DRIVER USING OBJECTPAL? CAN I CHANGE THE PRINTER
ORIENTATION?
A: The best way to choose a printer driver using ObjectPAL is to use the printerSetCurrent() procedure (available with Paradox version 5.0
and higher). You can also use the enumPrinters() procedure to retrieve a list of printer setups available on the computer. Each entry returned by
enumPrinters() is a string that contains the printer driver name, the printer driver filename and the printer port. The desired entry can be used as
the parameter in the printerSetCurrent() procedure.
To set options such the printer orientation and paper size, use the printerSetOptions() procedure, which is also available for users of Paradox
5.0 and higher. Refer to the ObjectPAL Reference for an example.
All versions of Paradox for Windows support reportPrintInfo records with the print() method that enable you to select options such as page
orientation and number of copies (depending on the capabilities of the printer.)
Q: IF I ENCOUNTER A PROBLEM WHEN PERFORMING A FIXED LENGTH IMPORT USING OBJECTPAL, WHAT MIGHT I DO
TO CORRECT OR CIRCUMVENT THE PROBLEM?
A:
- Test the import interactively to determine if the problem is import-related or code-related.
- If the error dialog gives you the option, choose ignore and allow the import to finish.
- Set MaxFileHandles to 14 in database engine configuration file
- Use another product to do the import, then import the data to Paradox.
- Check the available disk space. There should be enough space to accommodate a file at least three times the size of the text file.
- Use a text editor to write a sub-section of the file to a new text file. Try importing the file in sections to locate the problem section.
Q: I AM TRYING TO OPEN A SECOND FORM FROM A PUSHBUTTON. I WANT TO HAVE BOTH FORMS SHOW THE
INFORMATION FOR THE SAME KEY FIELD (E.G., CUSTOMER, PART, INVOICE NO, ETC.) HOW CAN I DO THIS?
A: Open the second form hidden using the open() method. Next, perform a locate on the second form so that it is showing the same record as
the first form. Then display the second form and have the first form wait on the second. In the example below, there is a field object named
"Customer_No" on the first and second form, and the key field is named "Customer No".
var
secondForm Form
endvar
secondForm.open("SecondFormName", WinStyleDefault + WinStyleHidden)
secondForm.Customer_No.locate("Customer No",Customer_No'Value)
secondForm.bringToTop()
secondForm.wait()
Q: I HAVE AN UNDEFINED (DATE/NUMBER) FIELD ON MY FORM. I WANT TO BE ABLE TO VALIDATE THE VALUE THAT
MY USER ENTERED SO THAT I KNOW I AM GETTING THE CORRECT INFORMATION.
A: In order to validate this information, you can do the following. On the changeValue method of the field, enter the following code:
doDefault
try
;// This is to convert the information to a Date-type value.
;// Change dateVal to LongInt, SmallInt, or Number for
;// different data types.
self.dateVal()
onFail
msgStop("Invalid Data","Please enter a date value.")
eventInfo.setErrorCode(CanNotDepart)
endTry
Q: I RUN AN OBJECTPAL QUERY, WITH THE RESULT STORED IN A TCURSOR. I THEN USE SCAN TO COPY THE RESULTS
INTO A TABLEFRAME ON MY FORM. FREQUENTLY (BUT NOT ALWAYS) ONLY THE FIRST ROW OR ROWS OF THE RESULT SHOW IN
THE TABLE, UNTIL FOCUS IS SHIFTED TO THE TABLE, AT WHICH TIME IT DOES INDEED FILL CORRECTLY WITH ALL THE ROWS OF
THE RESULT. WHAT CAN BE DONE TO FIX THIS?
A: TableFrame.forceRefresh() should work in most situations.
Q: WHAT IS THE BEST WAY TO GET THE CONTENTS OF A TCURSOR TO A LIBRARY FOR PROCESSING?
A: It is possible to pass a TCursor variable by reference, just like other variables, to the library. See the ObjectPAL Reference, for information
on passing by reference.
Q: HOW DO I PERFORM ACTIONS IN A MODAL DIALOG (SUCH AS THE PRINT DIALOG)? THE SENDKEYS PROCEDURE
DOESN'T SEEM TO EXECUTE UNTIL AFTER THE DIALOG BOX HAS BEEN ANSWERED.
A: The only way to get sendKeys to perform an action inside a modal dialog is if the sendKeys action itself is what initiated the dialog box.
For instance, the following
sendKeys( "%FP~" )
opens and closes the Print dialog box and performs the requested action. Whereas
sendKeys( "%FP" )
sendKeys( "~" )
waits until the user manually presses Enter before the sendKeys Enter is pressed.