views:

294

answers:

1

Hi, I'm doing an add-in for Outlook 2007 in C++.

I need to capture the events like create, change or delete from the Outlook Items (Contact, Appointment, Tasks and Notes) but the only information/examples I've found are for Visual Basic so I don't know how to connect the event handler.

Here is some information related: http://msdn.microsoft.com/en-us/library/bb208390(v=office.12).aspx

Any help is welcome :) Thanks

Update

Sorry for taking this long to update, I've been out of town. I have some doubts/problems that you may know how to help.

In my case, I'm taking this project that was started so I'm a bit confused about all this. I have the class OutlookAddin that derives from IDTExtensibility2. I also have this other class, called AutoSync, were I'd like to do all the methods when the event fires and so. An object of this class is initialized in OutlookAddin.cpp OnStartupComplete.

According to your post MyClass should extends from IDispEventSimpleImpl<1 /*N*/, MyClass, &__uuidof(Outlook::ItemsEvents)> but which one of them? OutlookAddin or AutoSync ?

Where I should put this code also?

CComPtr<Outlook::MAPIFolder> folder;
// get the folder you're interested in
CComPtr<Outlook::_Items> items;
hr = folder->get_Items(&items);
hr = MyItemEvents::DispEventAdvise(items, &__uuidof(Outlook::ItemsEvents));

typedef IDispEventSimpleImpl<1 /*N*/, MyClass, 
          &__uuidof(Outlook::ItemsEvents)> MyItemEvents;

I've read the links you posted but still having these doubts...

Update 2

This is more complicated to understand than I though in a first instance.

So I have like this:

OutlookAddin.h

class OutlookAddin : 
public IDTExtensibility2,
public IDispEventSimpleImpl<1, OutlookAddin, &__uuidof(Outlook::ItemEvents)>
...
BEGIN_SINK_MAP(OutlookAddin)
SINK_ENTRY_INFO(1, __uuidof(Outlook::ItemEvents), 0xf002, OutlookAddin::OnItemChange, &OnSimpleEventInfo)
END_SINK_MAP()
...
void __stdcall OnItemChange();

'OnSimpleEventInfo' is defined like:

extern _ATL_FUNC_INFO OnSimpleEventInfo;
_ATL_FUNC_INFO OnSimpleEventInfo = {CC_STDCALL,VT_EMPTY,0};

then in OutlookAddin.cpp, OnConnection method:

    CComPtr<Outlook::MAPIFolder> folder;
CComPtr<Outlook::_Items> items;

OutlookWorker::GetInstance()->GetNameSpacePtr()->GetDefaultFolder(olFolderContacts, &folder);
folder->get_Items(&items);
DispEventAdvise(items, &__uuidof(Outlook::ItemsEvents));

being 'OutlookWorker::GetInstance()->GetNameSpacePtr()' the _NameSpacePtr where all the environment is kept.

The expected behaviour here is to fire the function 'OnItemChange' from OutlookAddin class when an ContactItem is created/edited/deleted but that's not happening... I changed a little bit the structure to everything is in the main class OutlookAddin. Then on the function 'OnItemChange' I'll start the object of 'AutoSync' that I told you before.

Anyway I'm following the articles you gave me, really useful, thank you. Do you still have any other suggestion for me?

Thanks your patience.

+1  A: 

Its been a while, but you should get these item events by advising for Folder.Items:

CComPtr<Outlook::MAPIFolder> folder;
// get the folder you're interested in
CComPtr<Outlook::_Items> items;
hr = folder->get_Items(&items);
hr = MyItemEvents::DispEventAdvise(items, &__uuidof(Outlook::ItemsEvents));

Where your class MyClass derives from:

IDispEventSimpleImpl<1 /*N*/, MyClass, &__uuidof(Outlook::ItemsEvents)>

And MyItemEvents is:

typedef IDispEventSimpleImpl<1 /*N*/, MyClass, 
          &__uuidof(Outlook::ItemsEvents)> MyItemEvents;

N identifies your sink here. Then there is the joy of the remaining macros to setup and the handler functions to implement - i refer you to this and this article for examples and to the dispinterface ItemsEvents that you can look up in oleview.exe.


Regarding update 1:
If you want to receive the events in AutoSync, implement the interface there - you are not required to sink the events to any specific instance. However, you know your design best :)
I'd just personally keep as much logic out of the central addin class as possible.

The registration code would go into some method of the class implementing the events then and called whenever it should start to receive events, while the typedef would be e.g. well placed in the class' declaration.


Regarding update 2:

From a quick glance it looks mostly right, but OnItemChange() takes one parameter - an IDispatch:

_ATL_FUNC_INFO AtlCallDispatch = {CC_STDCALL, VT_EMPTY, 1, {VT_DISPATCH}};
Georg Fritzsche
Thank you, I'm going to take a look to this ;)
framara
Question updated, if you could have a look. Thanks.
framara
@framara, updated.
Georg Fritzsche
Question updated again with more detail of the code. Hope you understand it better. Thanks
framara
@framara, updated.
Georg Fritzsche