|
|
Can someone please point me to an example pof using C++ and catching Explorer events in a Com addin.
|
|
There are links to a couple of Outlook C++ addins at http://www.outlookcode.com/article.aspx?ID=36. I haven't looked at them so I don't know if they handle Explorer events but take a look at them and see.
-- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm
"Michael Tissington" <michael[ at ]nospam.newsgroups.com> wrote in message news:OQ$R5dwNJHA.4928[ at ]TK2MSFTNGP05.phx.gbl...
[Quoted Text] > Can someone please point me to an example pof using C++ and catching > Explorer events in a Com addin. > >
|
|
|
|
Here's one of my add-ins. It uses ATL, but I highly recommend doing so.
Here's the OnConnection handler that adds event sinks for all the explorers that are extant when the add-in is loaded and adds an event sink to watch for new explorers.
STDMETHODIMP CBmaOutlookAddIn::OnConnection(IDispatch *pApplication, AddInDesignerObjects::ext_ConnectMode /*ConnectMode*/, IDispatch * / *pAddInInst*/, SAFEARRAY ** /*custom*/ ) { DebugLog( _T( "Entering CBmaOutlookAddIn::OnConnection")); mOutlookApplication = pApplication; try { mExplorers = mOutlookApplication->GetExplorers(); if( mExplorers) { for( int i = 1; i <= mExplorers->GetCount(); i++) { Outlook::_ExplorerPtr explorer = mExplorers->Item( i); CExplorerEventSink *sink = new CExplorerEventSink( this); if( SUCCEEDED( sink->Initialize( explorer))) mExplorerEventSinks.Add( sink); else sink->Release(); } ExplorersEvents::DispEventAdvise( mExplorers); } ....
Here's the header file for my explorer event sink. It inherits from my general toolbar event sink since I use similar toolbars on inspector windows and the explorer context menu.
class CExplorerEventSink : public CToolbarEventSink, public IDispEventSimpleImpl< 1, CExplorerEventSink, &__uuidof(Outlook::ExplorerEvents_10)>, public IDispEventSimpleImpl< 2, CExplorerEventSink, &__uuidof(Outlook::ExplorerEvents_10)>, public IDispEventSimpleImpl< 3, CExplorerEventSink, &__uuidof(Outlook::ExplorerEvents_10)>, public IDispEventSimpleImpl< 4, CExplorerEventSink, &__uuidof(Office::_CommandBarsEvents)> { public: CExplorerEventSink( CBmaOutlookAddIn *addIn); virtual ~CExplorerEventSink();
virtual ULONG STDMETHODCALLTYPE AddRef(); virtual ULONG STDMETHODCALLTYPE Release();
HRESULT Initialize( Outlook::_ExplorerPtr explorer); virtual void Uninitialize(); Outlook::_ExplorerPtr GetExplorer() const{ return mExplorer;} virtual void OnButtonClicked( CButtonEventSink::Id id);
void __stdcall OnExplorerActivate(); void __stdcall OnExplorerFolderSwitched(); void __stdcall OnExplorerClose(); void __stdcall OnCommandBarsUpdated();
BEGIN_SINK_MAP(CExplorerEventSink) SINK_ENTRY_INFO( 1, __uuidof(Outlook::ExplorerEvents_10), 0x0000f001, OnExplorerActivate, &NoParamsInfo) SINK_ENTRY_INFO( 2, __uuidof(Outlook::ExplorerEvents_10), 0x0000f002, OnExplorerFolderSwitched, &NoParamsInfo) SINK_ENTRY_INFO( 3, __uuidof(Outlook::ExplorerEvents_10), 0x0000f008, OnExplorerClose, &NoParamsInfo) SINK_ENTRY_INFO( 4, __uuidof(Office::_CommandBarsEvents), 0x00000001, OnCommandBarsUpdated, &NoParamsInfo) END_SINK_MAP()
protected: virtual Office::_CommandBarsPtr GetToolbars(){ return mCommandBars;} void RemoveContextMenuButtons();
protected: long mRefCount; Outlook::_ExplorerPtr mExplorer; Office::_CommandBarsPtr mCommandBars; CContextMenuEventSink *mContextMenuEventSink; CHiddenWindow *mHiddenWindow; };
Here's the relevant pieces of my .cpp file. I haven't included the toolbar event sink's source, but it's not the interesting bit.
#include "stdafx.h" #include "ExplorerEventSink.h" #include "HiddenWindow.h"
typedef IDispEventSimpleImpl< 1, CExplorerEventSink, &__uuidof(Outlook::ExplorerEvents_10)> ExplorerEvent1; typedef IDispEventSimpleImpl< 2, CExplorerEventSink, &__uuidof(Outlook::ExplorerEvents_10)> ExplorerEvent2; typedef IDispEventSimpleImpl< 3, CExplorerEventSink, &__uuidof(Outlook::ExplorerEvents_10)> ExplorerEvent3; typedef IDispEventSimpleImpl< 4, CExplorerEventSink, &__uuidof(Office::_CommandBarsEvents)> CommandBarsEvent;
CExplorerEventSink::CExplorerEventSink( CBmaOutlookAddIn *addIn) : CToolbarEventSink( addIn) { mRefCount = 1; mContextMenuEventSink = NULL; mHiddenWindow = NULL; }
CExplorerEventSink::~CExplorerEventSink() { Uninitialize(); if( mHiddenWindow) { mHiddenWindow->DestroyWindow(); delete mHiddenWindow; } }
HRESULT CExplorerEventSink::Initialize( Outlook::_ExplorerPtr explorer) { HRESULT hResult = S_OK; if( FAILED( hResult = ExplorerEvent1::DispEventAdvise( explorer))) return hResult; if( FAILED( hResult = ExplorerEvent2::DispEventAdvise( explorer))) return hResult; if( FAILED( hResult = ExplorerEvent3::DispEventAdvise( explorer))) return hResult;
mExplorer = explorer; OnExplorerActivate(); return S_OK; }
void CExplorerEventSink::Uninitialize() { CToolbarEventSink::Unitialize();
if( mExplorer) { RemoveContextMenuButtons();
if( mCommandBars) { CommandBarsEvent::DispEventUnadvise( mCommandBars); mCommandBars = NULL; }
ExplorerEvent3::DispEventUnadvise( mExplorer); ExplorerEvent2::DispEventUnadvise( mExplorer); ExplorerEvent1::DispEventUnadvise( mExplorer); mExplorer = NULL; } }
void __stdcall CExplorerEventSink::OnExplorerActivate() { DebugLog( _T( "Entering CExplorerEventSink::OnExplorerActivate")); try { if( !mCommandBars && mExplorer->GetCommandBars()) { mCommandBars = mExplorer->GetCommandBars(); CommandBarsEvent::DispEventAdvise( mCommandBars); AddButtons(); } } IGNORE_COM_EXCEPTION DebugLog( _T( "Leaving CExplorerEventSink::OnExplorerActivate")); }
void __stdcall CExplorerEventSink::OnExplorerFolderSwitched() { DebugLog( _T( "Entering CExplorerEventSink::OnExplorerFolderSwitched")); try { Outlook::MAPIFolderPtr currentFolder = mExplorer-
[Quoted Text] >GetCurrentFolder();
if( currentFolder && currentFolder->GetDefaultItemType() == Outlook::olMailItem) { if( !HasButton()) AddButtons(); } else RemoveButtons(); } IGNORE_COM_EXCEPTION DebugLog( _T( "Leaving CExplorerEventSink::OnExplorerFolderSwitched")); }
void __stdcall CExplorerEventSink::OnCommandBarsUpdated() { DebugLog( _T( "Entering CExplorerEventSink::OnCommandBarsUpdated")); try { if( mCommandBars) { if( HasButton()) { RemoveContextMenuButtons(); Office::CommandBarPtr menu = mCommandBars->GetItem( _T( "Context Menu")); if( menu) { CContextMenuEventSink *sink = new CContextMenuEventSink( this, mAddIn); if( SUCCEEDED( sink->Initialize( menu))) mContextMenuEventSink = sink; else sink->Release(); } } else RemoveContextMenuButtons(); } } IGNORE_COM_EXCEPTION DebugLog( _T( "Leaving CExplorerEventSink::OnCommandBarsUpdated")); }
void __stdcall CExplorerEventSink::OnExplorerClose() { Uninitialize(); mAddIn->RemoveExplorerEventSink( this); }
void CExplorerEventSink::RemoveContextMenuButtons() { if( mContextMenuEventSink) { mContextMenuEventSink->Uninitialize(); mContextMenuEventSink->Release(); mContextMenuEventSink = NULL; } }
STDMETHODIMP_(ULONG) CExplorerEventSink::AddRef() { InterlockedIncrement( &mRefCount); return mRefCount; }
STDMETHODIMP_(ULONG) CExplorerEventSink::Release() { ULONG refCount = InterlockedDecrement( &mRefCount); if( !refCount) delete this; return refCount; }
Maybe creating add-ins is easier in VB, but I've run across several gotcha's in C++/ATL. I'm doing some odd stuff (including mixing OOM and MAPI), which is part of the problem. For example, though, all the example code I've seen (including that linked by Dmitry above) shows how to inherit from IDispEventSimpleImpl to sink events from Outlook, but none of them mention that you may want to override AddRef and Release. They're virtuals on IDispEventSimpleImpl and its default implementation just returns 1 in both cases. If you leave it at that, it works most of the time, but there are cases where Outlook will (wisely) addref an event sink, call it, then release it, and if you've disappeared in the meantime, it'll crash Outlook.
|
|
On Oct 27, 1:40 pm, "Michael Tissington" <mich...[ at ]nospam.newsgroups.com> wrote:
[Quoted Text] > Thanks
Oops... I meant "the links that _Ken_ posted above." :)
|
|
On Oct 27, 1:40 pm, "Michael Tissington" <mich...[ at ]nospam.newsgroups.com> wrote:
[Quoted Text] > Thanks
Google keeps losing my posts... going to see if this makes it before I repost all my source.
|
|
|