Welcome!

PowerBuilder Authors: Dan Joe Barry, Carmen Gonzalez, Ian Thain, Yakov Werde, Paul Slater

Related Topics: PowerBuilder

PowerBuilder: Article

OLE - Extending the Capabilities of PowerBuilder

Part 2

public function integer of_open (string as_filename);
IF IsNull ( inv_word ) THEN Return -1
try
    inv_word.Documents.open ( as_filename )
catch (OLERuntimeError MyOLEError )
    Return -1
catch (NullObjectError MyNullError )
    Return -1
end try

The of_close function shows how the constant's instance variable is used to pass arguments to functions of the OLE object.

public function integer of_close ();
try
    inv_word.Documents.close( &
    inv_const.wdSaveChanges, &
    inv_const.wdWordDocument )
catch (OLERuntimeError MyOLEError )
    Return -1
end try
Return 1
end function

PowerBuilder does not support skipping "optional" arguments in OLE Automation function calls. For example, the Word Document object Close function used above takes three optional arguments:

  • SaveChanges
  • OriginalFormat
  • RouteDocument
Since all the arguments are optional, we could have called it without passing any arguments. However, once we start passing arguments, we have to pass all the arguments through the last optional one we wish to pass. That is, we could pass the SaveChanges argument by itself, but we couldn't pass that OriginalFormat argument by itself. Instead, we would have to pass something for the SaveChanges argument as well as the OriginalFormat argument (as we have done in the sample). This may not come as much of a surprise to many PowerBuilder developers unless they have some Visual Basic background, because that development tool does support skipping optional arguments. PowerBuilder also does not support the use of named notation rather than positional notation for arguments.

The of_printpreview demonstrates the use of the AsStatement! keyword. The Word ActiveDocument PrintPreview method doesn't take any arguments and doesn't have a return value, which makes it look like a property. What's more, there is a Word PrintPreview property as well. Therefore, we need to use the AsStatement! to ensure that PowerBuilder knows we are attempting to call a function rather than refer to a property.

public function integer of_printpreview ();
IF IsNull ( inv_word ) THEN Return -1
long ll_type
try
   ll_type = inv_word.ActiveWindow.View.Type
   IF ll_type = inv_const.wdPrintPreview THEN
     inv_word.ActiveDocument.ClosePrintPreview()
   ELSE
     inv_word.ActiveDocument.PrintPreview( AsStatement! )
   END IF
catch ( OLERuntimeError MyOLEError )
   Return -1
end try
Return 1
end function

So far the method we've used to interact with OLE Automation methods and properties is no different from the method we used with OLE Custom Controls. The similarity ends when we come to handling events though. While PowerBuilder exposes the events fired by the control within the IDE, it doesn't do so for OLE Automation. For that matter, few programming languages do, and many OLE Automation targets fire few - if any - events.

Nonetheless, there is a mechanism for capturing OLE Automation events (see Figure 4), which is explained in some detail in Microsoft Knowledge Base article 183599. Basically, it's necessary to create another COM object referred to as an "eventsink" that implements the same events as the OLE Automation object you want to capture events from. That eventsink object is then registered with the OLE Automation application's "ConnectionPoint". Now when the OLE Automation object fires an event, that same event fires on the eventsink. Since the eventsink is an object we created, we can have it respond to the event.

We could have implemented this prior to PowerBuilder 9 by creating a separate COM object in PowerBuilder or by writing a custom DLL in C++, either of which would then relay the event notifications on to our PowerBuilder application. However, the introduction of PBNI in PowerBuilder 9 has simplified things for us considerably. Essentially it allows us to create objects in C++ and then use them in PowerBuilder as if they were native PowerBuilder objects. PBNI objects can in fact inherit from PowerBuilder objects, and PowerBuilder can create objects inherited from PBNI objects.

OLEStream and OLEStorage
OLE objects store data internally in objects referred to as "streams," which are contained within other objects called "storages." Conceptually, you could think of these as similar to files and directories for storage of data on your hard drive. As a directory can contain a number of different files and even other directories, a storage can contain one or more different streams and even other storages. In addition, just as a directory can contain files that were created from different applications, a storage can contain streams that were created from different OLE objects.

The PowerBuilder OLEStream and OLEStorage classes map to the stream and storage objects and provide the means for accessing the data in them (see Figure 5). Generally you should use the OLE Custom Control or OLE Automation application that created the data to manipulate that data. Accessing the data directly using the OLEStream and OLEStorage classes has somewhat limited capabilities but you may find it useful in special circumstances. For example, you may find it to be particularly useful if your target database doesn't handle BLOBs, so the OLE data information used in your application could not be stored in the database, or if some other factor required an approach other than storage in the database.

One interesting item is that the visible aspects of the OLE data are actually stored with the OLE data. Therefore, you can insert the data into an appropriate control on a PowerBuilder application and it would display properly without having to start the related application. The application would only need to be started if the user attempted to activate the control.

In the sample application provided in the source code (based largely on the sample provided in the PowerBuilder documentation), one PowerBuilder application is used to read a number of image files into a single OLE storage object, which is then saved as a file. Another PowerBuilder application then reads those images out of the OLE storage file and inserts them back into another image control.

The main advantage of this technique - other than being able to store image files used by the application outside of the database - is performance. The single file acts like a database of its own. The PowerBuilder application reads it once and then simply pulls out the images as they're referenced. If the images were stored in separate records in the database or as separate files on a file server, PowerBuilder would have to read each individually, which could impact performance considerably.

Conclusion
OLE provides a very powerful way to extend the capabilities of PowerBuilder either through the use of third-party controls or by allowing PowerBuilder to interact with other applications.

. . .

This article is based on PowerBuilder 9 Internet and Distributed Application Development by various authors (ISBN 0672324997), published by Sams Publishing.

More Stories By Bruce Armstrong

Bruce Armstrong is a development lead with Integrated Data Services (www.get-integrated.com). 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 (2) View Comments

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.


Most Recent Comments
SYS-CON India News Desk 01/16/06 03:01:47 PM EST

This two-part article provides a primer on OLE, some practical examples of its use, and demonstrates some methods for addressing the limitations of PowerBuilder's implementation of OLE.

PBDJ News Desk 01/16/06 02:51:32 PM EST

This two-part article provides a primer on OLE, some practical examples of its use, and demonstrates some methods for addressing the limitations of PowerBuilder's implementation of OLE.