Supporting the Clipboard, DDE, and OLE in Applications

 

Herman Rodent
Microsoft Developer Network Technology Group

Created: September 24, 1992

There are two sample applications associated with this technical article.

Click here to download the StockSrv sample application associated with this article from the Downloads Center.

Click here to download the DDERecon sample application associated with this article from the Downloads Center.

Abstract

Microsoft® Windows™ provides many methods through which applications can communicate with each other, including shared memory, shared files, the Clipboard, dynamic data exchange (DDE), and object linking and embedding (OLE).

Many applications would benefit from the ability to import data from other applications or export it to them. The difficulty lies in determining which of the mechanisms listed above are most appropriate to support.

This document reviews Clipboard support in applications and goes on to look at why an application might be designed to support the Clipboard, DDE, or OLE. It looks at a number of different types of applications and discusses what support is appropriate for each of them.

Introduction

Most applications either generate or process data in one form or another. It seems reasonable to the humble user that one might copy data between these applications without much restriction. Unfortunately, implementing support for such widespread importing and exporting of data is not trivial. Many techniques are possible under Microsoft® Windows™ for sharing data, and for each of these there are many different possible data formats.

For an application to support every possible format and communication technique, it would have to include a huge amount of code. To enable widespread communication between applications in a consistent way, the protocols for the Clipboard, dynamic data exchange (DDE), and object linking and embedding (OLE) have been defined together with a set of methods that allow an application to support a much smaller set of data formats and still have good communications with other applications.

Much of the discussion here centers around the Clipboard. DDE and OLE work with the same data types as the Clipboard and manage similar data ownership issues. If you are implementing DDE or OLE support for the first time, adding Clipboard support to the application first is often a good way to become familiar with the problems of multiple data types. Some of the code written to support the Clipboard will often be directly reusable in a DDE or OLE implementation.

DDE and OLE both use the concepts of clients and servers. A server is generally the source of the data and provides services to its clients. A client uses servers as data providers or to manipulate data on its behalf. There are some cases, particularly in certain DDE contexts, in which it seems that two applications are behaving as peers, both being providers and consumers of each other's information. In these cases, we will refer to the initiator of a conversation as the client and the responder as the server. An application may be both a client and a server, and may support DDE, OLE, or both.

Some technical articles on OLE have pointed out that the OLE libraries include all that is required to support DDE as well as OLE. This does not mean that if you intend to implement DDE in an application, you should automatically choose the OLE libraries as the way to go. The dynamic data exchange management library (DDEML) provides a much better approach if the application is to support only DDE.

This article doesn't consider the command execution function supported by DDE because it's not really a means of data exchange. Command execution support in DDE servers is covered in other articles.

Working with the Clipboard

The most common means of interapplication communication is the Clipboard. The process is initiated by the user and has a very simple protocol. When the user requests a cut or copy operation to place data in the Clipboard, the application makes application programming interface (API) calls to empty the Clipboard and then to send data to it. The application provides the single item of data in as many formats as it can, so as to increase the likelihood that the eventual recipient will understand one of them. Possible problems of using huge amounts of system resources in rendering your application's data in many different formats can be avoided by employing the delayed rendering technique. Using this technique allows the provider of the data to simply list the formats it supports, but only to have to render the data when another application actually tries to take it from the Clipboard. In this way, data that is never going to be used never needs to be rendered.

When the user makes a paste request, the receiving application enumerates the formats of the data in the Clipboard and, having found one it likes, takes the data.

Figure 1. Communication through the Clipboard

Types of Data Used in Clipboard Transfers

We may transfer objects in one of a number of standard formats through the Clipboard or a private data type specific to an application or set of applications.

Standard types

Windows supports many types of data. Table 1 lists the standard types defined in WINDOWS.H for Windows version 3.1.

Table 1. Windows 3.1 Standard Clipboard Formats

Format name Description
CF_TEXT Null-terminated, plain ANSI text in a global memory block.
CF_BITMAP A bitmap compatible with Windows 2.x.
CF_METAFILEPICT A Windows metafile with some additional information about how the metafile should be displayed.
CF_SYLK An ASCII text format used by some older Microsoft products.
CF_DIF Software Art's data interchange format (DIF). Also an ASCII text format.
CF_TIFF Tag image file format (TIFF) data in a global memory block.
CF_OEMTEXT Similar to CF_TEXT but using the OEM character set.
CF_DIB A global memory block containing a Windows device-independent bitmap (DIB) as a BITMAPINFO structure followed by the bitmap bits.
CF_PALETTE A color-palette handle. (Used in conjunction with CF_DIB.)
CF_PENDATA Data is for the pen extensions to Windows.
CF_RIFF Resource interchange file format (RIFF) data as a global memory block.
CF_WAVE A specific case of RIFF in which the contained data is a waveform (sampled sound).

