|By Bruce Armstrong||
|April 26, 2005 10:00 AM EDT||
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.
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.
- Where Are RIA Technologies Headed in 2008?
- PowerBuilder History - How Did It Evolve?
- Creation and Consumption of Web Services with PowerBuilder
- Cloud People: A Who's Who of Cloud Computing
- DDDW Tips and Tricks
- Cloud Expo 2011 East To Attract 10,000 Delegates and 200 Exhibitors
- Working with SOA & Web Services in PowerBuilder
- Dynamically Creating DataWindow Objects
- OLE - Extending the Capabilities of PowerBuilder
- DataWindow.NET How To: Data Entry Form