Figure 2: The DDEClient class. Only the most important members are shown here.

class DDEClient 
{
   HCONV hConversation;       // Handle of DDE conversation
   UINT  TimeOut;             // Timeout for synchronous transactions

   DDEString Service;         // Service name
   DDEString Topic;           // Topic name
   
   static CMapPtrToPtr ClientMap; // Maps conv handles to DDEClient
                                  // objects
   static CPtrList ClientList;    // List of all DDEClient objects

   //..............

 public:

   // Constructor and destructor
   DDEClient();
   virtual ~DDEClient();

   // Client conversation connection, use to start/stop connections
   // Connects to service/topic unless already connected there
   BOOL Connect(const DDEString & service, const DDEString & topic); 
   BOOL Disconnect();  // Disconnects from service
   
   // Functions that start client transactions follow:
   // For the meaning of each transaction see DDE documentation.

   // Start a request transaction. Pass a DDEDataIn object where
   // the data will be put. For asynchronous transactions, you can
   // pass NULL as the DDEDataIn pointer. 
   BOOL
   Request(const DDEString & Item, DDEDataIn * Data,
      UINT format=CF_TEXT, DWORD AsyncUserID=SYNC_TRAN,
      LPDWORD pdwResult=NULL);

   // Send unsolicited data to the server. The data is pointed to
   // by ptrData.
   BOOL
   Poke(const DDEString & Item, LPCVOID ptrData,
      DWORD length=ZERO_TERMINATED, UINT format=CF_TEXT,
      DWORD AsyncUserID=SYNC_TRAN, LPDWORD pdwResult=NULL);

   // Send a DDE execute string to the server
   BOOL
   Execute(LPCSTR sCommand, DWORD AsyncUserID=SYNC_TRAN,
      LPDWORD pdwResult=NULL);

   // Start an advise link.
   BOOL
   StartAdvise(const DDEString & Item, BOOL Warm=FALSE,
      BOOL ackRequired=FALSE, UINT format=CF_TEXT,
      DWORD AsyncUserID=SYNC_TRAN, LPDWORD pdwResult=NULL);

   // Stop an advise link.
   BOOL
   StopAdvise(const DDEString & Item, UINT format=CF_TEXT,
      DWORD AsyncUserID=SYNC_TRAN, LPDWORD pdwResult=NULL);

   //.................      
                                                        
                                                       
   // Virtual functions to redefine to handle DDE events 
   // Redefine them to implement your own event handling

   // Called when server sends us advise data (data=NULL for
   // warm link)
   virtual BOOL
   ReceiveAdvise(const DDEString & Item,
      const DDEDataIn * const data, UINT format)
         {return FALSE;} // Return TRUE if you accept the data
   
   // Called when an async transaction has completed (data=NULL
   // if no data is passed)
   virtual void
   TransactionCompleted(const DDEString & Item,
      const DDEDataIn * const data, UINT format,
      DWORD UserID,BOOL Ok)
         {}
   
   // Called when we got disconnected by the server
   virtual void Disconnected()
         {}
   
   // Called when services are registered/unregistered in system.
   // Register=FALSE for Unregister
   virtual void
   Register(const DDEString & BaseServiceName,
      const DDEString & InstanceServiceName, BOOL Register)
         {}
   
   // Called when a DDE memory error occurs, release your data and
   // close conversations if possible. Can get passed the handle of
   // the conversation causing the error or NULL
   virtual void OnError(HCONV hConvError)
         {}


  private: // Private functions
   
   // DDE Callback function that dispatches transactions to clients
   // and servers
   friend HDDEDATA CALLBACK
   DDECallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD);   

   // DDE Callback function where all client DDE transactions
   // get dispatched
   HDDEDATA
   DDEClientCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA,
      DWORD, DWORD);