Some of these tips answer very frequently asked questions. Others are just plain interesting. Most are from
public postings on PB newsgroups & lists -- some by our staff, many by others. In some cases we lost
track of the name of the author. If we have included in this list something that you wrote, and if you would like
attribution, please drop us a line. If you would like to make some other kind of correction or your own contribution,
we'd be delighted to hear from you.
Alter Table - Adding not-null columns
Array - Changing from bounded to unbounded
Autologoff Bitwise and - Alternative
Connecting to multiple databases
Directory file list without a window
Dot notation - limitations in 5.0.0x
DW - changing the presentation style
DW - currentrow() and getrow()
DW column - highlighting of current row
DW column - setting value of computed column
DW - referencing computed fields
DW - finding column names at runtime
DW - finding controls at runtime
DW - preventing focus loss on tabbing from last row or column
DW
horizontal lines every
DW retrieval argument using aggregate function
DW update error, row changed between retrieve and update
Enter key - make it emulate the tab key
Login - Getting netware login name
PFC DDDW - multiple rows from a lookup
PFC Numeric service - hex extensions
PFC Transactions - optimistic locking, one opinion
PFC Windows - placing controls
Set default printer from within PB
Stored Procedure with Output Parameter
1. Export syntax of the table to the log.
2.
Save the log as a SQL file
3.
Drop the table.
4.
Go into the DBA Admin painter, open the SQL file that contains the syntax of
the table.
5.
Make changes.
6.
Execute the SQL. This will create the table again with the field options
changed.
ALTER TABLE - ADDING NOT-NULL
ATTRIBUTES OR COLUMNS
A
table doesnt have to be dropped or empty to add a NOT NULL constraint. You have only to
- make sure all rows are indeed not null on
the target field
- write and run the alter statement in the
DBA painter
You
have to leave and re-enter the painter to see the changes.
If new not null columns are to be added you either have to start with an empty table or do it in 3 steps:
first add the column, then fill in some values and finally set it to not null.
ARRAY CHANGING FROM BOUNDED TO
UNBOUNDED
string
lsNull [ ], lsBounded [ 5 ], lsUnbounded [ ]
//
assume lsUnbounded has been populated elsewhere.
lsUnbounded
= ls_Null
lsUnbounded
= ls_Bounded
Now
unbounded array will contain the values of the bounded array, dimensioned at 5.
To autologoff after an hour of
inactivity, place code in events as follows:
1. application idle event: gnv_app.event pfc_idle()
2. appmanager contructor event:
Idle(3600)
3. appmanager pfc_idle event:
halt close
If you are familiar with the workings of the Idle event, then you could have it start a timer on your frame window in PB5,
and there is a timer NVO in PFC 6.0. Both of these will trigger a timer event after the specified time length has expired.
Method 1:
Quick & dirty: log out any open transactions, and call a HALT CLOSE. This will force the application to close
immediately without any further processing. If you want open windows to be able to perform specific processing
before
the
app closes, then try something like Method 2.
Method 2:
Since you are using PFC, you could use the sheetmanager application service to pull a list of open sheet windows.
Inherit all of them from an application sheet ancestor and add a custom user event that will be triggered on all open
windows. Something like ue_IdleTimeout(). It will need a return code so the calling script will know when all the
processing is complete.
Instead of using an ancestor application sheet, you could also code this in w_master if you are using a copy of the
PFE layer for your application. Using w_master would allow you to include any open response windows, etc.,
though you have to figure out how get a reference to the non-sheet windows. Some tweaking to the sheetmanager
service might work.
In
the window you declare the event, add the following script:
ib_disableclosequery = True
This is a PFC instance variable that will disable all closequery and pfc_Save processing. Add any other globally
required logic. Then, in the rest of your windows down the inheritance chain, add any other specific logic that is
necessary. Once this event has been triggered on all open windows, close all transactions, and perform a HALT
CLOSE just to make sure something didn't get
missed
Alternative
to pfc's of_BiwiseAnd (). faster than
pfc's. Here is the comparison (50
calls):
this: . 1948 secs
pfc version .7168
sec
//
Function: of_BitWiseAnd (UnsignedLong
aul_value1,UnsignedLong aul_value2)
//
Description: ANDs each bit of the
values. this is an iterative function.
// al_Value1
The first value to be used in the operation.
// al_Value2
The second value to be used in the operation.
//
Returns: UnsignedLong The result of
the AND operation.
//
Author: Lijun Yang Date: 4/8/97
UnsignedLong lul_return = 0
Unsignedlong lul_multiple = 1
// Check for nulls
If IsNull(aul_Value1) Or IsNull(aul_Value2)
Then
SetNull(ll_Result)
Return ll_Result
End If
// Perform the AND
Do
lul_return += mod (aul_value1, 2) * mod (aul_value2, 2) * lul_multiple
aul_value1 = aul_value1 / 2
aul_value2 = aul_value2 / 2
lul_multiple *= 2
Loop Until aul_value1 = 0 AND aul_value2 = 0
RETURN lul_return
Colors in Windows are stored as 4 byte longs, with one byte each representing the Red, Green, and Blue
components and fourth byte usually indicating (alpha) transparency. The structure is: 0xAABBGGRR 0x is
hexadecimal zero, where AA is the alpha (usually 0), BB is the blue component, GG is Green, and RR is red.
0x00 represents no colour,
0xFF saturation You
can easily calculate the colors by the following two methods:
1) Use the Windows Calculator. Set the mode to Scientific (View->Scientific). Select Decimal (Dec) mode.
Enter the number you have, then change to Hex mode.
2)
Use math. R = mod (Colorvalue, 256); G = mod (Colorvalue /256, 256); B = mod
(Colorvalue/65536, 256)
The
16 basic colours are listed in Help/RGB. Other colors of note are:
Buttonface 79741120
WindowText 41943040
WindowBackground 1088479456
Transparent 536870912
CONSTANT long BLACK = 0
CONSTANT long WHITE = 16777215
CONSTANT long LIGHTGREY = 12632256
CONSTANT long DARKGREY = 8421504
CONSTANT long RED = 255
CONSTANT long DARKRED = 128
CONSTANT long GREEN = 65280
CONSTANT long DARKGREEN = 32768
CONSTANT long BLUE = 16711680
CONSTANT long DARKBLUE = 8388608
CONSTANT long MAGENTA = 16711935
CONSTANT long DARKMAGENTA = 8388736
CONSTANT long BROWN = 8388736
CONSTANT long CYAN = 16776960
CONSTANT long YELLOW = 65535
CONSTANT long PALEYELLOW = 1226487
CONSTANT long WINDOWBACKGROUND =
1090519039
CONSTANT long BUTTONFACE = 79741120
CONSTANT long WINDOWTEXT = 33554432
CONSTANT long APPWORKSPACE = 276856960
Values
for the upper color bits
2^25 - Window Text
2^26 - buttonface
2^27 - scrollbar background
2^28 - app. wrokspace
2^29
- transparent
2^30 - Window Background
2^31 - unused
2^32 - unused
string
ls_cmd, ls_arg[]
integer
i, li_argcnt
//
Get arguments and strip blanks from start and end of string
ls_cmd = Trim( commandParm () )
li_argcnt
= 1
DO
WHILE Len(ls_cmd ) > 0
// Find first blank
i =Pos( ls_cmd, " " )
// If no blanks (only one argument),
set i to point to the hypothetical character after end of string
if i =0 then i =Len(ls_cmd) + 1
// Assign the arg to the
arg array.No. of chars copied is one less than position of the space found with
Pos
ls_arg[li_argcnt] =Left( ls_cmd, i - 1
)
// Increment the argument count for
the next loop
li_argcnt = li_argcnt + 1
// Remove the argument from the string so the next argument
becomes first
ls_cmd =Replace( ls_cmd, 1, i,
"" )
LOOP
CONNECTING TO MULTIPLE DATABASES
//
enable transaction registration (the registration service is need when using
more than one database)
gnv_app.of_SetTrRegistration(TRUE)
//
register SQLCA (the connection to the first database which was connect to the
usual way)
gnv_app.inv_trregistration.of_Register(SQLCA)
//
connect to and register ABRN_MRS database (the second database)
//
create 2nd transaction object; n_tr gtr2 must be declared global
gtr2
= CREATE n_tr
//
copy connection info from the first database called SQLCA to the second
database
//
called gtr2 - it copies the user id, password, database name, server name, etc.
from
//
the definition of the first database connection to the definition of the second
database connection
il_return
= SQLCA.of_CopyTo(gtr2)
//
re-assign the database name to the second definition
gtr2.Database
= "your_2nd_database_name"
//
re-assign the server name to the second definition - if it's different
gtr2.ServerName
= "your_2nd_server_name"
//
connect to the second database
ll_return
= gtr2.of_Connect()
If
ll_return <> 0 then MessageBox("Error", "Unable to
connect.")
//
register the second database with the registration service
gnv_app.inv_trregistration.of_Register(gtr2)
Now
whenever you want to retrieve data from the 2nd database, you would write in
the window's open event
li_return = dw_1.of_SetTransObject(gtr2)
dw_1.retrieve()
There is an undocumented way to get to a lot of DDDW / DDLB events. Whenever an event occurs in the
datawindowchild it sends a notification code to the parent DW. This code can be intercepted in the user
event mapped to pbm_command datawindow event. If you want to experiment to determine which events
you can
intercept, try adding the code below to ue_command mapped to pbm_command:
mle_status.text
+= "hwndchild = " + String(hwndchild) + ", " +
"childid = " + String(childid) + ", " + &
"notificationcode
= " + String(notificationcode) + "~r~n"
The
code needed to intercept the dropdown arrow in the ddlb is:
int
li_rc
li_rc
= this.GetChild("ddlbtest", ldwc_ddlb)
IF
childid = Handle(ldwc_ddlb) THEN
CHOOSE CASE notificationcode
CASE 1
Post Event ue_DDLBRowFocusChanged()
END CHOOSE
END
IF
Other
events:
Event ActionID
from WordParm
Clicked 1281
RowFocusChanged 2048,
2049
RightMouseButtonDown 2314
Left Button Up 2313
Retrieve End 769
MouseMove 2311
To use the Drop Down Calendar or the Drop Down Calculator with the editmask style column you will need to use
the
"NONE" style service option.
1.
Create a computed field with a bitmap() expression to the right of the
datawindow column:
BitMap("calendar.bmp")
where "calendar.bmp" may be a small calendar or a drop down arrow. Give the computed field a name;
say "ship_date_arrow".
2.
Enable the DDCalendar service with the "NONE" option:
This.of_SetDropDownCalendar(TRUE)
This.iuo_calendar.of_SetInitialValue(FALSE)
This.iuo_calendar.of_SetAlwaysRedraw(FALSE)
This.iuo_calendar.of_SetCloseOnClick(TRUE)
This.iuo_calendar.of_SetCloseOnDClick(TRUE)
This.iuo_calendar.of_Register("ship_date",iuo_calendar.NONE)
3.
Add code to the DW clicked event to drop the Calendar:
IF dwo.name = "ship_date_arrow"
THEN
IF IsValid(iuo_calendar) THEN
this.SetColumn("ship_date")
this.event pfc_ddcalendar()
END IF
END IF
5.X
It is mandatory to have the deployment kit on your client machine. It doesn't matter if you are building machine code or
p-code executable. In either case you need deployment kit. But you may reduce the number of DLLs to be deployed
depending on what features you used in your application. Following gives the list of DLLs which are optional. For
more information
see Powersoft
Document 4427.
All
Platforms
pbbgr050.dll Business graph engine
pbdwe050.dll DW engine
pbrte050.dll Runtime engine
pbrtf050.dll Runtime functions
pbshr050.dll Stg mgr, dec, print, ...
pbtyp050.dll System object/function definitions
pbitxt50.dll DW
Import text (optional)
Win16,
Win32
pbroi050.dll OLE 2 support
pbtra050.dll Database interface - trace of any database
pbdbl050.dll Database interface - msg handler for pbsyb,
pbmdi, pbnet (optional)
pbdbt050.dll Database interface - msg handler for pbsyc
(optional)
pbdpb050.dll Dist PB - local driver (optional)
pbdse050.dll Distributed PB (optional)
pbidbf50.dll DW Import Dbase (optional)
pbin5050.dll Database interface - Informix 5.0
(optional)
pbmdi050.dll Database interface - MDI (optional)
pbmss050.dll
Database interface - MS SQL Server 6.0 (optional)
pbo71050.dll Database interface - Oracle 7.1 (optional)
pbodb050.dll Database interface - ODBC (optional)
pbor7050.dll Database interface - Oracle 7.0 (optional)
pborc050.dll ORCA
(optional)
pbosc050.dll Dist PB - open server client (optional)
pbrtc050.dll Rich text support (optional)
pbsmi050.dll Dist. PB (optional)
pbsyb050.dll Database interface - Sybase dblib interface
(Microsoft lib linked) (optional)
pbsyc050.dll
Database interface - Sybase ctlib
interface (optional)
pbwsc050.dll Dist PB - winsock client (optional)
Win32
pbwss050.dll Dist PB - winsock server (optional)
pbnpc050.dll Dist PB - named pipe client (optional)
pbnps050.dll Dist PB - named pipe server (optional)
pbo72050.dll Database interface - Oracle 7.2 (optional)
pboss050.dll Dist PB - open server server (optional)
pbsyt050.dll Database interface - Sybase dblib
interface (Sybase lib linked) (optional)
PFCCOM32.DLL
required for PFC apps
Win16
pboui050.dll OLE 2 user interface
pbvbx050.dll VBX
pbibm050.dll Database interface - IBM (optional)
pbnet050.dll Database interface - net gateway (optional)
And!
-- PFCCOMM.DLL, PFCFLSRV.DLL
6.5
pbdwe60.dll datawindow engine
pbmss60.dll