Note

   

A more detailed description of these formats can be found in the Microsoft Windows version 3.1 Software Development Kit (SDK) Guide to Programming or Charles Petzold's book, Programming Windows 3.1, on the MSDN Library Archive CD.

Private types

The standard data types support the simple common objects in the Windows environment and a lot of data can be transferred using them. In fact, much can be accomplished with just CF_TEXT for plain text and CF_BITMAP or CF_METAFILEPICT for images.

If the data has some structure to it (a spreadsheet for example), using these simple types has some drawbacks. Transferring a spreadsheet in CF_BITMAP format will produce a nice picture but won't allow the receiving application any opportunity to manipulate the data. Sending it as CF_TEXT would work, providing some scheme has been defined for expressing how the rows and columns are sent. Once a protocol is superimposed upon a standard format, the format really becomes nonstandard and requires special knowledge to interpret it. It then makes more sense to define a new format and publish it.

Windows provides a mechanism to register the names of private formats at run time. Publishing the format means creating a document that gives details of the format and describes how it should be used. Ideally, you should supply sample code in case the documentation is ambiguous. Include all the documents and code samples with your application user manuals. Microsoft Excel, for example, prefers to use its own XlTable format when transferring spreadsheet data. The details of this format are published in the user documentation for Microsoft Excel.

What Data Types Should I Support?

Determining what data types to support depends on two things: first, the basic type of data (text, image, or sound); and second, whether you expect to be passing this data to specific applications that have a preferred data format.

Consider as an example a simple calculator application such as the one supplied with Windows. If the user makes a calculation and then copies it to the Clipboard, what formats make sense? In this case, CF_TEXT works well since the data can be represented unambiguously in plain text. Copying it as a bitmap is pointless because it's not the image of the number we care about, but some representation that will essentially transfer the number's value.

Now consider who our prospective clients might be. The most important client is our own application. We must be able to paste back anything we copy. CF_TEXT can be converted back to the number values we understand, so this works for us. CF_TEXT also works for word processors such as Microsoft Write or Microsoft Word. But what about a spreadsheet program such as Microsoft Excel? Microsoft Excel understands CF_TEXT and can import it. The only problem with this is that Microsoft Excel supports both text and numeric objects in spreadsheet cells. How would it know whether to treat this object as a piece of text to display or a number to use? Generally, Microsoft Excel tries to be smart about this, and if the object looks like a number, Microsoft Excel treats it as a number. If it doesn't look like a number, it treats it as text. Allowing the destination application to make a choice of this sort can lead to inconsistent behavior as far as the user is concerned.

If we really want to work well with Microsoft Excel, we might consider supporting its private XlTable format. This format has explicit tags that define the data as a string, a floating-point value, or whatever. In this way, we can force the application to treat the data as a number and guarantee the behavior of the client application. But is this really necessary? Providing support for these product-specific formats is quite a lot of extra work for a limited benefit. To get real benefit, we should consider doing this sort of specific data type support for all applications that have published private data formats, a task that is obviously not realistic. Generally, this approach only makes real sense where a suite of applications use a common private format.

Figure 2. Data provided in multiple formats

Who Owns What?

Part of any data-exchange protocol is concerned with ownership of the data. When the data object is first created, it belongs to the application in which it was created. The rules for using the Clipboard are that once the creator application places the data (or more precisely, a handle to the data object) in the Clipboard, that application ceases to be the owner of the object and ownership is transferred to the Clipboard.

Any application that subsequently pastes this data makes a copy of it for its own use. The Clipboard retains ownership and is responsible for deleting the original object there when the Clipboard is next emptied. The client is required to copy the data so that, in the event that the client modifies it, such modification will not affect a subsequent paste operation by some other application.

There is a little more to it than that, but this description will do for now. The point being made here is that rules exist by which all applications must abide if the transfer is to take place successfully.

Going Live with DDE

The Clipboard allows the user to take a piece of data from one place and put it somewhere else. This process provides a snapshot of what the data was when it was copied to the Clipboard. But what if the data changes continuously, and we want this changing information passed from one application to another so that it can be processed in real time?

