Ribbon and a checkbox (C++ ATL)

  • Thread starter Thread starter Tom
  • Start date Start date
T

Tom

Hi,

I have run into a problem using the a checkbox within a Ribbon control. I
have a C++ COM component which I have implemented a ribbon solution that
works fine for all of the buttons; but does not work 100 percent for a
checkbox.

I originally implemented the ribbon logic in accordance with an article by
Jensen Harris (Using RibbonX with C++ and ATL) and implementing buttons was
not an issue. However I have not been able to get the checkbox logic to work
correctly.

The only difference with his implementation and mine is that I am handling
the IDispatch::invoke directly (for many reasons other than the ribbon).

I am able to capture the onAction event without problem. But the issue I am
facing is the getPressed event is not acting the way I would think. I am
expecting two parameters, one being the dispatch for the ribbon control and
the other being the return value of the initial state of the checkbox.
However when I capture the event I only receive one parameter. So I do get
the event (id 2) and I can see that it is the proper ID for the checkbox by
calling GetId. However if I try to call GetTag is throws an unhandeled
exception.

Does anybody have any idea what is going on? I think I am missing something
in the design.

Thanks,
Tom -
 
The obvious and dumb question is whether your getPressed() signature is
correct.

Can you access the other Context and Id control properties passed to
getPressed() as part of the IRibbonControl object passed to you?

Does it work if you do what Eric mentioned in the blog post and not use your
own implementation? That's probably the first thing I'd look at.
 
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
 
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
 
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;
}

Ken Slovak - said:
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
 
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.




Tom said:
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;
}
 
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.



Ken Slovak - said:
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.




Tom said:
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;
}
 
We attribute some Outlook things to the phases of the moon, they're just
unsolvable <g>
 
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!
 
Back
Top