Introduction
I have tried to make this tutorial very much practical oriented, and it shows how to implement connection points practically, rather than concentrating on the theory. And before starting anything, I want to give a sincere thanks from the depth of my soul to Mr. Alex C. Punnen for his article published in The Code Project: COM Connection Points.
As this is my first article, I am sincerely thankful for all your suggestions and comments.
Let’s Start
Create a console based application with MFC support. Let’s name it ConClient.
![Image 1](/KB/atl/ConnectionPoint/1.jpg)
Add another ATL project as the dependency of the current project. Name the ATL project as ConServer.
![Image 2](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Create an interface named XMath
in to our new ConServer.
![Image 3](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
But this time, please check the ConnectionPoint check box.
![Image 4](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Then, build our ConServer.
![Image 5](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
You will see a new interface _IXMathEvents
in your class view.
![Image 6](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Add a new method to our Interface, XMath
(please note here that there is no return type or [out, retval]
specified).
![Image 7](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Add a new method to our event interface (_IXMathEvents
in our case).
![Image 8](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
The method should be like this:
![Image 9](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
After adding the method to the event interface, please right click on the CoClass of our project, as shown in the picture below:
![Image 10](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Then as it is highlighted, in the Implement Connection Point dialog, select it. You are going to see the following screen:
![Image 11](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
As in the picture, please check the box that says _IXMathEvents. After that, you will see some class generated for us by the wizard named CProxy_IXMathEvents<class T>
.
![Image 12](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Again, if you implement the connection point, then you will see some methods, like Fire_ExecutionOver
inside the CProxy_IXMathEvents
class, if you are not seeing the Fire_ExecutionOver
method in the CProxy…
class.
![Image 13](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Double click on the Add(int n1, int n2)
function of the CXMath->IXMath->Add
function. And write the following line of code:
Fire_ExecutionOver(n1 + n2);
![Image 14](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Build the server DLL, in the File view, by right clicking on it.
If you are getting some errors like in the picture below:
![Image 15](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Please change the CONNECTION_POINT_ENTRY(IID__IXMathEvents)
line to CONNECTION_POINT_ENTRY(DIID__IXMathEvents)
.
Make the ConClient as the active project now. And add a new class CSink
derived from CCmdTarget
, and please select the Automation radio button from the Automation panel.
![Image 16](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Enter the following line to the StdAfx.h of the client:
#import "ConServer\Debug\ConServer.DLL" named_guids
using namespace CONSERVERLib;
Add a member function to the CSink
class, as HRESULT Add(int nResult)
.
Open the Sink.CPP file and modify the following lines. Comment the INTERFACE_PART(CSink, IID_ISink, Dispatch)
line and add INTERFACE_PART(CSink, DIID__IXMathEvents, Dispatch)
.
BEGIN_INTERFACE_MAP(CSink, CCmdTarget)
INTERFACE_PART(CSink, DIID__IXMathEvents, Dispatch)
END_INTERFACE_MAP()
In the DISPATCH MAP, add the following line:
DISP_FUNCTION(CSink, "Add", Add, VT_I4, VTS_I4)
The changes have been marked with the red lines in Sink.CPP.
![Image 17](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
Add #include “Sink.h”
to your main function’s file. And write the following lines of code to your main function:
IXMathPtr ptrMath;
CoInitialize(NULL);
ptrMath.CreateInstance(__uuidof(XMath));
if(ptrMath)
{
IConnectionPointContainerPtr ptrConPntCnt = (IDispatch*)ptrMath;
IConnectionPointPtr ptrCon;
IUnknown* pHandler = NULL;
DWORD dwCookie;
if(ptrConPntCnt != NULL)
{
ptrConPntCnt->FindConnectionPoint(DIID__IXMathEvents,&ptrCon);
CSink *pSink = new CSink;
pHandler = pSink->GetInterface(&IID_IUnknown);
ptrCon->Advise(pHandler,&dwCookie);
ptrMath->Add(10, 20);
ptrCon->Unadvise(dwCookie);
ptrCon.Release();
ptrConPntCnt.Release();
delete pSink;
}
ptrMath.Release();
}
CoUninitialize();
After successfully running this program, you will see a message box showing you the value as 30 as in the figure down below:
![Image 18](data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)
In my second version of the article, I am intending to implement connection points using eVC++ 4.0 and VS 7.0.