We could still use the Clipboard for this. We already understand how it works. All we need to do is copy it to the Clipboard each time it changes and find a way to tell the other application to go get it from the Clipboard. We could do this notification by sending a standard Windows message.

This mechanism could certainly work but it has a rather irritating side effect. Consider this scenario: A user is busy with a word processor, cutting and pasting text. Suddenly, a piece of data being monitored by another application changes and gets copied to the Clipboard. The user then finds that he pastes something into his word-processing document he didn't copy to the Clipboard in the first place, and worse still, has lost the item he cut from his document. So, to avoid irate phone calls to the support department, we have a rule that all Clipboard operations are initiated by the user.

Nonetheless, the Clipboard mechanism seems to have most of what we want: It handles multiple formats of the same data, and we could easily add a way of telling whoever might care that the data has changed.

DDE is the answer we want in our search for a protocol that allows two applications to exchange data in a format that they both understand. The DDE protocol was originally implemented using a set of Windows messages and the same set of data formats that the Clipboard uses. The specification of the protocol is quite complex, and consequently, implementations of it are often slightly different depending on how the specification was interpreted at the time the application was developed.

Figure 3. DDE implemented directly using Windows messages

More recently, the DDEML API set was introduced to provide isolation both from the actual protocol and also from the implementation of the protocol under Windows. Having DDEML implement the protocol means a much higher degree of uniformity of behavior in applications using DDE (via DDEML calls) and also allows for the underlying mechanism to be changed in the future without breaking applications that support DDE.

Figure 4. DDE implemented through the DDEML

DDE Terminology

When a DDE client establishes contact with a DDE server for the purpose of exchanging data on a specific subject, we say that a conversation has been established between the client and the server.

The server supports conversations on a set of topics. A topic is generally a broad area of interest. For example, Microsoft Excel considers each file it has open to be a topic.

Each topic may have items of data associated with it. Often the same item can be requested from various different topics. For example, we might design a server that has a set of topics corresponding to the currently open set of files, and items such as "size," "date," and so forth. A DDE client could request data on the size or date of any or all of the available topics (files, in this case).

In addition to any topics of its own, a DDE server should always support a specific topic called the System topic. The System topic has a set of items associated with it that enable DDE clients to query the server for the list of topics currently supported, the data formats it supports, and a number of other data items. A more complete discussion of the System topic can be found in the technical article "Supporting the DDE System Topic" on the Microsoft Developer Network CD (Technical Articles, Windows Articles, OLE and DDE Articles).

Establishing the Data Format

Let's say a DDE server has a topic called "Food prices" and items such as "Bread," "Cheese," and so on. If the client application wants to know the price of bread, it needs to know the name of the service to connect to. Usually, the user would provide this by making a selection from a list of available services or simply typing the name in. Once connected, the client application can ask to have data supplied on a particular item ("Bread") of a topic ("Food prices") in its favorite format. If the client were Microsoft Excel, for example, it would ask for the data in XlTable format. The client application would ask for this format first because it's the one that is most useful to it and that it can process most easily. If the server doesn't do this format for the particular item, it simply fails the request. In that case, the client application would try again with another format, for example CF_TEXT. This time the server supplies the data as requested, and the client application is happy.

This negotiation of the format can be simplified if the server supports the System topic. The client application can simply ask what formats are supported for a given topic/item pair.

DDE Execute Commands

In addition to providing a protocol for data exchange, DDE also specifies a mechanism that allows one application to send a command string to another. For example, the DDE commands can be used to open a file in one application from another. This can be a reason for providing DDE server support in an application even though the application has no data to share.

The technique for parsing these command strings varies somewhat from application to application, so the users currently see slight differences in syntax here. If you are proposing to support DDE execute commands, look at the way they are supported in Microsoft Excel as an example.

Summary

DDE provides a data exchange protocol for applications to exchange data where both sides of a conversation need to be able to manipulate the data.

But I Just Want to See the Picture

Imagine that you're writing a word-processor package, and you'd like your user to be able to copy a Microsoft Excel chart to the Clipboard and paste the picture of the chart into the word processing document, but you don't want to write the code to take a huge XlTable structure and display it the way Microsoft Excel does. What you're looking for here is a way to save the chart data with the document but have someone else do the work of displaying it.

The object linking and embedding (OLE) libraries provide applications with a mechanism to capture, display, and edit data in formats they don't understand.

