Figure 4: The client side of the sample DDE application

// Application class
class CClientApp : public CWinApp
{
public:
   virtual BOOL InitInstance();
   virtual int  ExitInstance();
};

// Main window class, inherits also from DDEClient
class CMainWindow : public CFrameWnd, public DDEClient
{
   UINT   PointClipFormat; // Clipboard format for Position
   CPoint Position;        // Position of circle in client area 

public: 
   CMainWindow();

   // Overridden DDEClient's virtual functions 
   virtual BOOL 
   ReceiveAdvise(const DDEString & Item, 
      const DDEDataIn * const data, UINT format);
   virtual void 
   TransactionCompleted(const DDEString & Item,
      const DDEDataIn * const data, UINT format, DWORD UserID, 
      BOOL Ok);
   virtual void Disconnected();
   virtual void 
   Register(const DDEString & BaseServiceName, 
      const DDEString & InstanceServiceName, BOOL Register);

protected:

   // Windows message handlers
   afx_msg void OnPaint();
   afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
   afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
   afx_msg void OnMouseMove(UINT nFlags, CPoint point);
   afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
   DECLARE_MESSAGE_MAP()
};

//client.cpp

#include <afxwin.h>
#include "ddegio.h" // DDE framework
#include "Client.h"

// How to use the program:
// Click left mouse button to connect to DDE server
// Click right mouse button to disconnect from server
// Move mouse on client area to send position to server
// Doubleclick left button to send Maximize command

CClientApp ClientApp;

BOOL CClientApp::InitInstance()
{
   DDEInitialize(); // Framework initialization
   m_pMainWnd=new CMainWindow;
   m_pMainWnd->ShowWindow(m_nCmdShow);
   m_pMainWnd->UpdateWindow();
   return TRUE;
}

int CClientApp::ExitInstance()
{
   DDEUninitialize(); // Framework cleanup
   return CWinApp::ExitInstance();
}


BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)
  ON_WM_PAINT()
  ON_WM_MOUSEMOVE()
  ON_WM_LBUTTONDOWN()
  ON_WM_RBUTTONDOWN()
  ON_WM_LBUTTONDBLCLK()
 END_MESSAGE_MAP()

CMainWindow::CMainWindow()
   : Position(0,0),
     PointClipFormat(RegisterClipboardFormat("POINT")) 
{
   Create(NULL,"DDE Client"); // Create main window
}

// Draw status of client and rectangle at current position
void CMainWindow::OnPaint()
{
   CPaintDC DC(this);
   CString Status=IsConnected()?"Connected":"Disconnected";
   DC.TextOut(0,0,Status);
   DC.Rectangle(Position.x-9, Position.y-9, 
      Position.x+9,Position.y+9);
}

// Try to connect to server if not already connected
// If it connects, it also requests current circle position
// and starts advise link on it
void CMainWindow::OnLButtonDown(UINT nFlags, CPoint point)
{
   if (!IsConnected() && Connect("DDEServerTest","Mouse"))
   {
      Request("Position",NULL,PointClipFormat,111);
      StartAdvise("Position",FALSE,FALSE,PointClipFormat,222);
   } 
}

// Disconnect from DDE server 
void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point)
{
   if (IsConnected())
   {
      Disconnect();
      InvalidateRect(NULL);
   }
}

// Tell the server the new position for its circle
void CMainWindow::OnMouseMove(UINT nFlags, CPoint point)
{
   if (IsConnected()) // Asyncronous to avoid reentrancy problems
      Poke("Position",&point,sizeof(point),PointClipFormat,333);
}

// Send maximize command to server
void CMainWindow::OnLButtonDblClk(UINT nFlags, CPoint point)
{
   if (IsConnected()) 
      Execute("[Maximize()]",444); // Asynchronous
}

// Receive new position of server's circle when it changes
BOOL 
CMainWindow::ReceiveAdvise(const DDEString & Item, 
   const DDEDataIn * const pData, UINT format)
{
   if (Item=="Position" && pData!=NULL)
   {
      memcpy(&Position,pData->GetData(),sizeof(Position));
      InvalidateRect(NULL);
      return TRUE;
   }
   else return FALSE;
}

// Receive notification that asynchronous transaction completed
void 
CMainWindow::TransactionCompleted(const DDEString & Item,
   const DDEDataIn * const pData,UINT format,DWORD UserID,BOOL Ok)
{
   // I only care when a request transaction completes
   // I started the request transaction with ID 111
   if (Ok && UserID==111 && pData!=NULL)
   {
      memcpy(&Position,pData->GetData(),sizeof(Position));
      InvalidateRect(NULL);
   } 
}

// Receive notification that client got disconnected
void CMainWindow::Disconnected()
{
   InvalidateRect(NULL);
}

// Flash your window when a server registers a service
void 
CMainWindow::Register(const DDEString & BaseServiceName, 
const DDEString & InstanceServiceName, BOOL Register)
{
   TRACE("A server %sregistered the %s service\n", 
      Register?"":"un", (LPCSTR)BaseServiceName);
}

// Report DDE errors
void ReportDDEErrorToApp(UINT,LPCSTR message)
{
   MessageBox(AfxGetMainWnd()->GetSafeHwnd(),
      message,"Dde Error",MB_OK);
}

/*
// Just to show you a synchronous request
void CMainWindow::ShowYouSynchronousRequestTransaction()
{
   if (IsConnected())
    {
      DDEDataIn Data;
      if (Request("Position",&Data) && 
          Data.GetSize()>=sizeof(Position))
      {
         memcpy(&Position,Data.GetData(),sizeof(Position));
         InvalidateRect(NULL);
      }
    }
}
*/