Goal:
Create a project where we use a COM client with Connection Point function.
Preface:
(1) VC6 IDE is necessary
Steps:
(1) Create a Win32 Console Application project
(2) create a simple "hello world" application
(3) Prepare to create a new class "Sink"
(4) "Sink" Class should derive from _IAddEvents, where is used to connect COM server.
(5) Just press "ok" when meeting this message
(6) Sink.h sample code
// Sink.h: interface for the CSink class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_SINK_H__F90A535B_4A71_433A_9A96_DE06BBEAB53C__INCLUDED_)
#define AFX_SINK_H__F90A535B_4A71_433A_9A96_DE06BBEAB53C__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "../Test_COM_Connection_Point/Test_COM_Connection_Point.h"
#import "../Test_COM_Connection_Point/Test_COM_Connection_Point.tlb" named_guids raw_interfaces_only
#include <stdio.h>
class CSink : public _IAddEvents
{
private:
DWORD m_dwRefCount;
public:
CSink();
virtual ~CSink();
// added by Mark manually -- Start
STDMETHODIMP ExecutionOver(int Result)
{
printf("CSink::ExecutionOver::The result is %d", Result);
return S_OK;;
};
//IUnknown member functions -- QueryInteface, AddRef, ReleaseRef
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
if (iid == DIID__IAddEvents)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
}
if (iid == IID_IUnknown)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
return m_dwRefCount;
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG l;
l = m_dwRefCount--;
if ( 0 == m_dwRefCount)
delete this;
return l;
}
// IDispatch member functions -- GetIDsOfNames, GetTypeInfo, GetTypeInfoCount, Invoke
STDMETHOD(GetIDsOfNames)( REFIID /*riid*/,
OLECHAR FAR *FAR *rgszNames,
unsigned int cNames,
LCID lcid,
DISPID FAR* /*rgDispId*/ )
{
UNREFERENCED_PARAMETER(rgszNames);
UNREFERENCED_PARAMETER(cNames);
UNREFERENCED_PARAMETER(lcid);
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfo)( unsigned int iTInfo,
LCID lcid,
ITypeInfo FAR *FAR *ppTInfo )
{
UNREFERENCED_PARAMETER(iTInfo);
UNREFERENCED_PARAMETER(lcid);
UNREFERENCED_PARAMETER(ppTInfo);
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfoCount)( unsigned int FAR *pctinfo )
{
UNREFERENCED_PARAMETER(pctinfo);
return E_NOTIMPL;
}
STDMETHOD(Invoke)( DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr );
// added by Mark manually -- End
};
#endif // !defined(AFX_SINK_H__F90A535B_4A71_433A_9A96_DE06BBEAB53C__INCLUDED_)
(7) Sink.cpp sample code
// Sink.cpp: implementation of the CSink class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Sink.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSink::CSink()
{
// added by Mark
m_dwRefCount =0;
}
CSink::~CSink()
{
}
// added by Mark for Invoke member -- Start
HRESULT CSink::Invoke( DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr )
{
if (!pDispParams)
return E_POINTER;
if (!pVarResult)
return E_POINTER;
if (pDispParams->cNamedArgs != 0)
return DISP_E_NONAMEDARGS;
switch (dispIdMember)
{
case 0x01: // 0x01 from COM server's Invoke
printf("0x01 is invoked from COM server\n");
break;
// case DISPID_CAPEVENT_ONPRECHANNELCHANGE:
// pVarResult->scode = m_pSinkCallback->OnPreChannelChanged(pDispParams->rgvarg[3].lVal, pDispParams->rgvarg[2].lVal, pDispParams->rgvarg[1].bstrVal, pDispParams->rgvarg[0].lVal);
// break;
// case DISPID_CAPEVENT_ONCHANNELCHANGE:
// pVarResult->scode = m_pSinkCallback->OnChannelChanged(pDispParams->rgvarg[3].lVal, pDispParams->rgvarg[2].lVal, pDispParams->rgvarg[1].bstrVal, pDispParams->rgvarg[0].lVal);
break;
default:
break;
}
return S_OK;
}
// added by Mark for Invoke member -- End
(8) main(..) function
#include "stdafx.h"
// -- Mark:: header files -- Start
#include "Sink.h"
#include <stdio.h>
#include <atlbase.h>
// -- Mark:: header files -- End
HRESULT test_COM_ConnectionPoint();
int main(int argc, char* argv[])
{
test_COM_ConnectionPoint();
return 0;
}
HRESULT test_COM_ConnectionPoint() {
HRESULT hr;
//call CoInitialize for COM initialisation
hr =CoInitialize(NULL);
if(hr != S_OK)
return -1;
// create an instance of the COM object
CComPtr<IAdd> pAdd;
hr =pAdd.CoCreateInstance(CLSID_Add);
if(hr != S_OK)
return -1;
IConnectionPointContainer * pCPC;
IConnectionPoint * pCP;
DWORD dwAdvise;
hr = pAdd->QueryInterface(IID_IConnectionPointContainer,
(void **)&pCPC);
if ( !SUCCEEDED(hr) )
{
return hr;
}
//
//OK, it does; now get the correct connection point interface
//in our case IID_IAddEvents
hr = pCPC->FindConnectionPoint(DIID__IAddEvents,&pCP);
if ( !SUCCEEDED(hr) )
{
return hr;
}
//we are done with the connection point container interface
pCPC->Release();
IUnknown *pSinkUnk;
// create a notification object from our CSink class
//
CSink *pSink = new CSink;
if ( NULL == pSink )
{
return E_FAIL;
}
//Get the pointer to CSink's IUnknown pointer (note we have
//implemented all this QueryInterface stuff earlier in our
//CSinkclass
hr = pSink->QueryInterface (IID_IUnknown,(void **)&pSinkUnk);
//Pass it to the COM through the COM's _IAddEvents
//interface (pCP) Advise method; Note that (pCP) was retrieved
//through the earlier FindConnectoinPoint call
//This is how the com gets our interface, so that it just needs
//to call the interface method when it has to notify us
_IAddEvents *pSinkAddEvents;
hr = pSink->QueryInterface (DIID__IAddEvents,(void **)&pSinkAddEvents);
if ( !SUCCEEDED(hr) )
{
return hr;
}
hr = pCP->Advise(pSinkAddEvents,&dwAdvise);
//now call the COM's add method, passing in 2 numbers
hr = pAdd->Add(2 ,4);
//do whatever u want here; once addition is here a message box
//will pop up showing the result
pCP->Unadvise(dwAdvise); // call this when you need to disconnect from server
printf("press any key to continue...");
getchar();
pCP->Release();
// Uninitialize COM
//CoUninitialize();
return hr;
}
(9) Results: