Click here to Skip to main content
Licence 
First Posted 30 Nov 2001
Views 83,640
Downloads 837
Bookmarked 37 times

Handling COM Events in a Console Application, Part II

By | 27 Jan 2003 | Article
Simple code to deal with multiple event sinks/sources

The XYDispDriver class is a simple generic dispatch driver class that can be used to create almost any COM object and call its methods. In my previous article Handling COM Events in a Console Application, I talked about enhancements to this class that makes handling COM events easy. No need for messy template code, no event sink map, and no sink entry macro, etc. All we need to do is create a COM object implementing the event interface using our favourite tool and then call the Advise method of XYDispDriver.

The previous version of XYDispDriver does not deal with some complicated situations, such as multiple event sinks or multiple event sources. Some people may worry that this is not the right way to handle general COM events. After making some changes to the XYDispDriver class, I was able to write code that deals with these situations successfully. The resulting code, as you can see, is simpler than the code you would have written using ATL to accomplish the same thing.

The only significant change I made is adding an assignment operator to the XYDispDriver class. As described in my article Getting the most out of IDispatch, the CreateObject method of XYDispDriver will create a new instance of a COM object, query and store its type information for future use. Assigning one XYDispDriver object to another does not create a new instance of the corresponding COM object, instead it only copies the type information and the IDispatch pointer, and call the IDispatch::AddRef method to bump up the reference count. Therefore, the two XYDispDriver objects will be referring to the same COM object after the assignment.

Let's first see the code that deals with multiple event sinks. We will be using the same example as in the previous article: "TestCon" is an ActiveX control that fires the InvalidLoginData event when its Connect method fails and "TestHndlr" is another ActiveX control that implements the event interface of TestCon. What we need to do is "connect" two instances of TestHndlr to a single instance of TestCon so that when the InvalidLoginData event is fired, the event handling method will be invoked in both instances of TestHndlr. Here is the code of a console application that demonstrates the scenario of two event sinks.

#include <stdio.h>
#include "XYDispDriver.h"

void main()
{
    // declare XYDispDriver variables
    XYDispDriver dispCon1, dispCon2, dispEventA, dispEventB;
    // create the TestCon control
    if(dispCon1.CreateObject("TestCon.1"))
    {
        // make a copy (AddRef)
        dispCon2 = dispCon1;
        // create the first TestHndlr control
        if(dispEventA.CreateObject("TestHndlr.1"))
        {
           // the class id of the event interface in the TestCon control
           CLSID clsidEventA = {0xe77a1f7e,0xe3ff,0x11d5,{0x88,0x12,0x00,0xb0,0xd0,0x55,0xb5,0x23}};
           // call the Advice method to set up the first event handler
           dispCon1.Advise(dispEventA.GetDispatch(),clsidEventA);
        }
        else printf("Error: %x\n",dispEventA.GetLastError());
        // create the second TestHndlr control
        if(dispEventB.CreateObject("TestHndlr.1"))
        {
           // the class id of the event interface in the TestCon control
           CLSID clsidEventB = {0xe77a1f7e,0xe3ff,0x11d5,{0x88,0x12,0x00,0xb0,0xd0,0x55,0xb5,0x23}};
           // call the Advice method to set up the second event handler
           dispCon2.Advise(dispEventB.GetDispatch(),clsidEventB);
        }
        else printf("Error: %x\n",dispEventB.GetLastError());
        // call the Connect method, passing strUserName and strPassword parameters
        // it should generate an InvalidLoginData event in either one of the following cases:
        // 1. strUsername or strPassword is empty
        // 2. the length of strPassword < 6
        // 3. strPassword equals strUsername
        dispCon1.InvokeMethod("Connect","MyName","MyPwd");
        // you should see two event message boxes by now
    }
    else printf("Error: %x\n",dispCon1.GetLastError());
    ::MessageBox(NULL,_T("Done"),_T("Test"),MB_OK); 
} 

The code that deals with multiple event sources is similar. Suppose the COM object TestCon has two different event interfaces, we can create two different types of COM objects TestHndlrA and TestHndlrB to implement these two interfaces, respectively. In the above code, if we let dispidEventA and dispidEventB be the dispids of these two event interfaces, and use the two XYDispDriver objects dispEventA and dispEventB to create these two event handler objects, then the above code will demonstrate the scenario of two event sources.

The zip file included with this article only has source code for the two ActiveX controls and the console app. You can download the source code for XYDispDriver from my article Getting the most out of IDispatch. You can also find more articles and software from my home page.

Disclaimer: I am not trying to show that ATL or any other related technology is not as good as my method. All I am doing is demonstrate a pretty simple and flexible (maybe unconventional) way to use COM objects.

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

About the Author

Xiangyang Liu 刘向阳



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionHow can I Fire Message from COM Server to its its client ? Pinmemberjags_vc17:55 4 Feb '06  
GeneralUpdate 2002/01/28 PinmemberXiangYangLiu4:29 28 Jan '02  
GeneralRe: Update 2002/01/28 PinmemberChopper3:17 25 Mar '02  
GeneralRe: Update 2002/01/28 PinmemberMahesh N Deshpande23:25 26 Jun '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 28 Jan 2003
Article Copyright 2001 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid