Home arrow C++ arrow Page 6 - Building An Outlook COM Add-In With VC /ATL
C++

Building An Outlook COM Add-In With VC /ATL


One of the great things about Windows is the ability that we have to create COM-based add-in's for the entire suit of Office 2000 applications. In this article, Amit shows us how to create an Outlook 2000 COM add-in using a pure Visual C ATL COM object. He starts by writing a basic functional COM add-in, and then adds standard user interface elements such as toolbars and menu items to Outlook. He finishes up by showing us how to respond to their events.

Author Info:
By: Amit Dey
Rating: 5 stars5 stars5 stars5 stars5 stars / 65
February 17, 2002
TABLE OF CONTENTS:
  1. · Building An Outlook COM Add-In With VC /ATL
  2. · Getting started
  3. · Building a minimal COM add-in
  4. · Command and conquer
  5. · Command and conquer (contd.)
  6. · Lord of the (disp) sinks
  7. · Conclusion

print this article
SEARCH DEVARTICLES

Building An Outlook COM Add-In With VC /ATL - Lord of the (disp) sinks
(Page 6 of 7 )

Putting together a couple of toolbars and menu items by themselves is not a very useful exercise, unless we can write command handlers that respond to their events (such as when they are clicked). Let's do that now.

We're going to create some simple code to popup a message box whenever our items are clicked on. In a real-life application (such as a customer relationship management tool), COM add-ins can be used to perform an endless variety of important tasks, such as filtering and forwarding mail automatically, etc.

The CommandBarButton control exposes a click event that is triggered when a user clicks a command bar button. We are going to use this event to run code when the user clicks the toolbar buttons or the menu item. For this, our COM object has to implement an event sink interface. For CommandBarButton control, the events dispinterface is _CommandBarButtonEvents. The click method is declared as

//...

//....Office objects typelibrary

//....

[id(0x00000001), helpcontext(0x00038271)]

void Click( [in] CommandBarButton* Ctrl, [in, out] VARIANT_BOOL* CancelDefault);

//....

//...


All we have to do is implement sink interfaces that will be called by the event source through regular connection point protocol whenever a menu or a toolbar button is clicked. Our callback method returns a pointer to the source CommandBarButton object, as well as a boolean value that can be used to accept or negate the default action. As for implementing a dispatch sink interface, that's nothing new, and as an ATL programmer you have probably done this a lot of times.

For the uninitiated, ATL provides two template classes, IDispEventImpl<> and IDispEventSimpleImpl<> for ATL COM objects. They provide an implementation of IDispatch. I prefer the lightweight IDispEventSimpleImpl interface, because it doesn't need the extra type library information.

We need to derive our class from IDispEventSimpleImpl<>, set up our sink map, rig up our callback parameters through the _ATL_SINK_INFO structure, and finally call DispEventAdvise and DispEventUnadvise to connect and disconnect from the source interface.

For our toolbar buttons and menu items, if we were to write a single callback method for all events, then once we have a pointer to the CommandBarButton that triggered the event, we can use it's GetCaption method to get the button text, based on which we can perform some selective action. For this sample however, we'll have just one callback per event.

Here's the steps and details to create our code:

1. Derive your class from IdispSimpleEventImpl. The first parameter is typically the child windows ID in the case of ActiveX controls. For us however, this can be any predefined integer that uniquely identifies the event source (in our case the first toolbar button):

class ATL_NO_VTABLE CAddin :

public CComObjectRootEx < CComSingleThreadModel>,

.....

.....

public IDispEventSimpleImpl<1,CAddin,&__uuidof(Office::_CommandBarButtonEvents>


2. Setup the callback. Firstly, we must define a callback as follows:

void __stdcall OnClickButton(IDispatch * /*Office::_CommandBarButton**/ Ctrl,VARIANT_BOOL * CancelDefault);

Then we use the _ATL_SINK_INFO structure to describe the callback parameters. Open the addin.h file and add the following declaration right near the top of the file:

extern _ATL_FUNC_INFO OnClickButtonInfo;

Open the addin.cpp file and add the following definition:

_ATL_FUNC_INFO OnClickButtonInfo ={CC_STDCALL,VT_EMPTY,2,{VT_DISPATCH,VT_BYREF | VT_BOOL}};

OnClickButton is very elementary. Its code looks like this:

void __stdcall CAddin::OnClickButton(IDispatch* /*Office::_CommandBarButton* */ Ctrl,VARIANT_BOOL * CancelDefault)

{

USES_CONVERSION;

CComQIPtr pCommandBarButton(Ctrl);

//the button that raised the event. Do something with this...

MessageBox(NULL, "Clicked Button1", "OnClickButton", MB_OK);

}


3. We will setup the sinkmap using the ATL macros BEGIN_SINK_MAP() and END_SINK_MAP(). The sink map needs to be populated by SINK_ENTRY_XXX. The sink map basically provides the mapping between a dispatch identifier that defines the event and the member function that handles it.

BEGIN_SINK_MAP(CAddin)

SINK_ENTRY_INFO(1, __uuidof(Office::_CommandBarButtonEvents),/*dispid*/ 0x01, OnClickButton, &OnClickButtonInfo)

END_SINK_MAP()


Now that everything is in place, we have to connect to and disconnect from the event source with DispEventAdvise() and DispEventUnadvise(). Our CAddin classes OnConnection() and OnDisconnection() methods are just the place to do this. The parameters to DispEventAdvise() and DispEventUnadvise() are the interface to the event source and the desired event source interface respectively.

//connect to event source in OnConnection

// m_spButton member variable is a smart pointer to _CommandBarButton

// that is used to cache the pointer to the first toolbar button.

DispEventAdvise((IDispatch*)m_spButton,&DIID__CommandBarButtonEvents);

//when I'm done disconnect from the event source

//some where in OnDisconnection()

DispEventUnadvise((IDispatch*)m_spButton);


Similarly, implement disp sinks for all of your command buttons and menu items. Write handlers to connect to and from them as described above. That's all there is to it.

If everything works without a hitch after you rebuild and run the add-in, then whenever the buttons or menu item is clicked, the respective callback method should be called, thus displaying a message box on the screen.
blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials