Professional PB Utilities

PowerGraph PowerGraphs Toolkit - Build 2D graphs not supported by PowerBuilder, including multi axes graphs, proportional time scale graphs, overlapped graphs, graph legends with any size, font and palcement, custom graph colors and labels and much more...
PowerDrop PowerDrops Toolkit - Make datawindow drop-down boxes from virtually any object, don't be limited to drop-down datawindows and list-boxes only. PowerDrops Toolkit is the only tool that provides guaranteed, precise positioning of the drop-down objects, regardless of a datawindow style, number of rows, levels of parent objects, etc.
PowerUndo PowerUndo Toolkit - Word-processor style multi-level undo/redo in any datawindow!
Win2BMP Window-To-Bitmap - Save graphs, datawindows and other objects programmatically in standard BMP files, then print, email, fax them as graphics.

 PB Tips, Scripts and Utilities

Table of Contents

  1. Secrets of ListView, PictureListBox, DropDownPictureListBox, TreeView, and Application Icon
  2. KGB Spy
  3. DataWindow property sheet: General tab
  4. DYNAMIC Function Call
  5. Secrets of DataWindows - CPU and other global functions
  6. Secrets of DataWindows - Timer Event
  7. Overriding System Functions
  8. Secrets of Menus - Animated Toolbar Icons
  9. Secrets of Environment Object
  10. DataWindow Row Selection Color
  11. Secrets of DataStore Implementation
  12. DataStore vs. DataWindow Performance Tests
  13. Secrets of DataWindow - Minimizing DataWindow Control
  14. Secrets of PowerBuilder Resource Files (PBR)
  15. PowerBuilder Dates and Y2000 Compliance
  16. Secrets of Menus - Toolbar Icon Tip and Text
  17. Secrets of Table Painter - Open Table Dialog
  18. Secrets of Menus - Dynamically Adding New Menu Items
  19. Most Simple Method To Count TreeView Items
  20. Secrets of PowerBuilder Executables
  21. Secrets of GetChild( )
  22. DataWindow Repair Utility
  23. DBMS/DataWindow Column Dependencies
  24. Response Window With Menu
  25. MDI Frame Without Menu and Toolbar
  26. Secrets of Dynamic DataWindows
  27. Custom Toolbars - This is Really Simple
  28. Asynchronous Processing in PowerBuilder (submitted by Michael Mwamunga)
  29. Export DataWindow to Excel including computed columns, headers, footers, groups, text label, etc... ( no kidding, it's simple!)
  30. Another Toolbar tip
  31. Exchange information between two PB application (submitted by Jose Manuel Navarro)
  32. SQL Exceptions handling (submitted by Jose Manuel Navarro)
  33. isValid ?
  34. Huge Windows API library containing functions, structures, contstants (submited by Santiago Ciappesoni)
  35. Accessing TopSpeed Databases (submitted by Michael Mwamunga)

  Secrets of ListView, PictureListBox, DropDownPictureListBox, TreeView, and Application Icon

Undocumented PowerBuilder: The following constants of enumerated data type may be used as Picture Names in any ListView, PictureListBox, DropDownPictureListBox, TreeView as well as Icon Name in the Application object properties:


For instance, some constants mentioned above can be used in a custom MessageBox window instead of bitmaps. Moreover, they can be changed dynamically from the script. Note that the images are consistent with the Operation System and have different look under Windows 3.1 and Windows 95/Windows NT. They look exactly like the images in the system MessageBox. To implement a custom MessageBox:

  1. Create a response window with the ListView control.
  2. Launch the control's properties dialog, then enter the desired icon name in the Picture Name list on the Large Picture tab. You can type in any picture name from the Stock Pictures or type in any of the enumerated constants from the list given earlier, even if the pictures are not represented in the Stock Pictures box. After that, switch to the Item tab and enter one item in the Item list. Switch to the General tab and deselect the "Enabled" and "Scrolling"; select "None" for Border; select Background Color same as the window color. Close the properties dialog window.
  3. Resize the ListView control so that it fits only the picture.
  4. Place MultiLineEdit control on the window for custom message text. Place and code the desired MessageBox buttons; complete other customizations and coding.

  If you think your application features perfect bulletproof security system then try it with the "KGB Spy".

Using KGB Spy you can "click" disabled and hidden buttons and controls. Check for yourself. 

Here you can download KGB Spy. Use this program to test your security. To run KGB Spy you will need PowerBuilder 6 deployment kit.

KGB Spy source code can be dowloaded here.


  DataWindow property sheet: General tab.

Undocumented PowerBuilder: On-line help says: "DataWindow property sheet, General tab, DataWindow Object Name - The name of the DataWindow object you want to embed in the Window."
However, you can also specify the name of PSR file you want to embed in the Window. You cannot use the Browse button to paste the PSR file name, but you can type it in or paste the name from the Clipboard. For example: when your DataWindow control always displays REPORT.PSR file, which your program dynamically creates, you do not have to code this DataWindow control for attaching the PSR file in run-time.

 DYNAMIC Function Call.

On-line help says: "When you specify a dynamic call, the function or event does not have to exist when you compile the code. You are saying to the compiler: trust me - there will be a suitable function or event available at execution time."
There are also the situations when the functions do exist in compile time, but you cannot call them directly because of the compiler's "Function not found" (actually "type mismatch") error. Using the DYNAMIC function call often allows significant reduction of the code logic branching. Consider the following example:

// PowerBuilder old style //

global function boolean f_zoom_out( powerobject apo_target )

DataWindow ldw_target
DataWindowChild ldwc_target
DataStore lds_target

CHOOSE CASE TypeOf( apo_target )
    CASE DataWindow!
         ldw_target = apo_target
   CASE DataWindowChild!
       ldwc_target = apo_target
   CASE DataStore!
       lds_target = apo_target
     // invalid argument type
      RETURN False


In PowerBuilder 5 and 6 you may use a more efficient and elegant code:

// PowerBuilder 5&6 new style //

global function boolean f_zoom_out( powerobject apo_target )
RETURN (apo_target.DYNAMIC Modify('DataWindow.Zoom=90') = '')

You may apply this technique for other objects and functions as well. However, in PowerBuilder 5 some very important functions such as Describe cannot be called dynamically due to the compiler limitations.

 Secrets of DataWindows - CPU and other global functions.

Undocumented PowerBuilder:DataWindow Painter provides the incomplete list of functions that may be used in the DataWindow expressions. For instance, you can use the CPU( ) function in DataWindow Painter expressions even if it is not listed in the "Modify Expression: Functions list box."

This function might be useful when dealing with fractions of a second in a DataWindow. Perhaps you want to have some animation in the DataWindow and build an expression using Bitmap( ) function. Such an expression can tell PowerBuilder how to change the bitmap without intervention from outside of the DataWindow. Therefore, you may want to code the following expression:

Bitmap(CASE( mod( cpu(), 200 )
  WHEN IS <= 50 THEN 'file1.bmp'
  WHEN IS <= 100 THEN 'file2.bmp'
  WHEN IS <= 150 THEN 'file3.bmp'
  ELSE 'file4.bmp') )

Now if you set the "Timer Interval" property for the DataWindow object to 50 milliseconds, PowerBuilder will loop through file 1 to 4 and simulate the animated picture. Note that you also need to create at least one expression that uses Today() function otherwise PowerBuilder will ignore "Timer Interval". If you do not want this expression appearing on the screen then set its visible property to 0.

When evaluating DataWindow expressions, PowerBuilder performs up to three lookups for the functions called in the expression. First, it checks DataWindow Painter's specific functions. Second, it checks user-defined global functions. Finally, it checks global system functions. This is why you can call many system functions in the DataWindow expressions including the CPU ( ). Moreover, knowing this, you can create some kind of macro language in PowerBuilder, which does not have to be compiled yet and can be executed in run-time. For instance, the following command will display a MessageBox:

string ls_command

// ... some file operations to read a command from the script file. Perhaps it is
// MessageBox ("Dynamic Message", "Hello World")

dw_1.Describe("Evaluate(' " + ls_command + " ', 1)")

Keep in mind that any DataWindow expression must return one of the following data types:

  • Double
  • String
  • DateTime
  • Time

Within an expression, a function can return other data types (such as boolean, date, or integer) but the final value of an expression is converted to one of the four data types above.

Click here to download tiny sample application that utilizes CPU( ) function to simulate a screen saver.


 Secrets of DataWindows - Timer Event.

Undocumented PowerBuilder:In the DataWindow control, declare the Timer event mapped to the PowerBuilder PBM_TIMER event. Your initial impression is that nothing new will happen. However, if you set the "Timer Interval" property (see Properties: General tab page) to any non-zero value in the attached DataWindow object, you will find out that PowerBuilder now fires the timer event for the DataWindow control. Note that PowerBuilder starts DataWindow timer only if the attached DataWindow has at least one expression that calls Today( ) or Now( ) functions. Also, note that the value for the "Timer Interval" must be specified in milliseconds rather than in seconds, as it is in the Timer() Powerscript function. Now code this new timer event and PowerBuilder will take care of it. This method allows having the timer event in the DataWindow without declaring and calling external functions, and this works both under 16-bit and 32-bit Windows.

 Overriding System Functions.

Perhaps some time ago you have developed a nice, user-friendly PowerBuilder application. Today your boss is asking you to update this application and make it even more friendlier by programming it to beep before displaying a MessageBox, e.g using sounf effects for informing operators that a certain error occured.

What to do? One solution is to change tons of existing scripts and inserting Beep(1) before the MessageBox ( ) call. Another solution is to override the system MessageBox ( ) by creating user-defined global function with the same name. As an experienced programmer you should ask: "But how can I call the system function from this one? If I call MessageBox( ) from this function, PowerBuilder will recursively call this function again and again and it will go to an endless loop until Stack overflow error occurs." Following is the technique you can use to call the system function and avoid the endless loop:

global function integer messagebox (readonly string as_title, readonly string as_message)
systemfunctions lsf_PB
integer li_rc

lsf_PB = CREATE systemfunctions
li_rc = lsf_PB.MessageBox(as_title, as_message)

RETURN li_rc

You may need to overload this function for the all argument types you use. If you plan to override several system functions, consider declaring a global variable of the SystemFunctions type, which you can create on the Open event of your application object and destroy on its Close event.

Warning: The described method for overriding system functions works fine in PowerBuilder 5 only. Unfortunately, it causes run-time errors in PowerBuilder 6 and does not event compile in later versions.

 Secrets of Menus - Animated Toolbar Icons.

Undocumented PowerBuilder: To simplify GUI development PowerBuilder, provides two events for each menu item: Selected and Clicked. Remember that menu level events are not native to Windows and they are generated and fired by PowerBuilder. Indeed, Windows sends all messages to the window that owns the menu and then PowerBuilder in turn dispatches and forwards messages to the appropriate menu items.

On-line help says: "Selected event occurs when the user highlights an item on the menu using the arrow keys or the mouse, without choosing it to be executed." However, this event also occurs when the user places the mouse pointer over a toolbar icon for a moment and PowerBuilder displays the icon's ToolbarTip (PowerBuilder uses the toolbar text attribute for the ToolbarTip). This feature allows us to code the Selected event so that when it is fired we can change the Toolbar Icon for the appropriate menu item then restore original picture when the icon loses focus. The trick is to distinguish whether the event is triggered when the user highlights the menu item or whether PowerBuilder triggers this event before the ToolbarTip appears.

You will need to do the following:

  1. Declare the menu level instance variable
    menu im_last_selected
  2. Declare 2 menu level functions:
    public subroutine mf_select (menu am_menuitem)
    public subroutine mf_unselect()
  3. For each menu item that has a toolbar icon, code mf_select(this) in the item Selected event.
  4. Make sure each menu item that features a toolbar icon gets one icon for the Toolbar Picture Name and another for the Toolbar Down Picture Name. These icons should be slightly different so that the user will see the animation effect.

In the parent window or in the common window ancestor, declare the new user event WM_MENUSELECT mapping PBM_MENUSELECT; then code in this event:
    if Handle(this.MenuID) = hmenu then this.MenuID.DYNAMIC mf_unselect()

Following are codes for the functions menthoined above:

public subroutine mf_unselect ()

if isValid(im_last_selected) then
    if im_last_selected.tag <> "" then
        im_last_selected.ToolBarItemName = im_last_selected.tag
    end if
end if

public subroutine mf_select (menu am_menuitem)

// First, find out what caused Selected event: the menu item selection or the toolbar item tip
uint lui_flags, MF_HILITE = 128

lui_flags = IntHigh(Message.WordParm)

// because PB does not support Bitwise operations like lui_flags = lui_flags AND MF_HILITE
// we have to use different method to check the highlight bit

lui_flags -= mod(lui_flags, MF_HILITE)
if mod(lui_flags, MF_HILITE * 2) > 0 then return // menu item text is selected

if am_menuitem.ToolBarItemDown then return // ignore icons, which are displayed down

if am_menuitem.tag = "" then
    am_menuitem.tag = am_menuitem.ToolBarItemName
end if

im_last_selected = am_menuitem
am_menuitem.ToolBarItemName = am_menuitem.ToolBarItemDownName

Note that in this example a menu item tag is used for temporarily storing the item's Picture Name. If your application is already using menu item tags, you will need to declare another menu level instance variable, which you will use instead.


Click here to download tiny sample PB 6 application that features animated Toolbar Icons. Download

 Secrets of Environment Object

Undocumented PowerBuilder: An environment Object in PowerBuilder 6 has the new undocumented property Language of enumerated type LanguageID. This makes it very useful for multi-language applications. For a list of available IDs launch PowerBuilder Object Browser, then select Enumerated tab; after that, find and highlight LanguageID type in the left pane then expand its properties in the right pane.

 DataWindow Row Selection Color

Undocumented PowerBuilder: As you know standard PowerBuilder function SelectRow(long Row, boolean State) can be used to highlight rows in a DataWindow. Before PowerBuilder highlights the row, it calls Windows API to retrieve system-defined color for an active selection.

If you want to know which color will be used for selected rows, you can call the GetSysColor function from Windows API. Following is a the required declaration for this external function:

.// The GetSysColor function retrieves the current color of the specified display
// element. For "Active Selection" use COLOR_HIGHLIGHT = 13

FUNCTION long GetSysColor(long color_element) LIBRARY "user32"

For 16-bit environments, change the type of color_element argument to integer and library name to "user." Pass 13 as a color_element to get row selection color.

By the way, some PowerBuilder functions like SelectRow ( ) successfully accept invalid row numbers. For instance, SelectRow( -1, TRUE) acts as SelectRow( 0, TRUE) and, therefore, successfully deselects all selected rows.

 Secrets of DataStore Implementation

PowerBuilder Internals: On-line help says: "A DataStore is a non-visual DataWindow control. DataStores act just like DataWindow controls except that many of the visual properties associated with DataWindow controls do not apply to DataStores. However, because you can print DataStores, PowerBuilder provides some events and functions for DataStores that pertain to the visual presentation of the data. " I wonder why everything else in the PowerBuilder documentation except this paragraph says that a DataStore is a non-visual object when it is really a hidden DataWindow control. Let's prove that a DataStore is a regular DataWindow control implemented as a top-level hidden popup window. Two external functions are needed for unhiding DataStores.

FUNCTION boolean SetWindowPos( &
    long hwnd, /* handle of window */
    long hWndInsertAfter, /* placement-order handle */
    int x, /* horizontal position */
    int y, /* vertical position */
    int cx, /* width */
    int cy, /* height */
    uint uFlag /* window-positioning flags */ ) LIBRARY "user32"

FUNCTION ulong FindWindowA(REF string class, REF string name) LIBRARY "user32"

We will use SetWindowPos function to show and resize the DataStore window, which is hidden and initially has zero size. Because the PowerBuilder compiler mostly treats DataStore as a pure non-visual object, it protects us from getting the handle of DataStore directly. That is why we will use FindWindowA function to find a DataStore window. For simplicity, we will call this function only once. This function will return the handle of the first found DataStore. The Following script demonstrates how to unhide a DataStore. Note that different PowerBuilder versions use different names of window classes for windows created within PowerBuilder. In PowerBuilder 5 a DataStore as well as a DataWindow class is PBDW050, in PowerBuilder 6 it is PBDW60.

ulong ll_handle
string ls_class, ls_title
DataStore lds_test

ls_class = "PBDW050" // PBDW60 for PB6

// create test DataStore
lds_test = CREATE datastore
lds_test.DataObject = "d_test"

// Get DataStore handle
ll_handle = FindWindowA(ls_class, ls_title)

IF ll_handle = 0 THEN
   MessageBox("Warning", "Not found!", Exclamation!)

// unhide and resize
SetWindowPos(ll_handle, 0, 0, 0, 300, 300, 64)
MessageBox("DataStore", "Now you can see non-visual datastore!", Exclamation!)
DESTROY lds_test

If you will examine PowerBuilder 5 DataStores, you can even make them editable. How is that, huh?

You can also use Windows SPY programs to search DataStores. A SPY program is usually a standard part of any C++ compiler package. You can find one that is included in Watcom C++ Class Builder that comes with PowerBuilder Enterprise.

You can easily convert a DataStore window to a regular DataWindow control by calling the SetParent function from Windows API . For details, please see Windows API documentation.

There are several improvements made in PowerBuilder 6 DataStores compared to the previous version. One of them is disabling DataStore painting (or should I say DataWindow painting?), which greatly improves performance, especially when doing multiple data manipulations in a DataStore.

I wonder why the DataWindow control is not inherited from the DataStore, which would be logical and would significantly improve the performance of thousands of PowerBuilder developers by eliminating unnecessary code duplication when programming DataWindow and DataStore services.

 Secrets of DataWindow - Minimizing DataWindow Control

Undocumented PowerBuilder: As you know a DataWindow control may have a title bar with minimize and maximize boxes and a control box (an icon in Windows 95) with the control menu. As opposed to normal windows, when the user minimizes a DataWindow control it completely disappears instead of displaying an icon that represents the minimized DataWindow. Well, not really. PowerBuilder traps the Resize event and hides the DataWindow. It also happens when the user closes DataWindow using its control menu. To unhide the DataWindow control, simply restore the control's visibility attribute.

my_dw.visible = True

 Secrets of PowerBuilder Resource Files (PBR)

Undocumented PowerBuilder: Unfortunately, the documentation provided with PowerBuilder does not list all the resources supported by PowerBuilder. There is no exact definition of the resource term. In most places we can see definitions like this one: "Resource File Name - Specify a PowerBuilder resource file for the dynamic library if it uses resources, such as bitmaps and icons, and you want the resources included in the dynamic library." As far as I know, a resource file may contain names of graphic files (BMP, RLE, WMF, CUR, ICO, etc.) and names of dynamically referenced objects (UserObject, Window, Menu and DataWindow). You do not need to include names of dynamically referenced objects if you are going to compile dynamic libraries (no matter PBDs or DLLs) and these objects are compiled into PBD/DLL. But you do need to include them if you compile just a single EXE. The format for specifying an object in the resource file is MYLIBRARY.PBL (MYOBJECT). For example: REPORTS.PBL (W_CASH_BALANCE). The name of the resource is not case sensitive.

 PowerBuilder Dates and Y2000 Compliance

Many corporations are currently certifying products as Y2K compliant. In PowerBuilder, when saving DataWindow data in text files, we often deal with short date formats that include a 2-digit year. However, there is a way to change the format so that the date is saved using a 4-digit year. PowerBuilder looks in the system registry for the format for Date. Changing the format for Date requires changing the Registry setting for the sShortDate value under HKEY_CURRENT_USER\Control Panel\International. There you can find short Time format as well. To make PowerBuilder use a 4-digit year, you just need to change sShortDate value to whatever you want then save DataWindow contents and restore the old format. You can use standard PowerBuilder registry functions to perform this task programmatically.

 Secrets of Menus - Toolbar Icon Tip and Text

Undocumented PowerBuilder: On-line help provides the following definition for the ToolbarItemText property of the menu item: "ToolbarItemText - Specifies the text that displays in the toolbar item when the display text option is on for toolbars." As you know, PowerBuilder also uses this property for the toolbar icon tips. How many times have you wanted to make the text long for the tip and short for the icon? Here is an extremely simple but undocumented way to do that: In the Toolbar Text property, specify different text, separated by comma, for the icon and the tip. For example: "Excel,Save report in MS Excel format.

 Secrets of Table Painter - Open Table Dialog

Undocumented PowerBuilder: To quickly locate the desired table in the Select Table dialog box just start typing its name and PowerBuilder will scroll the list box to the nearest match. This undocumented feature is very useful when your list of database tables is really long.

Secrets of Menus - Dynamically Adding New Menu Items

Undocumented PowerBuilder: The menu Item[] property is not fixed array as many of you think. Nothing can stop you from adding the new elements to this array. The trick is to force PowerBuilder to redraw updated menu properly. The following example demonstrate how to do this.

  1. Create new window with any existing menu attached to it.
  2. Place a new button on the window
  3. Code Clicked event for the button:
    MenuID.Item[UpperBound(MenuID.Item[]) + 1] = CREATE menu
    MenuID.Item[UpperBound(MenuID.Item[])].text = "&New Menu Item"
    MenuID.Item[UpperBound(MenuID.Item[])].ToolBarItemName = "Save!"
    MenuID.Item[UpperBound(MenuID.Item[])].ToolBarItemVisible = True
    // force PB to redraw menu with the new item added
  4. Run the new window and click on the button one or more times

 Most Simple Method To Count TreeView Items

Use the following code to quickly count items in the TreeView control:
     li_count = Send(handle(treeview_control), 4357, 0, 0)

To find out how many items can be fully visible in the TreeView control visible area use the following script:
     li_count = Send(handle(treeview_control), 4368, 0, 0)

 Secrets of PowerBuilder Executables

Do you know that any program you create in PowerBuilder is property of Sybase, Inc. No kidding, it is not yours as you might think. Here is the proof:

  1. Open Windows Explorer.
  2. Locate your EXE and right-click on it.
  3. Choose Properties menu then jump to the Version property page. Click here to see a sample.
  4. Check the Company name and Copyright notice. Make sure to click on the Copyright notice then scroll it to right.

If you fill strong that your work belongs to you, not to Sybase, Inc. use Resource Editor from any C++ package to correct EXE header. Unfortunately you have to do this each time you have a new executable compiled. By the way, you probably know that in any other programming system (take VisualBasic for instance) users can customize their EXE headers (usually via project properties) so that the correct information gets compiled into EXE.

 Secrets of GetChild( )

Undocumented PowerBuilder: On-line help provides the following definition for the GetChild ( ) function:
Provides a reference to a child DataWindow or to a report in a composite DataWindow, which you can use in DataWindow functions to manipulate that DataWindow or report.A child DataWindow is a DropDownDataWindow in a DataWindow object. A report is a DataWindow that is part of a composite DataWindow.

According to the definition above, a call to GetChild ( ) for the nested report that is part of a tabular DataWindow fails and the function returns -1. So there is no way you can get a reference to the nested DataWindow that is part of a non-composite DataWindow. Well, not really. Just remember that all DataWindow presentation styles are equal, except "Grid". Therefore, the work-around for this GetChild ( ) issue is the following:

  1. Export your "Tabular", "Free form", "Graph" ( or whatever ) style DataWindow.
  2. In the third line of the export file change "processing=0" (or whatever) to "processing=5".
  3. Import back this export file.
  4. Enjoy working GetChild ( ) and everything else that you have had working before.

 DataWindow Repair Utility

This utility fixes invalid column IDs in the datawindow definition.
Most often we get invalid IDs in design time (DataWindow Painter) when we copy columns from one datawindow and paste them into another datawindow. This happens when the source and the target datawindows have same column names but different column order or different number of columns.
Click here to download DW_FIX.EXE. You will need PowerBuilder 6 deployment kit in order to run DW_FIX.


 Response Window With Menu

Undocumented PowerBuilder: You can have a menu in a response window?
Although this is not standard windows GUI, it could be handy sometimes. Use the ChangeMenu( ) function in the open event to associate a menu with the window.

 MDI Frame Without Menu and Toolbar 

Undocumented PowerBuilder: You can have a MDI frame without a menu and without a toolbar? Create a menu with only one item, which is invisible and disabled and use that menu for the MDI frame.

  Secrets of Dynamic DataWindows

Undocumented PowerBuilder: As you know you can use SyntaxFromSQL function to generate DataWindow source code based on a SQL SELECT statement.Then you can pass the source code returned by SyntaxFromSQL directly to the Create function to create new datawindow dynamically. On-line helps says that for SyntaxFromSQL argument you can use only a string whose value is a valid SQL SELECT statement. However, in PowerBuilder 6.0 and above you can also use EXEC <procedure name> <parameters>, where you substitute <procedure name> with the actual stored procedure name and <parameters> with the actual parameter values instead of   parameter names. For example, you can use NULL as a value for each required parameter. After you have the new datawindow created, you can use the Modify function to correct parameter names in the datawindow SQL.

  Custom Toolbars - This is Really Simple

Can you have a toolbar in a response window? Or may be you want a second or third toolbar on your MDI sheet window?
Although this is not directly supported PB feature, it could be handy sometimes. Moreover this is really simple and portable. I mean you can take your existing windows, code, menus, and toolbars and reuse them with very little changes. Download sample code here.


  Export DataWindow to Excel including computed columns, headers, footers, groups, text labels, etc...

As you probably know, SaveAs function can save datawindow contents in MS Excel format, but ... Yes, unfortunately, it saves raw data only, forget about computed columns, formats, group headers and footers. Not many people have a solution for this problem. However, the solution is quite simple:

  1. SaveAs you datawindow to HTMLTable! file.
  2. Use OLE with Excel to convert the HTML file to Excel native format.

This method works quite well with grid-style reports and other style datawindows, but it is as good as good PowerBuilder datawindow conversion to HTML.

Check out sample code here.

  Asynchronous Processing in PowerBuilder (submitted by Michael Mwamunga)

This article contains information that is useful in creating PB applications where asynchronous functions need to be called. An example may be when you need to call a heavy database stored procedure and don't want your application to remain locked while the procedure executes.Click here to download ZIP file containing the article and the example code that you can use in your applications.


  Another Toolbar Tip

Undocumented PowerBuilder: The most simple and efficient way to have both MDI frame and MDI sheets share the same toolbar and avoid multiple toolbars is to give them the same name. You can do this in the application open event:

this.ToolBarFrameTitle = "Toolbar"
this.ToolBarSheetTitle = "Toolbar"

  Exchange information between PB applications (submitted by Jose Manuel Navarro)

This trick is in case you need trigger a event from a application to another.

Basically, the tip is about calling PB Send() function with ne following parameters:
    handle:          handle of target application.
    #message      1023 + XX, where XX is the number of a pbm_customXX message.
    longword       a optional long parameter
    long                a optionar long parameter. You can't send string as long in this case.

Click here to download ZIP file containing two sample PB applications demonstrating this technique: a source application, wich send a message, and a target application wich receive that message. Both are
in PB 6.5..


  SQL Exceptions handling (submitted by Jose Manuel Navarro)

This excellent tip demonstrates how you can catch and handle SQL errors.

This tip is based on exception handling methods available in other languages, like Delphi, C++ or Java.
In PB8, exception handling is included but, while we migrate to PB8...

This solution could be used in all PB versions (I hope).

Click here to download ZIP file containing the sample PB applications wtih complete source code (PB 6.5).


  isValid ?

window my_window
isValid(my_window)  -->  as you expect, it returns False

So far so good...and now, let's see how it works for dwo object in the datawindow events. Let's consider a situation when we have a script for datawindow clicked event and pehaps we clicked inside the datawindow, but not on any object.

isValid(dwo) --> as you don't expect, it returns True
isNull(dwo) --> returns True

Surprise? bug? or may be it is a feature?

Note: old good GetObjectAtPointer() always works correctly as well as GetClickedColumn() and  GetRow() are still much more reliable than these event arguments.

  Windows API library (submitted by Santiago Ciappesoni)

This library contains ready for "copy and paste"  declarations of most Window API functions, structures and constants. You will find there everything, from declarations of functions for working with standard Windows controls to WinSock interface. Do yourself a favor and download this library. If you don't need it today, you will need it tomorrow.


  Accesing TopSpeed Databases  (submitted by Michael Mwamunga)

Although perhaps the two were never meant meet, accessing Topspeed (.TPS) database tables from Powerbuilder via the ODBC driver from Soft Velocity is possible. Here is how...

Note: This page is maintained by mail.gif (898 bytes) Dmitriy Evinshteyn


 Press Ctrl+D to bookmark this page. I will add more tips soon.

Have a cool tip? Why don't share with other? Email your tip and I will add it to this page along with a link to your site.