
---------------------------------------------------------- back to tips menu
PFC Tip 1: Making PFC Help Easily Accessible
To make the PFC Help easily accessible, customize the PowerBuilder Toolbar, as follows:
On PowerBuilder toolbar, choose right-mouse, "Customize..."
Choose "Custom Toolbar" radio button
Select a toolbar icon (to represent PFC Help) from top list and drag it to bottom list.
Specify the following toolbar details:
Command Line: WINHELP C:\PWRS\PB5\SYS\PBPFC050.HLP
or WINHELP C:\PROGRAM FILES\PB6\HELP\PBPFC060.HLP
Item Text: PFC Help
Item MicroHelp: Invoke PFC Help
PFC Tip 2: Message Handling in a PFC DataWindow
A general purpose DataWindow message function can provide two important capabilities:
The function called f_Message can be placed on u_dw. The function provides the above capabilities and it calls the standard PFC Error message function to actually display the error message.
Function: f_Message
Purpose: If the ParentWindow isn't closing, the function sets focus to the current DW
and displays the specified message.
Parameters: in - as_MsgId: Message Id of message to display
in - as_MsgParms: array of message parms for message.
Returns: Integer
>0: button selected for the message
0: message not displayed since window is in close process.
-1: error occurred.
integer li_Return = 1
boolean lb_DisplayMsg = True
// Determine if parent window is in the process of closing (i.e. in CloseQuery)
IF NOT IsNull(iw_ParentWin) THEN
IF iw_ParentWin.of_GetCloseStatus() THEN
lb_DisplayMsg = False
END IF
END IF
// If the window is NOT closing, then proceed with display of message
IF lb_DisplayMsg THEN
// first set focus to Window, DW and Tabpage
iw_ParentWin.ShowWindow() // see function in general tips
This.f_MakeTabPageCurrent() // see function in general tips
This.SetFocus()
li_Return = gnv_app.inv_error.of_message(as_MsgId, as_MsgParms)
ELSE
li_Return = 0
END IF
Return li_Return
Notes:
PFC Tip 3: Replacement for pfc_u_tv's of_FindItem
The following function was written to stand in place for pfc_u_tv's of_FindItem function. At least in 16-bit environments (not sure of 32-bit), PFC's of_FindItem gets a stack overflow and GPFs when it has to search more than 50 tree items. This function avoids the problem by searching the tree items in a loop instead of recursively. The parameters are the same as of_FindItem, except the parameter "ai_Level" is replaced by "ab_AllDescendants" -- I found the parameter switch made the function easier to use.
Function: f_FindChild
Purpose: Searches a TreeView Item's immediate children (or all its descendants)
for the target value. In trying to match, it checks either the Label
or Data attribute on each child TreeView item. Only expanded TreeView
items are searched.
Parameters:
in - as_Attribute The attribute of the TreeView item to search ("Label",
or "Data")
in - aa_Target A variable of type Any containg the search target.
in - al_Begin The handle of the TreeView item to begin searching, if
0 entire tree will be searched.
in - ab_AllDescendants True indicates all descendants to be searched (False for only
immediate children).
in - ab_RespectCase True - search is case sensitive,
False - search is not case sensitive. Only used if the
target is a string.
in - ab_FullCompare True - Label or Data and Target must be equal
False - Label or Data can contain Target (uses POS() function).
Only used if the target is a string.
Returns: Long
>0: the handle of the item whose Label or Data matches the target
0: item not found
-1: a serious error occurred
String ls_Label, ls_Target
Integer li_Level, li_ChildLevel
Long ll_Handle, ll_Found, ll_Parent
Long ll_MatchingItem = 0
TreeViewItem ltvi_Item
// Get the first expanded child of the starting point
ll_Handle = f_GetFirstExpandedChild(al_Begin)
// Save the level for the child
IF ll_Handle > 0 THEN
IF This.GetItem(ll_Handle, ltvi_Item) = -1 Then Return -1
li_ChildLevel = ltvi_Item.Level
li_level = ltvi_Item.Level
END IF
// Checking for this item and stop when we get to the level higher than
// we're looking
DO WHILE ll_Handle > 0 AND ll_MatchingItem = 0 AND li_level >= li_ChildLevel
// only do comparison if we're at the correct level (i.e. immediate child
// or checking all levels)
IF li_Level = li_ChildLevel OR ab_AllDescendants THEN
// Check if this item matches using pfc_u_tv function
IF Trigger Event pfc_searchcompare(ll_Handle, as_Attribute, aa_Target, &
ab_RespectCase, ab_FullCompare) Then
ll_MatchingItem = ll_Handle
END IF
END IF
// Get the next Tree Item, going deeper into tree if the caller requested it
IF ab_AllDescendants THEN
ll_Handle = FindItem(NextVisibleTreeItem!, ll_Handle)
ELSE
ll_Handle = FindItem(NextTreeItem!, ll_Handle)
END IF
IF ll_Handle > 0 THEN
IF This.GetItem(ll_Handle, ltvi_Item) = -1 Then Return -1
li_level = ltvi_Item.Level
END IF
LOOP
Return ll_MatchingItem
This supporting function gets the first expanded child for a specified TreeView item, if any.
Function: GetFirstExpandedChild (supports f_FindChild)
Long ll_Handle
TreeViewItem ltvi_Item
// if whole tree is being searched, start looking from the first tree item
IF al_Parent = 0 THEN
ll_Handle = FindItem(RootTreeItem!, 0)
ELSE
IF This.GetItem(al_Parent, ltvi_Item) = -1 Then Return -1 // error getting TVI
// If the specified tree item is not expanded, it will have no expanded children
IF ltvi_Item.Expanded = False THEN
ll_Handle = 0 // return not found
ELSE
// it's expanded, so get handle to first child
ll_Handle = FindItem(ChildTreeItem!, al_Parent)
END IF
END IF
Return ll_Handle
PFC Tip 4: CloseQuery Fix
One problem with PFC's CloseQuery logic is that it doesn't set focus to the Window before displaying an error message. Since the window focus is not changed, the user could easily give an incorrect response to a save confirmation message. Scenario: the user makes changes to Window A (without saving these changes), then the user opens Window B. If the user tried to close the application while on Window B, the user would be prompted to save Window A but the Window B would be showing in the background.
To fix the problem, you need to copy the PFC CloseQuery logic and then place a call to f_ShowWindow() in two places: once just above where PFC displays the pfc_closequery_failsvalidation message and again just above where PFC displays the pfc_closequery_savechanges message. f_ShowWindow() is described in the general PowerBuilder tips.
PFC Tip 5: String-to-DateTime Conversion Function
This function takes a string and, if the value provided is a valid DateTime, it returns a valid DateTime variable. If it is invalid, it returns Null (so it can easily be tested for validity). An underlying PFC support function is used to implement the logic.
Function: f_DateTime
Parmeters: in - as_datetime: Datetime value as a string
Returns: datetime, if input is valid and Null otherwise.
DateTime ldtm_rc
Time ltm_Time
long ll_count
string ls_datetime[]
boolean lb_BadDateTime = False
n_cst_string lnv_string
// Check arguments
IF IsNull (as_datetime) THEN
lb_BadDateTime = True
ELSE
// Validate datetime string
ll_count = lnv_string.of_ParseToArray (as_datetime, " ", ls_datetime)
IF ll_count <= 0 or ll_count > 2 THEN
lb_BadDateTime = True
END IF
END IF
// Now try to convert
IF NOT lb_BadDateTime THEN
// Date string passed in
IF ll_count = 1 THEN
IF IsDate(as_datetime) THEN
ltm_Time = Time('00') // no time so default to 0:00
ldtm_rc = DateTime(Date(as_datetime), ltm_Time)
ELSE
lb_BadDateTime = True
END IF
// Datetime string passed in
ELSEIF ll_count = 2 THEN
IF IsDate(ls_datetime[1]) AND IsTime(ls_datetime[2]) THEN
ldtm_rc = DateTime(Date(ls_datetime[1]), Time(ls_datetime[2]))
ELSE
lb_BadDateTime = True
END IF
END IF
END IF
// set return code when bad date time found
IF lb_BadDateTime THEN
SetNull(ldtm_rc)
END IF
Return ldtm_rc
PFC Tip 6: Shutdown Window with no Prompts
When a serious error is encountered, it is sometimes necessary to close the window.
Unless you
are careful, two problems can occur when closing the window:
The window function f_Shutdown() avoids the two problems and it is easy for developers to call.
Function: f_ShutdownWindow
Parameters: ab_DisplayMessage: indicates if a window closing message
should be displayed.
string ls_MsgId
// display standard message, if caller wants one
IF ab_DisplayMessage THEN
// display message
gnv_app.inv_error.of_Message("sl_syserr_windowclosing")
END IF
// Stop PFC from prompting to save and then close the window
ib_DisableCloseQuery = True
This.Post pfc_close // close is posted so that scripts complete first
---------------------------------------------------------- back to tips menu