Group:  Microsoft Outlook » microsoft.public.outlook.program_addins
Thread: C++ and Explorers

Geek News

C++ and Explorers
"Michael Tissington" <michael[ at ]nospam.newsgroups.com> 10/26/2008 1:09:16 AM
Can someone please point me to an example pof using C++ and catching
Explorer events in a Com addin.


Re: C++ and Explorers
"Ken Slovak - [MVP - Outlook]" <kenslovak[ at ]mvps.org> 10/27/2008 1:01:06 PM
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.
>
>

Re: C++ and Explorers
"Michael Tissington" <michael[ at ]nospam.newsgroups.com> 10/27/2008 5:40:16 PM
Thanks
Re: C++ and Explorers
cainrandom[ at ]gmail.com 10/28/2008 12:06:04 PM
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.
Re: C++ and Explorers
cainrandom[ at ]gmail.com 10/28/2008 12:08:48 PM
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." :)
Re: C++ and Explorers
cainrandom[ at ]gmail.com 10/28/2008 2:08:55 PM
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.

Home | Search | Terms | Imprint Contact
Newsgroups Reader - provided by WiredBox.Net