Figure 1    CMyClient Methods


 ULONG __stdcall CMyClient::XStockInfo::AddRef ()
 {
     METHOD_PROLOGUE (CMyClient, StockInfo)
     return pThis->ExternalAddRef ();
 }
 
 ULONG __stdcall CMyClient::XStockInfo::Release ()
 {
     METHOD_PROLOGUE (CMyClient, StockInfo)
     return pThis->ExternalRelease ();
 }
 
 HRESULT __stdcall CMyClient::XStockInfo::QueryInterface (REFIID riid,
     void** ppv)
 {
     METHOD_PROLOGUE (CMyClient, StockInfo)
     return pThis->ExternalQueryInterface (&riid, ppv);
 }
 
 HRESULT __stdcall CMyClient::XStockInfo::NewValue (long lPrice)
 {
     // Your code goes here.
 }

Figure 3   CPServer

DlgProxy.h


 // DlgProxy.h : header file
 //
 
 #if !defined(AFX_DLGPROXY_H__F7AC4B0B_B1D1_11D1_8E53_006008A82731__INCLUDED_)
 #define AFX_DLGPROXY_H__F7AC4B0B_B1D1_11D1_8E53_006008A82731__INCLUDED_
 
 #if _MSC_VER >= 1000
 #pragma once
 #endif // _MSC_VER >= 1000
 
 #include "Cpproxy.h"
 #include "OleSingleObjectFactory.h"
 
 //
 // New macros to replace DECLARE_OLECREATE and IMPLEMENT_OLECREATE
 //
 #define DECLARE_OLECREATE_CUSTOM(class_name, classfactory_name) \
 public: \
     static AFX_DATA classfactory_name factory; \
     static AFX_DATA const GUID guid; \
 
 #define IMPLEMENT_OLECREATE_CUSTOM(class_name, classfactory_name, external_name,\  	    l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
     AFX_DATADEF classfactory_name class_name::factory(class_name::guid, \
         RUNTIME_CLASS(class_name), FALSE, _T(external_name)); \
     const AFX_DATADEF GUID class_name::guid = \
         { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \
 
 class CServerDlg;
 
 /////////////////////////////////////////////////////////////////////////////
 // CAutoProxy command target
 
 class CAutoProxy : public CCmdTarget
 {
     DECLARE_DYNCREATE(CAutoProxy)
 
     CAutoProxy();           // protected constructor used by dynamic creation
 
 // Attributes
 public:
     CServerDlg* m_pDialog;
 
 // Operations
 public:
 
 // Overrides
     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CAutoProxy)
     public:
     virtual void OnFinalRelease();
     //}}AFX_VIRTUAL
 
 // Implementation
 protected:
     long m_lPos;
     virtual ~CAutoProxy();
     void MulticastPositionChange(long lPos);
 
     // Generated message map functions
     //{{AFX_MSG(CAutoProxy)
         // NOTE - the ClassWizard will add and remove member functions here.
     //}}AFX_MSG
 
     DECLARE_MESSAGE_MAP()
     DECLARE_OLECREATE_CUSTOM(CAutoProxy, COleSingleObjectFactory)
 
     BEGIN_INTERFACE_PART(Position, IPosition)
         virtual HRESULT __stdcall SetPos (long lPos);
         virtual HRESULT __stdcall GetPos (long* plPos);
     END_INTERFACE_PART(Position)
 
     DECLARE_INTERFACE_MAP()
 
     BEGIN_CONNECTION_PART (CAutoProxy, NotifyPosCP)
         CONNECTION_IID (IID_INotifyPos)
     END_CONNECTION_PART (NotifyPosCP)
 
     DECLARE_CONNECTION_MAP ()
 };
 
 /////////////////////////////////////////////////////////////////////////////
 
 //{{AFX_INSERT_LOCATION}}
 // Microsoft Developer Studio will insert additional declarations immediately  	// before the previous line.
 
 #endif // !defined(AFX_DLGPROXY_H__F7AC4B0B_B1D1_11D1_8E53_006008A82731__INCLUDED_)

