C++
  Home arrow C++ arrow Page 6 - Building An Outlook COM Add-In With VC /A...
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C++

Building An Outlook COM Add-In With VC /ATL
By: Amit Dey
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 57
    2002-02-17

    Table of Contents:
  • Building An Outlook COM Add-In With VC /ATL
  • Getting started
  • Building a minimal COM add-in
  • Command and conquer
  • Command and conquer (contd.)
  • Lord of the (disp) sinks
  • Conclusion

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    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.

    More C++ Articles
    More By Amit Dey


     

    C++ ARTICLES

    - 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++
    - Advanced File Handling with Streams in C++
    - File Handling and Streams in C++
    - The STL String Class







    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 2 Hosted by Hostway
    For more Enterprise Application Development news, visit eWeek