Creating OLE clients
An OleClient widget provides an OLE container the place to put embedded or linked OLE objects. An OleClient is a primitive widget, thus conforms to all standard management of widget geometry. An OleClient widget contains a connection to an embedded or linked OLE object and transparently manages all low-level OLE interaction with that object. The contained OLE object renders its content on the OleClient widget, which may be configured to allow the user to resize its area or move it within its enclosing window.
OleClient widgets are created and managed like other primitive widgets. However, there are several techniques for creating and connecting an embedded or linked OLE object to an OleClient widget.
Some techniques create and connect an embedded or linked OLE object at the same time as the OleClient widget is created. These include creating an OLE object by its registered name or from one of its server files.
Other techniques create and connect the OLE object after the widget has been created but before it is managed in the widget tree. These include creating an OLE object from the following:
• An invocation of the Insert Object dialog
• The clipboard through the Paste Special dialog
• The clipboard without going through the Paste Special dialog
• A drag and drop operation that uses the framework described in
Drag and Drop.
Creating by name
To create an OLE object and connect it with an OleClient widget, the OLE object's server must be registered in the system registry, which is often called the "registration database". One of the attributes of the registration is the programmatic identifier, or ProgId, which identifies the registered OLE object. The ProgId of a registered OLE object is the name used for the clientName resource of an OleClient.
Since OLE clients are created as child widgets of non-primitive widgets (that is, any CwComposite), there is an additional widget-creation convenience method implemented in CwWidget called createOleClient:argBlock:. Hence, knowing an OLE object's ProgId, an OLE client is simply created and connected to the OLE object.
For example, an embedded Microsoft Word document is created using:
| client |
client := composite
createOleClient: 'client'
argBlock: [:w |
w
x: 50;
y: 50;
width: 200;
height: 200;
clientType: XmEMBEDDED;
clientName: 'Word.Document.6'].
client manageChild.
Here, the clientType resource is set to XmEMBEDDED and specifically requests that the OLE object named 'Word.Document.6' be embedded into the new OleClient. This code fragment creates an OleClient widget that contains an empty embedded Microsoft Word document. Double-clicking anywhere on the OleClient widget causes Microsoft Word to be activated in place and ready for editing the embedded document.
Creating from a file
Creating an OleClient from an OLE object server's data file is similar to creating by name. To create from a file, the file must already be created by the OLE server.
An embedded OLE object can be created from an existing Microsoft Word document file using:
| client |
client := composite
createOleClient: 'client'
argBlock: [:w |
w
x: 50;
y: 50;
width: 200;
height: 200;
clientType: XmEMBEDDED;
sourcePath: 'c:\docs\sample.doc'].
client manageChild.
The OleClient is created to be linked to the same document file by changing the clientType resource to XmLINKED. For example, an OleClient is created to be linked to a Microsoft Word document file using:
| client |
client := composite
createOleClient: 'client'
argBlock: [:w |
w
x: 50;
y: 50;
width: 200;
height: 200;
clientType: XmLINKED;
sourcePath: 'c:\docs\sample.doc'].
client manageChild.
The embedded and linked cases look the same to the user. However, in the linked case, when the user double-clicks on the OleClient, Microsoft Word opens in its own windows for editing the linked document; it does not activate in place in the container. Furthermore, since the OleClient is linked to the file, other users can separately edit the file and modify its contents. However, an OleClient can be explicitly updated to reflect third-party changes in the linked OLE object's content by sending the OleClient the updateFromLink message.
Creating from the Insert Object dialog
Many containers let their users insert registered OLE objects into the application. To support this, the OleClient widget provides access to the standard OLE Insert Object dialog. This dialog can be invoked from an existing OleClient through its promptInsertObject: method.
Applications typically offer access to this dialog through one of their menu items. In fact, the OLE user-interface guidelines suggest offering an Insert Object item on either an Edit or Insert pull-down menu. Before the Insert Object dialog can be invoked, an OleClient widget must already exist and must not be connected to an OLE object. For example, an Insert Object menu item callback might look like:
menuEditInsertObject
"Private - Process the Edit menu Insert item."
| client result |
client := composite
createOleClient: 'client'
argBlock: [:w |
w
x: 20;
y: 40;
width: 200;
height: 200].
client
mappedWhenManaged: false;
manageChild.
result := client promptInsertObject: XmANY.
result == nil ifTrue: ^client destroyWidget]. "Dialog canceled"
result
ifTrue: [
client mappedWhenManaged: true.
^self]
ifFalse: [
CwMessagePrompter warn:
('The server application, source file, or item cannot be found.\',
'Make sure the application is properly installed, and that it \',
'has not been deleted, moved or renamed.') addLineDelimiters].
In this example, the OleClient is first created with an initial position and size. The OleClient widget is then managed. It is not, however, made visible to you using mappedWhenManged: false until the embedded or linked OLE object is created and connected to the widget. The parameter to promptInsertObject: specifies what kind of OLE object can be inserted in the widget. If XmANY is specified, for example, you can select the Create from File option in the dialog and then optionally select Link.
For each resource value designated below, you can take the designated action with the inserted OLE object:
XmANY
Can be embedded or linked
XmLINKED
Must be linked
XmEMBEDDED
Must be embedded
If promptInsertObject: answers true, an OLE object was created and connected to the OleClient widget, which can then be mapped with the message client mappedWhenManaged: true.
If promptInsertObject: answers nil, you canceled the dialog. However, if it answers false, the creation of the OLE object failed.
If you insert an object from a file, whether it is linked or not, the widget displays the contents of that OLE object. However, if the OLE object is inserted as embedded, there is nothing to display, and the OLE object is immediately activated to let you enter some initial content.
Note:
An OleClient can be queried to determine whether it is embedded or linked by sending isEmbedded or isLinked.
Creating from the Paste Special dialog
When an OLE object is copied to the clipboard, its server renders the object in many different formats, many of which are required by OLE for interoperability with other OLE-enabled applications.
The OLE system provides a standard dialog called Paste Special, which allows you to select which object format to paste into their application. An OleClient widget provides access to the Paste Special dialog through its promptPasteSpecial: instance method.
As with the Insert Object dialog, applications typically offer access to the Paste Special dialog through one of their menu items. Again, the OLE user interface guidelines suggest offering a Paste Special item on the Edit pull-down menu. Before the Paste Special dialog can be invoked, an OleClient widget must already exist and must not be connected to an OLE object. For example, a Paste Special menu item callback might look like:
menuEditPasteSpecial
"Private - Process the Edit menu Paste Special item."
| client |
client := composite
createOleClient: 'client'
argBlock: [:w |
w
x: 20;
y: 40;
width: 200;
height: 200].
client
mappedWhenManaged: false;
manageChild.
(client promptPasteSpecial: XmANY) == true
ifFalse: [^client destroyWidget].
client mappedWhenManaged: true
In this example as in the one before it, the OleClient is first created with an initial position and size. The OleClient widget is then managed but not made visible to you until the OLE object is created and connected to the widget. The parameter to promptPasteSpecial: takes the same values as promptInsertObject:. If XmANY is specified, for example, you can select the Paste Link option in the dialog to create a linked OLE object.
If promptPasteSpecial: answers true, an OLE object was created and connected to the OleClient widget. The widget can then be mapped and the OLE object made visible.
If promptPasteSpecial: answers nil, you canceled the dialog. However, if it answers false, the creation of the OLE object failed.
OLE servers render a variety of formats on the clipboard when one of their objects is copied. With the Paste Special dialog, you can select for embedding one of the non-object renderings, such as a metafile or bitmap. In this case, the image of the rendering appears in the OleClient widget when it is mapped, but it you cannot activated it. This is known as static embedding. The instance method isStaticEmbedding is available to query an OleClient to see whether it has a static embedding. For example, if a container application disallows static embedding, it could test using:
((client promptPasteSpecial: XmANY) ~= true or: client isStaticEmbedding])
ifTrue: [^client destroyWidget].