From the Editor-in-Chief of PowerBuilder Developer's Journal

Bruce Armstrong

Subscribe to Bruce Armstrong: eMailAlertsEmail Alerts
Get Bruce Armstrong: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

PowerBuilder: Article

Custom Common Dialogs Using SetWindowsHookEx

There's No End To The Customization You Can Do

PowerBuilder contains a number of built-in common dialogs that can be used within your own applications.

What do you do when one of these dialogs meets most, but not quite all, of the functionality you need? Do you simply accept the limited functionality? Do you write your own dialog from scratch to replicate them and add the additional functionality (a maintenance headache)? There is a third option. You can simply use the dialog that PowerBuilder provides and modify it at runtime to provide just the additional functionality that you need.

The dialogs PowerBuilder provides include:

  • The GetFileOpenName, GetFileSaveName, ChooseColor, GetFolder, PrintSetup, and PrintSetupPrinter system function dialogs
  • The DataWindow Control SaveAs, SetFilter, and SetSort function dialogs
  • The DataWindow object DataWindow.Print.Prompt attribute dialog
  • The ubiquitous MessageBox dialog

For the purposes of this article we're going to use the DataWindow control SaveAs dialog, but the technique can be used to customize any common dialog.

Enter SetWindowsHookEx
The Windows API has supported the SetWindowsHookEx method since Windows 95. The method allows a developer to "hook" certain Windows messages, adding their own procedure into the chain of procedures that will be processed as a result of the message. The issue is that the method requires a callback. That is, we need to be able to pass the address of the procedure we want the hook to include.

Fortunately, the introduction of the PowerBuilder Native Interface (PBNI) allows us to implement a callback in a fairly straightforward manner. In this particular example, the callback procedure within our PBNI extension will do all the necessary work. However, since PBNI extensions can invoke PowerBuilder object methods, it's certainly possible to move the processing back into PowerBuilder objects as well.

Note that the SetWindowsHookEx method will hook all occurrences of the particular Windows message it's set for. This means we should follow a number of guidelines when using this method.

  • We should wait until just before we need to use the hook to set it and "unhook" the Window messages just as soon as we're done. This will improve performance (our procedure won't be called for messages we're not interested in) and will help ensure we don't end up processing messages we didn't intend to.
  • Since we are hooking a common dialog message, we must avoid doing anything that will cause another common dialog to appear while our procedure is running. Otherwise, we may run into some recursion if the new common dialog generates the same message and ends up retriggering our procedure.
  • We may not be the only process that has hooked the message. Therefore, we need to allow the message to process other hooks once we're done with it rather than ending the execution of the message at the end of our procedure.

A Real-Life Example
With the most recent versions of PowerBuilder, the DataWindow Control now supports saving the data out in 18 different file formats. In combination with the option to include column header information in the file for certain formats, the resulting dropdown list box of file formats in the SaveAs dialog contains 26 options. Unfortunately, the SaveAs method doesn't allow you to filter the list or to control which file format appears as the default format.

There are a number of reasons that you might want to have those options. For example, two of the formats on that default list (XML and XSLFO) require you to deploy additional DLLs (e.g., PBXerces90.DLL and xerces-c_2_1_0.DLL). One of the other formats (PDF) requires the deployment of some printer driver files and Ghostscript, a third-party GPL-licensed utility. In most cases, the GPL license prohibits distribution of that utility outside of your own company, which could make it necessary for your end users to obtain and install it themselves to support that particular format. You may simply decide that you would rather remove those formats from the dropdown list rather than deal with the deployment issues. There are also a number of other formats (SYLK, WKS, WK1, DIF, dBASE2, dBASE3) that are largely irrelevant in most cases and that you may want to exclude. There are still other formats you may choose not to support for your application (e.g., older Excel formats, SQLInsert, PSReport, WMF, and HTMLTable). Finally, if you're fairly certain that your end users will be saving to a particular format the majority of the time (e.g., Excel8), you may want to make that the default format.

More Stories By Bruce Armstrong

Bruce Armstrong is a development lead with Integrated Data Services ( A charter member of TeamSybase, he has been using PowerBuilder since version 1.0.B. He was a contributing author to SYS-CON's PowerBuilder 4.0 Secrets of the Masters and the editor of SAMs' PowerBuilder 9: Advanced Client/Server Development.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.