A word processor that only understands how to lay out text and generic rectangles bounding pictures can allow its user to include pieces of sound, charts, or spreadsheets. Whenever the user wants to hear the sound or see the chart, the creator of the data (Microsoft Excel, for example) is called upon to do whatever is required to render it. The OLE client application simply provides a container for the bits.

OLE Terminology and Technology

OLE provides two mechanisms, linking and embedding. If the data is embedded, the host application provides a container for the data itself. If the data is linked, the host provides a container for a reference to where the data can be found (a file path, for example).

OLE version 1.0 provides image rendering internal to the host application but editing as an external feature. If the host contains a linked or embedded Microsoft Excel chart, it will be displayed where it was pasted, but if the user double-clicks it to edit it, OLE will invoke Microsoft Excel, which will show the chart in a separate Microsoft Excel window.

OLE is currently implemented using the DDE protocol. Applications using OLE are not aware that DDE is being used, nor should they rely on this, because the implementation mechanism will not be there in future releases of the OLE components.

Figure 5. The current OLE implementation structure

What Should I Implement in My Application?

Having decided that you want your application to be able to share data with other applications, how do you determine what method or methods to use?

Determining whether to support the Clipboard is usually a simple matter. If your application has any sort of text, image, or other data that might possibly be moved around or of use to the user in some other application context, you need to provide at least minimal Clipboard support.

Determining a need for DDE and/or OLE support is perhaps less clear. DDE is for client applications that need to manipulate the data. OLE is for client applications that just want to contain and show it without knowing what it is. We will look at three applications and examine whether they could usefully support the Clipboard, DDE, or OLE.

The three application examples were chosen to show how data from a single source can pass from application to application via different methods. In the case here, we begin with a live data feed attached to a communications port, convert it to a stream of DDE data, and finally end up with a linked OLE object. The purpose of this example is to help illustrate how to choose the most appropriate type of communication support to include in an application. Figure 6 shows the flow of data through the examples.

Figure 6. Data flow through the example applications

A Stock Market Data Feed

The first application is a stock market price monitor. It watches data arriving at a communications port and extracts share price information for a given list of stocks. The application has a display window showing the prices as they change in real time.

Adding Clipboard support

In designing the application, we might want the user to be able to take a snapshot of the current set of prices so that the data may be included in another document. If we provide simple Clipboard support to copy the data as CF_TEXT format, there is a reasonable chance that other applications could paste that data. Note that the data provided will always be only a snapshot in time of the continuously changing information. Simply choosing CF_TEXT as the format is not quite the end of the decision, however, as we need to format the block of text in a way that will allow another application to parse it successfully. The example included here uses tab characters to separate the fields and generates pairs of name/price fields. Here's how the string of text might be built for a sample set of price quotes:

MSFT<tab>75.26<tab>Bread<tab>12.5<tab>Milk<tab>24.6<null>

Many applications use tabs as field delimiters in text strings and would be able to read this successfully.

Try running the sample StockSrv application included at the beginning of this article, use the Edit Copy command to copy the current data to the Clipboard, and view it with the Clipboard viewer. You should see the current set of prices displayed in the Clipboard viewer window. If you have a copy of Microsoft Excel, try pasting the Clipboard contents into a spreadsheet. This time you should see that the data copies to a series of spreadsheet cells.

Adding DDE support

Users of our stock price application might want to plot a graph of the stock prices as they vary over time. We could add a graph-plotting package to the application to do this, or we could add DDE support so that the data could be sent to another application, such as Microsoft Excel, that could do the plotting for us. Adding the DDE support is much simpler than adding a graph-plotting package and enables many other applications to gain access to the data we provide.

Figure 7. A live DDE link between applications

As with the Clipboard, we should try to provide the data in many different formats. In this case, we would certainly provide it as CF_TEXT, and we might also consider providing it in a form Microsoft Excel can deal with more directly, such as XlTable. The XlTable format is documented in the Microsoft Excel Software Development Kit published by Microsoft Press.

By providing XlTable format support for the Clipboard, a Microsoft Excel spreadsheet could request data on a named share value and be provided with it every time it changed.

If you have a copy of Microsoft Excel version 4.0, start the StockSrv sample application. Then try opening the Microsoft Excel worksheet STOCK.XLS, and watch what happens as the data changes at the server.

What about OLE?

Does it make sense to add OLE support to the stock price server as either a client or a server? Not really. We have data that we can provide to another application, but the application could easily render it for itself, so we wouldn't need to be an OLE server. We have no need to incorporate other data in our display, so we don't need to be an OLE client either.

