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
}
}

Signature
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
> Hi Ken,
>
[quoted text clipped - 36 lines]
> Thanks,
> Tom
Tom - 30 Jul 2009 19:57 GMT
Hi Ken,
Thanks Ken.
I have snipped my invoke code below.
Actually your C# function for getpressed is equivalent to
CheckboxClicked([in]IDispatch* ribboncontrol, [out,retval]VARIANT_BOOL
state);
But I am not getting that event.
However the OnAction is infact sending me two parameters for the checkbox.
BTW - we have created our own ribbon tlb also using the MIDL compiler.
STDMETHODIMP CGSDExt::Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
WORD wFlags,
DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
if(dispidMember == 0xf001)
{
// Handle the NewInpector event
OnNewInspector(pdispparams->rgvarg[0].pdispVal);
}
else if(dispidMember == 1) // OnAction
{
// STDMETHOD(CheckboxClicked)( IDispatch * RibbonControl)
ATLTRACE(_T("state = %i\n"), pdispparams->rgvarg[0].boolVal);
DWORD dwDisable = 0;
if(pdispparams->rgvarg[0].boolVal)
{
dwDisable = 1;
GenericRegistry::WriteDwordValue(REGISTRY_CONFIG_ENTRY_OUTLOOK,
REGISTRY_DISABLE_BCC, dwDisable);
}
else
{
GenericRegistry::WriteDwordValue(REGISTRY_CONFIG_ENTRY_OUTLOOK,
REGISTRY_DISABLE_BCC, dwDisable);
}
CComPtr<IRibbonControl> spRibbon;
HRESULT hr =
pdispparams->rgvarg[1].pdispVal->QueryInterface(IID_IRibbonControl,
(LPVOID*)&spRibbon);
if(SUCCEEDED(hr) && spRibbon)
{
}
}
else if(dispidMember == 2) //getPressed
{
// STDMETHOD(GetCheckboxState)( IDispatch * RibbonControl, VARIANT_BOOL *
state)
BSTR b;
CComPtr<IRibbonControl> spRibbon;
BSTR bstr = NULL;
if(pdispparams->rgvarg[0].vt == VT_DISPATCH)
{
HRESULT hr =
pdispparams->rgvarg[0].pdispVal->QueryInterface(IID_IRibbonControl,
(LPVOID*)&spRibbon);
if(SUCCEEDED(hr) && spRibbon)
{
//hr = spRibbon->get_Tag(&b); <<<< This blows up
hr = spRibbon->get_Id(&bstr);
if(SUCCEEDED(hr) && bstr)
{
TString str = (const TCHAR*)_bstr_t(bstr, true);
::SysFreeString(bstr);
if(str.find(_T("gsdcheckbox")) != TString::npos)
{
DWORD dwDisable = 0;
if(!GenericRegistry::ReadDwordValue(REGISTRY_CONFIG_ENTRY_OUTLOOK,
REGISTRY_DISABLE_BCC, dwDisable))
{
dwDisable = 0;
GenericRegistry::WriteDwordValue(REGISTRY_CONFIG_ENTRY_OUTLOOK,
REGISTRY_DISABLE_BCC, dwDisable);
}
/* >>> the first parameter is the dispatch - Ugh!
// This should be the first parameter
if(dwDisable)
{
*(pdispparams->rgvarg[0].pboolVal) = VARIANT_TRUE;
}
else
*(pdispparams->rgvarg[0].pboolVal) = VARIANT_FALSE;
*/
}
}
}
}
}
return S_OK;
}
> The only callback signature I'm familiar with for onAction is something
> like this C# signature:
[quoted text clipped - 198 lines]
>> Thanks,
>> Tom
Ken Slovak - [MVP - Outlook] - 30 Jul 2009 22:26 GMT
The signature for a button's onAction callback is just the control, for a
checkbox it has 2 parameters: the control and a bool for pressed. In that
case the bool tells you the state of the checkbox. True == checked, false ==
unchecked.
For a checkbox in VB the getPressed signature is supposed to have 2
parameters: control and pressed. You set the pressed parameter to check the
checkbox and clear that bool to uncheck it. In VB terms that is passed
ByRef. In C# the signature is as a function with a bool return and only 1
parameter.
I was able to get the Tag property from control without any problems in a C#
test addin I keep around. It was null when I didn't set Tag in the ribbon
XML, it had the string value I set when I modified the XML to set the tag
property.
I'm curious if you'd have the same problem getting Tag in getPressed() on a
toggleButton?
I guess I can't really help with this any further, except to say that since
things work in both C# and VB6 testing I just did here that there must be
something in your implementation.
This does look correct:
//hr = spRibbon->get_Tag(&b);
with the call and BSTR return as far as I can see.
As a non-C++ guy I can't be more specific, and offhand I can't think of
another group that would be better for answers on this. About all I can
think of otherwise is to open a support case with MS. If you have MSDN you
can use one of your support incidents for that.

Signature
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
> Hi Ken,
>
[quoted text clipped - 99 lines]
> return S_OK;
> }
Tom - 30 Jul 2009 22:46 GMT
Thanks Ken.
Yes - I think I will open a support case.
BTW - I saw somebody else on a blog that had the exact same problem. But
nobody gave him an answer.
> The signature for a button's onAction callback is just the control, for a
> checkbox it has 2 parameters: the control and a bool for pressed. In that
[quoted text clipped - 134 lines]
>> return S_OK;
>> }
Ken Slovak - [MVP - Outlook] - 30 Jul 2009 23:01 GMT
We attribute some Outlook things to the phases of the moon, they're just
unsolvable <g>

Signature
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
> Thanks Ken.
>
> Yes - I think I will open a support case.
>
> BTW - I saw somebody else on a blog that had the exact same problem. But
> nobody gave him an answer.
Tom - 30 Jul 2009 23:18 GMT
Yes - we'll have to share a beer over that. I could tell you some good ones.
I am begining to see (unfortunately) the death of C++ in the Microsoft
world. This will make things extremely difficult designing any kind of low
level component.
Thanks agian for your thoughts on this!
> We attribute some Outlook things to the phases of the moon, they're just
> unsolvable <g>
[quoted text clipped - 5 lines]
>> BTW - I saw somebody else on a blog that had the exact same problem. But
>> nobody gave him an answer.