Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A Beginner's Tutorial for Connection Points Using VC++ and ATL

0.00/5 (No votes)
10 Apr 2002 4  
A tutorial on how to create connection points using VC++ and ATL

Introduction

The purpose of this article is to provide an introductory tutorial to implement connection points in VC++ using ATL. From a simplistic point of view I tend to treat Connection Points as an event handling mechanism for COM. So if you created an ActiveX control, a button for example and you wanted the click event to be handled by the container of the control and not the control itself you would use connection points. You may, however, go beyond just handling windows event and create those of your own. I have found that creating connection points in VC++ 6.0 to be a little confusing and not very obvious. I did these a couple of years ago while creating some controls and then recently had to use connection points again and just could not remember how I implemented them the first time. This tutorial is designed to help figure out how to create connection points using VC++.

The Project

Some of what is here will be a repeat of what you have seen in other articles. I will be as brief as possible and will assume that you know how to create an ATL DLL and a control within it. Lets start with creating an ATL COM DLL using the VC++ wizards calling the project Connection. Then lets create a composite control. You can create any control or object. A composite control simply allows me to provide for a good example. I am not showing how to create these as I am assuming that you know. If you do not know how to do so you should read some of the other articles posted here. Name this control ConnCtl. While creating the control select the attribute tab and then select the Support Connection Points check box. Then click OK.

Screenshot - Pic_1.jpg

VC++ This will automatically take you to the resource editor to place controls and build your composite control. For starters lets place a button on this control. You can either double click on the button or right click on CConCtl in the ClassView and then select to Add a Windows Message Handler. We add a handler to handle the clicking of a the button. This is done no differently from how we would add a windows message handler in a regular windows application using VC++. In the message handling function lets add a message box to show that we handled the click.

LRESULT CConnCtl::OnClickedButton(WORD wNotifyCode, WORD wID, 
    HWND hWndCtl, BOOL& bHandled) 
{
    ::MessageBox( hWndCtl, "Button was clicked"", 
        "Handled in Control", MB_OK" );
    return 0;
}

Build the project and test the control. When you click on the button you will see the message box we added. So now we have an ActiveX control that has a button and when you click the button you get our message box. Fantastic! You can use this control in any COM container. So where do the connection points come in?

Now suppose you wanted to trap the button click event in the container. Or to be more precise if you wanted the control to inform the container that the button has been clicked. This is when you need to implement connection points.

To do so first go to class view and right click on _IconnCtlEvents and add a method that will represent the interface that your control will provide its container with the information that the button has been clicked. Lets call it OnControlButtonClicked. And let's pass a BSTR. You could pass anything. I guess you should have arguments that are pertinent to button clicks. Well figure it out.

Screenshot - Pic_2.jpg

Now here comes the tricky part. I always goof up here and tend o forget what needs to be done to create a connection point. You need to compile the project. I always forget to do this and then wonder why the following steps do not work. Now in class view right click on CConCtl and then select "Implement Connection Point."You will be shown a dialog box.

Screenshot - Pic_3.jpg

Check IConnCtlEvents and click OK. Now VC++ implements connection points for you. In class view you will see that CProxy_IConnCtlEvents< class T> is created and it provides Fire_OnControlButtonClicked(BSTR someStr). Next, to make connection points work, that is for your code to let its container know that the button has been clicked we add Fire_OnControlButtonClicked(BSTR someStr) to the Windows message handling function created earlier.

LRESULT CConnCtl::OnClickedButton(WORD wNotifyCode, 
    WORD wID, HWND hWndCtl, BOOL& bHandled) 
{
    ::MessageBox( hWndCtl, "Button was clicked", 
        "Handled in Control", MB_OK );

    Fire_OnControlButtonClicked( CComBSTR( 
        "This message has been fired to the container" ) );

    return 0;
}

Now compile the project and if everything goes as designed you should get a few compile errors saying something along the lines that IID__IConnCtlEvents could not be found. If that is the case make IID__IconnCtlEvents in ConnCTL.h as shown below. I have always wondered if this is a problem on my installation of VC++ or a VC++ bug.

BEGIN_CONNECTION_POINT_MAP(CConnCtl)
    CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
    CONNECTION_POINT_ENTRY(DIID__IConnCtlEvents)
END_CONNECTION_POINT_MAP()

You now have a control that handles the windows click button event and passes that event on as defined by you (This is very cool. You the developer get to decide how this event is fired and what information is sent to the container). If you place this control in a VB form you will be able to catch the button click event fired by ConnCtl as follows:

Private Sub ConnCtl1_OnControlButtonClicked( ByVal someStr As String )
    'Now the container can do further processing once the button is clicked.

End Sub

Only Windows Messages?

Are connection points used just to pass on Windows Messages? No. Connection Points are a way for a COM object, server or control to provide an interface via which other objects, applications etc can receive notifications of events. You can read ATL Internals by Brent Rector and Chris Sells.

So lets suppose that not only did we want to let the control container know when we click the button but also when we clicked it for the 10th time. The process to set this up is very simple. Once again in class view right click on _IconnCtlEvents and select the option to add a method. Let's call this one OnTenthClick. Once again compile the project. Then right-click on CConCtl and then select "Implement Connection Point". Follow the steps mentioned above. Now you have the ability to provide the container with an interface that will notify the container when the user has clicked 10 times. Well not really. All you have done is create an interface that has that name. Now you must count the clicks and when you reach ten you must call Fire_OnTenthClick().

LRESULT CConnCtl::OnClickedButton(WORD wNotifyCode, 
     WORD wID, HWND hWndCtl, BOOL& bHandled) 
{
    ::MessageBox( hWndCtl, "Button was clicked", 
        "Handled in Control", MB_OK );

    Fire_OnControlButtonClicked( CComBSTR( 
        "This message has been fired to the container" ) );

    ClickCounter();  //Do stuff with how many times 

                     //the button has been clicked


    return 0;
}
void CConnCtl::ClickCounter() 
{
    _clickCount++;

    if( 10 == _clickCount ) 
    {
        Fire_OnTenthClick( CComBSTR( "Button has been clicked 10 times" ) );
    }
}

Conclusion

Connection Points are a great mechanism to handle events and are very easy to implement in VC++ using ATL (except for some non-intuitive steps). Please note that connection points can be created for any COM object and not just controls.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here