Home
What's New
Dev Tools
Services
Feedback
Site Map

---------------------------------------------------------- back to tips menu

Details of PFC Tips

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:

  1. The user will be prompted to save outstanding changes.
  2. Some further logic might execute after the window closes causes a serious application error.

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


Copyright © Woodger Computing Inc.