DlgProxy.cpp


 // DlgProxy.cpp : implementation file
 //
 
 #include "stdafx.h"
 #include "CPServer.h"
 #include "DlgProxy.h"
 #include "CPServerDlg.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 const IID IID_IPosition = { 0xAA393021, 0xB04D, 0x11D1,
     { 0x8E, 0x53, 0x00, 0x60, 0x08, 0xA8, 0x27, 0x31 }};
 
 const IID IID_INotifyPos = { 0xAA393021, 0xB04D, 0x11D1,
     { 0x8E, 0x53, 0x00, 0x60, 0x08, 0xA8, 0x27, 0x32 }};
 
 /////////////////////////////////////////////////////////////////////////////
 // CAutoProxy
 
 IMPLEMENT_DYNCREATE(CAutoProxy, CCmdTarget)
 
 CAutoProxy::CAutoProxy()
 {
     EnableConnections ();    // Very important!
 
     // To keep the application running as long as an OLE automation 
     // object is active, the constructor calls AfxOleLockApp.
     AfxOleLockApp();
 
     // Get access to the dialog through the application's
     // main window pointer.  Set the proxy's internal pointer
     // to point to the dialog, and set the dialog's back pointer to
     // this proxy.
     ASSERT (AfxGetApp()->m_pMainWnd != NULL);
     ASSERT_VALID (AfxGetApp()->m_pMainWnd);
     ASSERT_KINDOF(CServerDlg, AfxGetApp()->m_pMainWnd);
     m_pDialog = (CServerDlg*) AfxGetApp()->m_pMainWnd;
     m_pDialog->m_pAutoProxy = this;
     m_lPos = 0;
 }
 
 CAutoProxy::~CAutoProxy()
 {
     // To terminate the application when all objects created with
     // with OLE automation, the destructor calls AfxOleUnlockApp.
     // Among other things, this will destroy the main dialog
     AfxOleUnlockApp();
 }
 
 void CAutoProxy::OnFinalRelease()
 {
     // When the last reference for an automation object is released
     // OnFinalRelease is called.  The base class will automatically
     // deletes the object.  Add additional cleanup required for your
     // object before calling the base class.
 
     CCmdTarget::OnFinalRelease();
 }
 
 BEGIN_MESSAGE_MAP(CAutoProxy, CCmdTarget)
     // {{AFX_MSG_MAP(CAutoProxy)
         // NOTE - the ClassWizard will add and remove mapping macros here.
     // }}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
 BEGIN_INTERFACE_MAP(CAutoProxy, CCmdTarget)
     INTERFACE_PART (CAutoProxy, IID_IPosition, Position)
     INTERFACE_PART (CAutoProxy, IID_IConnectionPointContainer,
         ConnPtContainer)
 END_INTERFACE_MAP()
 
 BEGIN_CONNECTION_MAP (CAutoProxy, CCmdTarget)
     CONNECTION_PART (CAutoProxy, IID_INotifyPos, NotifyPosCP)
 END_CONNECTION_MAP ()
 
 IMPLEMENT_OLECREATE_CUSTOM (CAutoProxy, COleSingleObjectFactory,
     "CPServer.Object", 0xb478e241, 0xb06d, 0x11d1, 0x8e, 0x53, 0x00,
     0x60, 0x08, 0xa8, 0x27, 0x31)
 
 void CAutoProxy::MulticastPositionChange(long lPos)
 {
     const CPtrArray* pConnections = m_xNotifyPosCP.GetConnections ();
     ASSERT (pConnections != NULL);
 
     int nConnections = pConnections->GetSize ();
 
     if (nConnections) {
         for (int i=0; i<nConnections; i++) {
             INotifyPos* pInterface =
                 (INotifyPos*) (pConnections->GetAt (i));
             ASSERT (pInterface != NULL);
             pInterface->NewPos (lPos); // Outgoing!
         }
     }
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // IPosition methods
 
 ULONG __stdcall CAutoProxy::XPosition::AddRef ()
 {
     METHOD_PROLOGUE (CAutoProxy, Position)
     return pThis->ExternalAddRef ();
 }
 
 ULONG __stdcall CAutoProxy::XPosition::Release ()
 {
     METHOD_PROLOGUE (CAutoProxy, Position)
     return pThis->ExternalRelease ();
 }
 
 HRESULT __stdcall CAutoProxy::XPosition::QueryInterface (REFIID riid,
     void** ppv)
 {
     METHOD_PROLOGUE (CAutoProxy, Position)
     return pThis->ExternalQueryInterface (&riid, ppv);
 }
 
 HRESULT __stdcall CAutoProxy::XPosition::SetPos (long lPos)
 {
     METHOD_PROLOGUE (CAutoProxy, Position)
     pThis->m_lPos = lPos;
     pThis->m_pDialog->SetDlgItemInt (IDC_POS, (UINT) pThis->m_lPos);
     pThis->MulticastPositionChange (pThis->m_lPos);
     return S_OK;
 }
 
 HRESULT __stdcall CAutoProxy::XPosition::GetPos (long* plPos)
 {
     METHOD_PROLOGUE (CAutoProxy, Position)
     *plPos = pThis->m_lPos;
     return S_OK;
 }

OleSingleObjectFactory.h


 #if !defined(AFX_OLESINGLEOBJECTFACTORY_H__7010CC01_52F1_11D1_B2D9_444553540000__INCLUDED_)
 #define AFX_OLESINGLEOBJECTFACTORY_H__7010CC01_52F1_11D1_B2D9_444553540000__INCLUDED_
 
 #if _MSC_VER >= 1000
 #pragma once
 #endif // _MSC_VER >= 1000
 // OleSingleObjectFactory.h : header file
 //
 
 /////////////////////////////////////////////////////////////////////////////
 // COleSingleObjectFactory
 
 class COleSingleObjectFactory : public COleObjectFactory
 {
 
 // Attributes
 public:
     COleSingleObjectFactory(REFCLSID clsid, CRuntimeClass* pRuntimeClass,
         BOOL bMultiInstance, LPCTSTR lpszProgID);
     virtual ~COleSingleObjectFactory();
 
 protected:
     CCmdTarget* m_pObject;
 
 // Operations
 public:
 
 // Overrides
     // ClassWizard generated virtual function overrides
     // {{AFX_VIRTUAL(COleSingleObjectFactory)
     // }}AFX_VIRTUAL
 
 // Implementation
 protected:
     virtual CCmdTarget* OnCreateObject ();
 
     // Generated message map functions
     // {{AFX_MSG(COleSingleObjectFactory)
         // NOTE - the ClassWizard will add and remove member functions here.
     //}}AFX_MSG
 
     DECLARE_MESSAGE_MAP()
 };
 
 /////////////////////////////////////////////////////////////////////////////
 
 // {{AFX_INSERT_LOCATION}}
 // Microsoft Developer Studio will insert additional declarations immediately 	// before the previous line.
 
 #endif // !defined(AFX_OLESINGLEOBJECTFACTORY_H__7010CC01_52F1_11D1_B2D9_444553540000__INCLUDED_)

OleSingleObjectFactory.cpp


 // OleSingleObjectFactory.cpp : implementation file
 //
 
 #include "stdafx.h"
 #include "OleSingleObjectFactory.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 /////////////////////////////////////////////////////////////////////////////
 // COleSingleObjectFactory
 
 COleSingleObjectFactory::COleSingleObjectFactory (REFCLSID clsid,
     CRuntimeClass* pRuntimeClass, BOOL bMultiInstance, LPCTSTR lpszProgID) :
     COleObjectFactory (clsid, pRuntimeClass, bMultiInstance, lpszProgID)
 {
     m_pObject = NULL;
 }
 
 COleSingleObjectFactory::~COleSingleObjectFactory()
 {
 }
 
 
 BEGIN_MESSAGE_MAP(COleSingleObjectFactory, COleObjectFactory)
     //{{AFX_MSG_MAP(COleSingleObjectFactory)
         // NOTE - the ClassWizard will add and remove mapping macros here.
     //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
 /////////////////////////////////////////////////////////////////////////////
 // COleSingleObjectFactory message handlers
 
 CCmdTarget* COleSingleObjectFactory::OnCreateObject ()
 {
     if (m_pObject == NULL)
         m_pObject = COleObjectFactory::OnCreateObject ();
     return m_pObject;
 }

Figure 4   CPClient

CPClientDlg.h


 // CPClientDlg.h : header file
 //
 
 #if !defined(AFX_CPCLIENTDLG_H__BF7C3CE8_B069_11D1_8E53_006008A82731__INCLUDED_)
 #define AFX_CPCLIENTDLG_H__BF7C3CE8_B069_11D1_8E53_006008A82731__INCLUDED_
 
 #if _MSC_VER >= 1000
 #pragma once
 #endif // _MSC_VER >= 1000
 
 /////////////////////////////////////////////////////////////////////////////
 // CClientDlg dialog
 
 class CClientDlg : public CDialog
 {
     DECLARE_DYNCREATE (CClientDlg)
 
 // Construction
 public:
     CClientDlg(CWnd* pParent = NULL);    // standard constructor
 
 // Dialog Data
     //{{AFX_DATA(CClientDlg)
     enum { IDD = IDD_CPCLIENT_DIALOG };
     CSliderCtrl    m_wndSlider;
     //}}AFX_DATA
 
     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CClientDlg)
     protected:
     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
     //}}AFX_VIRTUAL
 
 // Implementation
 protected:
     DWORD m_dwConnectID;
     IPosition* m_pPosition;
     HICON m_hIcon;
 
     // Generated message map functions
     //{{AFX_MSG(CClientDlg)
     virtual BOOL OnInitDialog();
     afx_msg void OnPaint();
     afx_msg HCURSOR OnQueryDragIcon();
     afx_msg void OnClose();
     afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()
 
     BEGIN_INTERFACE_PART(NotifyPos, INotifyPos)
         virtual HRESULT __stdcall NewPos (long lPos);
     END_INTERFACE_PART(NotifyPos)
 
     DECLARE_INTERFACE_MAP ()
 };
 
 // {{AFX_INSERT_LOCATION}}
 // Microsoft Developer Studio will insert additional declarations immediately 	// before the previous line.
 
 #endif // !defined(AFX_CPCLIENTDLG_H__BF7C3CE8_B069_11D1_8E53_006008A82731__INCLUDED_)

