Programmer's Reference

Building a DDE server that uses default processing

To build a DDE server application that uses default processing, do the following:

  1. Create a DdeServerManager.
  2. Build the default database by sending the addItem:topic:value:format: message to the DdeServerManager for each item that you want to make available to DDE clients.
  3. Send the updateItem:topic:value:format: message to the DdeServerManager each time the value of the item changes.
  4. When the application is finished, send the free message to the DdeServerManager.

By using default processing, the DdeServerManager (along with the default database) handles all connection requests from DDE clients as well as requests for hotlinks, warmlinks, coldlinks, and data.

By default, data sent from any DDE client to your DdeServerManager (a poke, in DDE terminology) is rejected. Requests from the client for the server to run commands are also rejected. However, both of these callbacks can be hooked, enabling the application to service these requests.

An example DDE server that uses default processing

To build a DDE server application that uses default processing:

This example builds a DDE server that has the time and date in two different formats for a total of four available items. The items are as follows:

First, create a class called DdeTimeServer that is a subclass of Object. Give it the two instance variables described in Table 42.

Table 42. Instance variables for DdeTimeServer

Instance variable Description
ddeServerManager The instance of the DdeServerManager class that you are creating.
timerOn A flag indicating whether the timer is on or off. Turning the timer off is important when the server shuts down.

Your new class looks like this:

Object subclass: #DdeTimeServer
   instanceVariableNames: 'ddeServerManager timerOn '
   classVariableNames: ''
   poolDictionaries: ''

Now create a class method new to create a new server. Send the initialize method to the new object in order to set it up.

new
   "Answer a new server after initializing it."
   ^super new initialize

Before executing the new class method, you need to create the initialize method. In the initialize method, first create the DdeServerManager and name it Timer. Next, build the default database.

Note:
With the default database setup you do not have to hook into any of the callbacks provided by the DdeServerManager. All you need to do is to update the items when the timer goes off. Notice that for the format of 'String,' you pass a Smalltalk String for the data. When the format is 'Smalltalk Object,' you use the IBM Smalltalk Swapper to convert the Smalltalk object into a ByteArray. The method flatten to perform this function is specified in Converting Smalltalk objects to a ByteArray and back.
initialize
   "Private - Create and initialize a DdeServerManager. Set the name
    of the server to 'Timer' and create two items in the item database
    under the topic of 'Time'. The two items will be 'date' and 'time.'
    Support two formats for the items, a string format and a Smalltalk
    object. Support the Smalltalk object format by using the IBM 
    Smalltalk Swapper to turn a Smalltalk object into a ByteArray."
 
   | currentDate currentTime |
   ddeServerManager := DdeServerManager name: 'Timer'.
   currentTime := Time now.
   currentDate := Date today.
 
   ddeServerManager
      addItem: 'time'
      topic: 'Time'
      value: currentTime printString
      format: 'String'.
 
   ddeServerManager
      addItem: 'time'
      topic: 'Time'
      value: (self flatten: currentTime)
      format: 'Smalltalk Object'.
 
   ddeServerManager
      addItem: 'date'
      topic: 'Time'
      value: currentDate printString
      format: 'String'.
 
   ddeServerManager
      addItem: 'date'
      topic: 'Time'
      value: (self flatten: currentDate)
      format: 'Smalltalk Object'.
 
   self timerOn: true.

At the end of initialization the timer is turned on by sending the timerOn: message, which in turn sends the timerSet message. The timer uses the Common Widgets timer functionality so that when the timer goes off, the message timerProc: is sent to the application.

timerOn: aBoolean
   "Start/stop the timer depending on aBoolean."
   timerOn := aBoolean.
   self timerSet.
 
timerOn
   "Answer whether the timer is on or off."
   ^timerOn.
 
timerSet
   "If the timer is on, reset it to go off in one second."
   self timerOn ifTrue: [
      CwAppContext default
            addTimeout: 1000
            receiver: self
            selector: #timerProc:
            clientData: nil
   ]

Now all initialization has been completed. The main work of the server is now in the method that is run whenever the timer goes off. When the timer goes off and the timerProc: method is run, all the items in the default database are updated. As the items are updated, the DdeServerManager looks for any hot- or warmlinks to the data and updates the clients that are linked to those items.

timerProc: clientData
   "The timer has gone off so save the current date and time and then
    update the item database."
 
   | currentDate currentTime |
   currentTime := Time now.
   currentDate := Date today.
 
   ddeServerManager
      updateItem: 'time'
      topic: 'Time'
      value: currentTime printString
      format: 'String'.
 
   ddeServerManager
      updateItem: 'date'
      topic: 'Time'
      value: currentDate printString
      format: 'String'.
 
   ddeServerManager
      updateItem: 'time'
      topic: 'Time'
      value: (self flatten: currentTime)
      format: 'Smalltalk Object'.
 
   ddeServerManager
      updateItem: 'date'
      topic: 'Time'
      value: (self flatten: currentDate)
      format: 'Smalltalk Object'.
 
   self timerSet.

The final method that you need to implement is the free method. This method stops the timer and frees up the DdeServerManager.

free
   "Close down by stopping the timer and freeing up the 
    DdeServerManager."
 
   self timerOn: false.
   ddeServerManager free.

You now have a DDE server that not only provides the current time and date to any DDE client but also allows access to the Systems Topics that should be supported by all servers.

In this example server, the time and date are both updated when the timer goes off. An improvement to the code might be to only update the date (and possibly the time) if it has changed since the previous update.


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]