You might say that we could be an OLE server and display the data, but what purpose would this serve? If we didn't provide the data via DDE as well, the client application would only be able to show an image of the data and not access it in any other way. That means that it couldn't plot a graph, set trigger alarms, or whatever because an OLE client treats the data as a black box and has no knowledge of its format.

A Graph Plotter

The second application under consideration is one that plots a graph from a set of data kept in a table. The application takes data in one form, the table, and renders it in a different form, the graph. The application stores both the data table and the properties of the graph in a single file in its own private format. We'd like the graph to be capable of being updated as data in the outside world changes, and we'd also like other applications to be able to include one of our graphs.

Figure 8 shows an example of the sort of graph we could produce using Microsoft Excel. The graph shows the most recent ten data items obtained via DDE and their values.

Figure 8. A Microsoft Excel graph

Adding Clipboard support

The graph plotter keeps two sets of data internally: the table of numbers and some representation of the actual graph. You could argue that the graph is simply a different way of representing the table of numbers, which it is. However, when we consider adding support to copy data to the Clipboard, we need to consider the table of numbers and the graph as different objects and, hence, be able to select and copy them separately.

The problem lies in the fact that we must try to copy any given object in as many different formats as possible. So the data for the table could be copied, for example, as CF_TEXT and as CF_BITMAP. The CF_BITMAP format is literally a picture of the table, but it makes sense to include this format because we might want to import and display the data table in a word processor as it looks in table view of the graph plotter. Of course, we probably want to be able to copy the graph itself to the Clipboard so that it, too, could be pasted into a word processor document. We would probably use CF_BITMAP as one of the formats here, too.

If we copied both the table and the graph (both being logically the same thing) to the Clipboard at the same time, which one should the application copy as CF_BITMAP?

In practice, we try to do what seems reasonable to the user. If there is a method for selecting an object on display, the Clipboard copy operation copies only the currently selected object, whether it's the table or the graph.

Adding DDE support

Being able to update the graph in real time would be a great feature. To provide this support, we can become a DDE client. We would need to provide the user with a way to select which DDE server to use and what the topic name was for any given graph we are plotting. The application could then establish an advise request with the server to get data on each topic whenever it changed. Microsoft Excel's macro language provides a way to update a cell with information from a DDE server. The macro command is of the form:

=ServiceName|Topic!Item

Once we know the name of the server, the list of topics can usually be obtained from the server directly by making a request to one of the System topic items. In this way, we could simply provide a list of topics for the user to choose from in a list box. Most DDE servers publish the service names they support, together with a list of topics and items for each service.

This application provides no real data of its own, so it doesn't have much to offer as a DDE server.

Adding OLE support

Our graph-plotting application would make a great OLE server. Why is this? It renders data into an image and keeps the image current in real time with a data stream. Being able to link this sort of object into another application—a word processor for example—means that the graph could be made available in a document that discusses the trends seen in the market as they are happening or, at least, up to the point at which the document is printed. Embedding the same graph allows a permanent record of the state of the market at that time to be recorded.

If an object is embedded into another document using OLE, the receiving document becomes a container for the snapshot of the data of the object and holds that snapshot of the object taken at the time the object was embedded. The object can be displayed or edited by its OLE server but will not change if the original object from which it was copied changes.

If the same object—our stock price graph, for example—is linked into the client's document, the client holds only a reference to the object and not an actual copy of the data. The view of the object linked in the document will change with the state of the original object itself. So if the graph changes because of stock price variations, any document it is linked to will also show these changes when we look at it. (This is not entirely true because we can have multiple documents open in one or more applications that contain links to a single object, and only the last one activated gets the changes.)

A Text Display Utility

The final example is a simple text display utility, a sort of poor man's word processor. It takes plain ASCII text and renders it in a window. The text can be annotated by including sounds and images. We don't want to write the code to support the image or sound editing, and it would be nice if we didn't have to do much about the object-rendering code either. Wishful thinking? Read on!

Figure 9. A text document containing a sound and a graph

Adding Clipboard support

Adding Clipboard support could enable the user to copy all or a selected region of the text and paste it elsewhere in the current text or into another application. It also enables text copied to the Clipboard by another application to be pasted for display. Providing support for CF_TEXT format would be a good place to start. Adding a private data format would allow the text and the annotation objects to be copied as one combined object.

Adding DDE support

This application doesn't have much use for live, changing data that it needs to manipulate, so we aren't really interested in becoming a DDE client.

Adding OLE support