CPClientDlg.cpp


 // CPClientDlg.cpp : implementation file
 //
 
 #include "stdafx.h"
 #include "cpproxy.h"
 #include "CPClient.h"
 #include "CPClientDlg.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 const CLSID CLSID_CPServer = { 0xb478e241, 0xb06d, 0x11d1,
     { 0x8e, 0x53, 0x00, 0x60, 0x08, 0xa8, 0x27, 0x31 }};
 
 const IID IID_IPosition = { 0xAA393021, 0xB04D, 0x11D1,
     { 0x8E, 0x53, 0x00, 0x60, 0x08, 0xA8, 0x27, 0x31 }};
 
 const IID IID_INotifyPos = { 0xAA393021, 0xB04D, 0x11D1,
     { 0x8E, 0x53, 0x00, 0x60, 0x08, 0xA8, 0x27, 0x32 }};
 
 /////////////////////////////////////////////////////////////////////////////
 // CClientDlg dialog
 
 CClientDlg::CClientDlg(CWnd* pParent /*=NULL*/)
     : CDialog(CClientDlg::IDD, pParent)
 {
     // {{AFX_DATA_INIT(CClientDlg)
     // NOTE: the ClassWizard will add member initialization here
     // }}AFX_DATA_INIT
     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
     m_pPosition = NULL;
 }
 
 void CClientDlg::DoDataExchange(CDataExchange* pDX)
 {
     CDialog::DoDataExchange(pDX);
     //{{AFX_DATA_MAP(CClientDlg)
     DDX_Control(pDX, IDC_SLIDER, m_wndSlider);
     //}}AFX_DATA_MAP
 }
 
 BEGIN_MESSAGE_MAP(CClientDlg, CDialog)
     //{{AFX_MSG_MAP(CClientDlg)
     ON_WM_PAINT()
     ON_WM_QUERYDRAGICON()
     ON_WM_CLOSE()
     ON_WM_HSCROLL()
     //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
 BEGIN_INTERFACE_MAP (CClientDlg, CDialog)
     INTERFACE_PART (CClientDlg, IID_INotifyPos, NotifyPos)
 END_INTERFACE_MAP ()
 
 IMPLEMENT_DYNCREATE (CClientDlg, CDialog)
 
 /////////////////////////////////////////////////////////////////////////////
 // CClientDlg message handlers
 
 BOOL CClientDlg::OnInitDialog()
 {
     CDialog::OnInitDialog();
 
     // Set the icon for this dialog.  The framework does this automatically
     //  when the application's main window is not a dialog
     SetIcon(m_hIcon, TRUE);            // Set big icon
     SetIcon(m_hIcon, FALSE);        // Set small icon
     
     //
     // Set the slider control's range.
     //
     m_wndSlider.SetRange (0, 10);    
     
     //
     // Create the object (or connect to a running instance).
     //
     HRESULT hr = ::CoCreateInstance (CLSID_CPServer,
         NULL, CLSCTX_SERVER, IID_IPosition, (void**) &m_pPosition);
 
     if (FAILED (hr)) {
         MessageBox ("CoCreateInstance failed", "Error", MB_OK);
         return TRUE;
     }
 
     //
     // Set the slider control's position.
     //
     long lPos;
     m_pPosition->GetPos (&lPos);
     m_wndSlider.SetPos ((int) lPos);    
 
     //
     // Get a pointer to our own INotifyPos interface.
     //
     INotifyPos* pNotifyPos;
     hr = m_xNotifyPos.QueryInterface (IID_INotifyPos, (void**) &pNotifyPos);
     ASSERT (SUCCEEDED (hr));
     m_xNotifyPos.Release ();    // Undo the AddRef performed by QueryInterface
 
     //
     // Plug into the server's connection point.
     //
     if (!AfxConnectionAdvise (m_pPosition, IID_INotifyPos, pNotifyPos,
         FALSE, &m_dwConnectID)) {
         MessageBox ("AfxConnectionAdvise failed", "Error", MB_OK);
         return TRUE;
     }
     return TRUE;
 }
 
 // If you add a minimize button to your dialog, you will need the code below
 // to draw the icon. For MFC applications using the document/view model,
 // this is automatically done for you by the framework.
 
 void CClientDlg::OnPaint() 
 {
     if (IsIconic())
     {
         CPaintDC dc(this); // device context for painting
 
         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
 
         // Center icon in client rectangle
         int cxIcon = GetSystemMetrics(SM_CXICON);
         int cyIcon = GetSystemMetrics(SM_CYICON);
         CRect rect;
         GetClientRect(&rect);
         int x = (rect.Width() - cxIcon + 1) / 2;
         int y = (rect.Height() - cyIcon + 1) / 2;
 
         // Draw the icon
         dc.DrawIcon(x, y, m_hIcon);
     }
     else
     {
         CDialog::OnPaint();
     }
 }
 
 // The system calls this to obtain the cursor to display while the user drags
 // the minimized window.
 HCURSOR CClientDlg::OnQueryDragIcon()
 {
     return (HCURSOR) m_hIcon;
 }
 
 void CClientDlg::OnClose() 
 {
     //
     // Disconnect from the server's connection point.
     //
     INotifyPos* pNotifyPos;
     HRESULT hr = m_xNotifyPos.QueryInterface (IID_INotifyPos,
         (void**) &pNotifyPos);
     ASSERT (SUCCEEDED (hr));
     m_xNotifyPos.Release ();
 
     AfxConnectionUnadvise (m_pPosition, IID_INotifyPos, pNotifyPos,
         FALSE, m_dwConnectID);
 
     //
     // Release the server's IPosition interface.
     //
     if (m_pPosition != NULL) {
         m_pPosition->Release ();    
         m_pPosition = NULL;
     }
     CDialog::OnClose();
 }
 
 void CClientDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
 {
     if (m_pPosition != NULL) {
         switch (nSBCode) {
 
         case TB_THUMBTRACK:
             m_pPosition->SetPos ((long) nPos);
             break;
             
         case TB_TOP:
         case TB_BOTTOM:
         case TB_LINEDOWN:
         case TB_LINEUP:
         case TB_PAGEDOWN:
         case TB_PAGEUP:
             m_pPosition->SetPos ((long) m_wndSlider.GetPos ());
             break;
         }
     }
     CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // INotifyPos methods
 
 ULONG __stdcall CClientDlg::XNotifyPos::AddRef ()
 {
     METHOD_PROLOGUE (CClientDlg, NotifyPos)
     return pThis->ExternalAddRef ();
 }
 
 ULONG __stdcall CClientDlg::XNotifyPos::Release ()
 {
     METHOD_PROLOGUE (CClientDlg, NotifyPos)
     return pThis->ExternalRelease ();
 }
 
 HRESULT __stdcall CClientDlg::XNotifyPos::QueryInterface (REFIID riid,
     void** ppv)
 {
     METHOD_PROLOGUE (CClientDlg, NotifyPos)
     return pThis->ExternalQueryInterface (&riid, ppv);
 }
 
 HRESULT __stdcall CClientDlg::XNotifyPos::NewPos (long lPos)
 {
     CClientDlg* pDlg = (CClientDlg*) AfxGetMainWnd ();
     ASSERT (pDlg->IsKindOf (RUNTIME_CLASS (CClientDlg)));
     pDlg->m_wndSlider.SetPos ((int) lPos);
     return S_OK;
 }