Herman Rodent, staff burrower
Microsoft Developer Network Technology Group
Created: October 1, 1992
Click to open or copy the files in the DDERecon sample application for this technical article.
Dynamic data exchange (DDE) is a powerful feature of the Microsoft® Windows™ operating environment. DDE provides a protocol through which applications can exchange data of all sorts. DDE enables applications to form hot links with DDE servers and obtain data in real time. A hot link is a direct data feed from one application (a DDE server) to another (a DDE client). As the data changes at the server, the server sends the new information to the client to be processed.
This article shows a technique for browsing DDE servers that may be used in a dialog box to establish a hot link and discusses the process required to reestablish a hot link when an application is restarted.
A sample application is included that demonstrates establishing a link and reestablishing the link when the application is started again later.
Dynamic data exchange (DDE) has been a part of Microsoft® Windows™ since version 2.1 was released. Since then it has been built into many applications and is used as the base mechanism for Object Linking and Embedding (OLE) version 1.0. Implementing a complete version of the DDE protocol is not a trivial matter; the result has been slight variations as different developers interpreted the specification.
The recently introduced dynamic data exchange management library (DDEML) provides a set of functions for DDE and implements the protocol on behalf of an application. Applications written to use DDEML are, therefore, more consistent in their behavior and communicate better with each other than those that don't use DDEML. Development of DDE support in an application is also much simpler when DDEML is used.
Even with DDEML, a substantial amount of work remains to be done in implementing DDE fully. This article proposes some conventions to follow when doing this work and provides some example code that shows how popular applications such as Microsoft Excel support DDE. The sample code can be directly included into your own application.
This document assumes that all DDE is done via the DDEML interface.
A server is an application that provides one or more DDE services. A service name is the name of a DDE service provided by a server. A server may provide one or more services. Commonly, a server only provides a single service and the name of that service is the same as the name of the server. Having a single name for both server and service is especially convenient when it comes time to reconnect a conversation—if the server is not started for that service, the client can infer the name of the application to start from the service name.
If you are creating a DDE server, it's a good idea to name the service and the server by the same name and have the server support only one service. If you must support multiple service names in a single server, you will have to publish the list of service names so that users of other applications can use them.
Microsoft Excel assumes the service and server names to be identical.
DDE server applications such as Microsoft Excel publish in their user documentation the names of the various topics they support. In order to connect to such a server from a client application, the user is often required to type in the name of the service (usually the same as the server application name), the name of the topic, and the name of the item of interest.
DDE servers that support the System topic can be interrogated for a list of the topics they support and the items supported for each of those topics. Given this functionality, a DDE client application can show a dialog box to allow a user to browse the currently registered set of DDE services and make a connection by clicking to select a service, topic, and item.
Because not all servers support the System topic service, and those that do support it often don't implement all of the topics needed to create the topic and item lists, the dialog box needs also to allow direct entry of the service, topic, and item names.
Figure 1 shows the connection dialog box from the DDERecon sample application.
Figure 1. The DDERecon connection dialog box
The left list box in Figure 1 shows the currently registered DDE services. In this case, both the StockSrv sample and Microsoft Word for Windows were running when the dialog box was invoked. The stock service is selected, so the middle list box shows all the topics available for this service. The StockSrv server supports the System topic fully, so the name of this specific topic is included in the list. Because including the System topic information from the server provides no useful purpose to most end users, the sample dialog box code includes a switch to ignore this information, which makes for a simpler, cleaner display.
Figure 2. The connection dialog box with the system items suppressed
Figure 2 shows the same Create DDE Link dialog box as in Figure 1, but with the System topic and items suppressed. The middle list box shows the "Prices" topic selected, and the right list box shows the items available for the "Prices" topic. Note that the "Formats" and "TopicItemList" entries are part of the server System topic support and are also excluded if the programmer selects the suppression option. The DDERecon sample includes a menu option to turn the display of the system information on and off.
DDE client applications that use DDE advise requests to obtain data from DDE servers have to reestablish conversations with their servers each time the client application is restarted.
We'll look at the steps required to reestablish a link, given the name of the service, topic and item.
A developer can design an application to reconnect DDE conversations without user involvement or to ask a user if he or she wants to reconnect. Automatic connection is convenient in many cases but can be inconvenient in an application such as Microsoft Excel, where a series of macros to process DDE data are under development, and the developer doesn't want the link brought up while the code to support it is still being written. Automatic connection might also be inconvenient if an application is being started simply to see what state the data was in last time it was used and not to see the current state of the data.
Figure 3 shows the message box that the DDERecon application uses to ask users if they want the link reestablished.
Figure 3. A request to reconnect a specific link
The message box in Figure 3 asks the user to decide on reconnection of a specific topic/item pair on a specific service. In some applications (such as Microsoft Excel) many hot links may exist; in such a case, it might be better to provide a single message box that asks if the user wants to try to reconnect all the links rather than one that asks about each one individually. Figure 4 shows the dialog box Microsoft Excel uses to request this information.
Figure 4. A request to reestablish all hot links
Note here that Microsoft Excel's dialog box has a Help button. Not a bad idea, considering that most end users have a very limited understanding of what a "remote link" might be.
To find out if the server the DDE client needs is already running, the client application can attempt to make a connect request using the name of the corresponding service it wants by calling the DdeConnect function. The application need not supply a topic name, only the service name. If the server is active, the connect request will succeed. (Every service must have at least one topic it supports.) Knowing the server is present, the client application can go on to request a connection for the actual topic, get the current value of the item it cares about, and finally make an advise request for the item so that it will get updated information if the item data subsequently changes.
An application can try to link to the specific topic directly by name instead of using the NULL topic, thus combining detection of the server with establishing the link. If the application links directly by name, it is necessary to look closely at the error codes returned in case the request fails and the server needs to be started. The DDERecon sample makes the connection in two steps rather than one, producing a simpler piece of code.
If the server is not currently running and, hence, the required service is not available, the application may want to ask users if they would like the client application to start the server for them. The DDERecon sample uses the dialog box in Figure 5 to find this out.
Figure 5. A request to start a service
If the user clicks Yes in the dialog box shown in Figure 5, DDERecon will try to run the server application. Because the name of the topic of interest may well be the name of a document the server will need to open in order to satisfy possible later requests, DDERecon appends the topic name to the server application name before making the execute request. For example, if DDERecon were invoking the STOCKSRV.EXE server for the topic "Prices," the function call might be:
WinExec("STOCKSRV.EXE Prices", SW_SHOWNOACTIVATE);
Microsoft Excel always starts other DDE servers this way. Microsoft Excel responds to being started this way by trying to open a file by the name supplied as the first command-line argument. Using command-line arguments this way really has nothing to do with DDE; it's the way most applications behave. Microsoft Excel does a little more than this, though—it treats open files as DDE topics. If you use the DDERecon sample to look at Microsoft Excel while it has a file open, you will see that the topic list box includes the full path of each file open at the time.
DDERecon uses the WinExec function to start the server application with the SW_SHOWNOACTIVATE flag so that the server will not get activated as it starts up. Before calling WinExec, DDERecon also makes its own application window topmost with a call to SetWindowPos using the HWND_TOPMOST option. After the call the WinExec returns, DDERecon calls SetWindowPos again, this time using HWND_NOTOPMOST. Making the client application window topmost prevents the server application window from coming up on top of the client when it's started. For more detail on WinExec, see "Z-Order Changes with WinExec" in the technical article "Ask Dr. GUI #4" on the Microsoft Developer Network CD (Technical Articles, Ask Dr. GUI).
As the server starts, it registers its DDE service name and does whatever other initialization it requires before it calls GetMessage for the first time. When the server initialization is complete, the call DDERecon made to WinExec returns. After return from the WinExec call, DDERecon can immediately connect to the service registered by the server.
There is a potential problem with using WinExec or LoadModule to start an application. The problem stems from the fact that the application may not be in the search paths that Windows uses. It is increasingly common to install an application (Microsoft Excel, for example) in a directory of its own name and not to add that directory to the MS-DOS® path because of exceeding the MS-DOS path length limit.
The DDERecon sample assumes the server is on the path. If the call to WinExec fails, DDERecon simply puts up the message box in Figure 6.
Figure 6. The message when WinExec fails
The message in Figure 6 is a horrible one to present to a user, so don't! You'll find more information on this path problem and a sample application that shows how to deal with it in the technical article "Launching Other Windows-Based Applications" on the Microsoft Developer Network CD (Technical Articles, Windows Articles, Kernel and Drivers Articles).
Once the server has started, DDERecon can use the DdeConnect call to establish a conversation on the topic of interest. Having established a conversation on the topic, DDERecon makes a call to DdeClientTransaction with XTYP_REQUEST to get the current state of the item it wants. To complete the process of reestablishing the hot link, DDERecon calls DdeClientTransaction again, but this time with XTYP_ADVSTART to establish an advise request on the required item. Having done this, the server will send DDERecon data every time the item data changes. The data is received by the client in an XTYP_ADVDATA transaction in its DDE callback function.
Although there is little technical difficulty from a developer's perspective in browsing DDE servers or establishing hot links with them, users often find the whole business of dealing with DDE confusing. Therefore, in incorporating DDE in your product, try to be as considerate of the user as possible. Make sure that the user understands the consequences of certain actions, such as pressing a button, entering text in a dialog box, or responding to a message. It is also very important to be as clear and specific as possible when reporting problems to the user so that the user understands what has gone wrong.