Making this application into an OLE client makes a lot of sense. It enables other data types to be attached to the text being displayed. For example, we might attach a graph of our stock market prices and a sound recording of the CEO giving an explanation of why the prices keep falling. We don't need to be able to render the images of these data types because that's the responsibility of the OLE server. We also get a free editor for our graph because the OLE server provides that support.

We could also add OLE server support. That way, the entire document could be linked to or embedded in another application document.

Making the Choice

The table below describes various ways in which an application could get or produce data or services, and suggests what sort of Clipboard, DDE, or OLE support might be appropriate for it.

Table 2. Communication Choices for Different Data Situations

Feature description Clipboard DDE Client DDE Server OLE Client OLE Server
Displays any form of data Yes   Maybe   Yes
Imports data to manipulate Yes Yes      
Exports data for others to manipulate Yes   Yes    
Imports data of unknown type       Yes  
Exports private data format Yes       Yes
Imports real-time data   Yes      
Exports real-time data     Yes    
Imports data of common types for display only (no data manipulation). Yes     Yes  

Although Clipboard support is not suggested in every case, the Clipboard can be used to establish DDE or OLE links through an Edit Paste Special... command and is, therefore, really an integral part of implementing OLE. Some applications might provide data through DDE but have no use for Clipboard support. An example of such an application might be a control unit for a piece of mechanical equipment connected to the computer via a communications port. The equipment is controlled by commands sent to the port and sends back information about itself. The DDE server provides an interface that applications can use to control the machine and monitor its status. In this case, Clipboard support is not needed.

Conclusions

The Clipboard is a useful facility to add to many applications. It allows the user to move data around within an application and between applications. It can also be used to establish OLE links and thus effectively copy an OLE object from one application to another. It also provides a good code base from which DDE or OLE support might be developed.

DDE provides an excellent method of importing live data to an application or exporting live data from it. If two applications want to share and manipulate a piece of data without the direct involvement of the user, DDE is the way to do this through use of the DDEML library.

If an application wants to include facilities to show data types such as Microsoft Excel graphs or sound files provided by OLE servers, OLE client support should be added.

If an application has data-rendering capability useful to other applications, it should become an OLE server.

Bibliography

For more information on the Clipboard, DDE, and OLE, consult the following publications.

Clipboard

Petzold, Charles. Programming Windows 3.1. 3d ed. Microsoft Press, 1992.

Microsoft Windows version 3.1 Software Development Kit Guide to Programming. Microsoft Corporation, 1987-1992. (MSDN Library Archive Edition)

Microsoft Windows version 3.1 Software Development Kit Programmer's Reference, Volume 1: Overview and Programmer's Reference, Volume 2: Functions. Microsoft Corporation, 1987-1992. (MSDN Library Archive Edition)

DDE

We recommend that you implement DDE through DDEML to make the task easier and to ensure that your code is protected against changes to the way the DDE protocol may be implemented in the future.

Petzold, Charles. Programming Windows 3.1. 3d ed. Microsoft Press, 1992. (MSDN Library Archive Edition)

Microsoft Windows version 3.1 Software Development Kit Guide to Programming. Microsoft Corporation, 1987-1992. (MSDN Library Archive Edition)

Microsoft Windows version 3.1 Software Development Kit Programmer's Reference, Volume 1: Overview and Programmer's Reference, Volume 2: Functions. Microsoft Corporation, 1987-1992. (MSDN Library Archive Edition)

Staab, Sanford A. "Raw DDE," 1992. (MSDN Library, Technical Articles, Platform Articles)

OLE

OLE is implemented through the OLE client and server libraries and can be implemented in C or C++. C++ implementations can benefit from using the OLE classes in the Microsoft Foundation Class libraries.

Microsoft Windows version 3.1 Software Development Kit Guide to Programming. Microsoft Corporation, 1987-1992. (MSDN Library Archive Edition)

Microsoft Windows version 3.1 Software Development Kit Programmer's Reference, Volume 1: Overview and Programmer's Reference, Volume 2: Functions. Microsoft Corporation, 1987-1992. (MSDN Library Archive Edition)

"MFC TN008—General OLE Overview," (MSDN Library, Developer Products, Visual C/C++, Microsoft Foundation Class Reference)

"MFC TN009—Writing an OLE Client Application," (MSDN Library, Developer Products, Visual C/C++, Microsoft Foundation Class Reference)

"MFC TN010—Writing an OLE Server Application," (MSDN Library, Developer Products, Visual C/C++, Microsoft Foundation Class Reference)