The only callback signature I'm familiar with for onAction is something
like this C# signature:
public void Ribbon_onAction(Ribbon.IRibbonControl control)
{
}
For getPressed it looks like this:
public bool Ribbon_getPressed(IRibbonControl control)
{
}
To me that implies that for C++ it could be something like this:
CheckboxClicked([in]IDispatch* ribboncontrol, [out]VARIANT_BOOL state);
Are you sure about that [in] attribute on the state variable?
You can take a look at
www.outlookcode.com, there are some C++ COM addin
samples for Outlook there, if you haven't seen them already.
For my own coding I restrict managed code addins to those that only need
to support Outlook 2003 or later. I could do 2000 or later but there are
some problems with the PIA's for 2002 and the 2002-modified one for 2000
that I prefer to avoid. For addins that must support Outlook 2000 and
later I use VB6, I don't really do any C++ programming, just some hacking
from time to time.
When I need to do one of those addins I reference the Outlook and Office
2000 tlb's and add ribbon support by using a special
XLIRibbonExtensibility tlb that has the ribbon interfaces. That way I fork
my code based on Outlook version and use the CommandBars interface for
versions before 2007 and the ribbon for 2007 and 2010 for Inspectors (and
Explorers for 2010).
When I do a C# addin that has to support Outlook 2003 and later I use
ribbon interface definitions based on a blog article by Andrew Whitechapel
of the VSTO team in a RibbonInterop class and handle the callbacks in a
RibbonX class. The RibbonInterop class has definitions like this (it's
been modified to also support the new interfaces in IRibbonUI for Office
2010):
//internal namespace to facilitate "Office" alias
namespace RibbonInterop
{
namespace Office
{
#region Ribbon
[ComImport(), Guid("000C0395-0000-0000-C000-000000000046"),
TypeLibType((short)0X1040)]
public interface IRibbonControl
{
[DispId(1)]
string Id { [return: MarshalAs(UnmanagedType.BStr)]
[MethodImpl(MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime), DispId(1)] get; }
[DispId(2)]
object Context { [return: MarshalAs(UnmanagedType.IDispatch)]
[MethodImpl(MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime), DispId(2)] get; }
[DispId(3)]
string Tag { [return: MarshalAs(UnmanagedType.BStr)]
[MethodImpl(MethodImplOptions.InternalCall,
MethodCodeType = MethodCodeType.Runtime), DispId(3)] get; }
}
[ComImport(), Guid("000C0396-0000-0000-C000-000000000046"),
TypeLibType((short)0X1040)]
public interface IRibbonExtensibility
{
[return: MarshalAs(UnmanagedType.BStr)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime), DispId(1)]
string GetCustomUI([In(), MarshalAs(UnmanagedType.BStr)] string RibbonID);
}
[ComImport(), Guid("000C03A7-0000-0000-C000-000000000046"),
TypeLibType((short)0X1040)]
public interface IRibbonUI
{
// for both Office 2007 and 2010
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime), DispId(1)]
void Invalidate();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime), DispId(2)]
void InvalidateControl([In(), MarshalAs(UnmanagedType.BStr)] string
ControlID);
// for Office 2010
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime), DispId(3)]
void InvalidateControlMso([In(), MarshalAs(UnmanagedType.BStr)] string
ControlID);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime), DispId(4)]
void ActivateTab([In(), MarshalAs(UnmanagedType.BStr)] string ControlID);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime), DispId(5)]
void ActivateTabMso([In(), MarshalAs(UnmanagedType.BStr)] string
ControlID);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime), DispId(6)]
void ActivateTabQ([In(), MarshalAs(UnmanagedType.BStr)] string ControlID,
[In(), MarshalAs(UnmanagedType.BStr)] string Namespace);
}
#endregion
}
}
Tom said:
Hi Ken,
Yes I can successfully call get_id and it returns the correct ID of the
check box and yes when I call get _context it does return the correct
dispatch. But when I call get_tag it throws an exception. In addition
when I look at the number of arguments passed to the invoke procedure
their is only one argument when there should be two.
I also modified the VS2005 C++/ATL example to be a check box and I get
the same result.
Yesterday after I sent this post, I started mucking around with this and
forgot to mention one thing that was puzzling to me. My interface and the
OnAction method (CheckboxClicked())could only be defined as:
HRESULT CheckboxClicked([in]IDispatch* ribboncontrol);
But the actual event is returning two parameters.
HRESULT CheckboxClicked([in]IDispatch* ribboncontrol, [in]VARIANT_BOOL
state);
So I believe by including the callback interface we are circumventing the
default events for the checkbox. Something just is not adding up.
Is there an event interface that we can setup an advise on?
BTW - I have tried several ideas on the web. There is not any unmanaged
solutions/examples that I have seen that appear to work one hundred
percent. Most of our outlook add-ins have to support all versions of
Outlook from 2000 (and windows 2000 and above) and above and a managed
solution is not an option.
BTW2 - we were trying to use the ribbon as an experiment for one of our
own products that we are releasing in a couple months. So far I think we
are going to have to use the same add-in toolbar that we have for 2002
and 2003.
Thanks,
Tom