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;
}