locked
Enabling/Disabling Custom buttons RRS feed

  • Question

  • Hi,

    I need to enable/disable custom buttons in my un-managed add-in. If a selection is a message then enable otherwise show the button as disabled. How to achieve this?

    My xml is

    <customUI onLoad="OnLoadCallback" xmlns="http://schemas.microsoft.com/office/2006/01/customui" xmlns:mso="http://schemas.microsoft.com/office/2009/07/customui">
      <ribbon>
        <tabs>
          <tab idQ="mso:TabMail">
            <group id="MyGroup" label="MyGroup">
              <button id="MyButton"
                    getEnabled="GetEnabledCallback"
                    getImage="MyImage"
                    label="MyImage"
                    onAction="OnClick"/>
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>

    Now when I write a callback  "GetEnabledCallback" function by default that button gets disabled without having anything in the function.

        STDMETHOD(GetEnabledCallback)(IDispatch* ribbon)
        {   

        return S_OK;

        }

    How can I solve this problem? Please let me know if you need any more information.

    Thanks,

    AK


    -AK
    Saturday, October 22, 2011 7:14 PM

Answers

  • Trap the Explorer.SelectionChange event and call IRibbonUI.InvalidateControl().

    IRibbonUI is passed to your add-in in the OnLoad callback specified in your Explorer ribbon XML.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    • Proposed as answer by Calvin_Gao Monday, October 24, 2011 8:17 AM
    • Marked as answer by akulka0 Wednesday, November 2, 2011 1:22 AM
    Saturday, October 22, 2011 8:04 PM
  • Hi,

    I think there are two places you need to modify.

    1. The C++ signature for getEnabled should be:  
    HRESULT GetEnabled([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarfEnabled)
    

    For more information about this, please refer to: http://msdn.microsoft.com/en-us/library/aa722523.aspx

    2. Callbacks doesn't works like your image. When the tab is first displayed, Office will call the
    corresponding procedures to retrieve required data for each properties of each controls.

    If you want to change some property somtime later, you can't just update an control's property. Instead,

    there is a interface, which just like Dmitry said, to tell Office that information provided in earlier callback is

    no longer valid, thus the corresponding callback will be called again. See the method:

    http://msdn.microsoft.com/en-us/library/microsoft.office.core.iribbonui.invalidatecontrol.aspx

    I hope this helps.


    Best Regards, Calvin Gao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    • Edited by Calvin_Gao Monday, October 24, 2011 8:16 AM
    • Marked as answer by akulka0 Wednesday, November 2, 2011 1:22 AM
    Monday, October 24, 2011 8:16 AM

All replies

  • Trap the Explorer.SelectionChange event and call IRibbonUI.InvalidateControl().

    IRibbonUI is passed to your add-in in the OnLoad callback specified in your Explorer ribbon XML.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    • Proposed as answer by Calvin_Gao Monday, October 24, 2011 8:17 AM
    • Marked as answer by akulka0 Wednesday, November 2, 2011 1:22 AM
    Saturday, October 22, 2011 8:04 PM
  • Hi,

    I think there are two places you need to modify.

    1. The C++ signature for getEnabled should be:  
    HRESULT GetEnabled([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarfEnabled)
    

    For more information about this, please refer to: http://msdn.microsoft.com/en-us/library/aa722523.aspx

    2. Callbacks doesn't works like your image. When the tab is first displayed, Office will call the
    corresponding procedures to retrieve required data for each properties of each controls.

    If you want to change some property somtime later, you can't just update an control's property. Instead,

    there is a interface, which just like Dmitry said, to tell Office that information provided in earlier callback is

    no longer valid, thus the corresponding callback will be called again. See the method:

    http://msdn.microsoft.com/en-us/library/microsoft.office.core.iribbonui.invalidatecontrol.aspx

    I hope this helps.


    Best Regards, Calvin Gao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    • Edited by Calvin_Gao Monday, October 24, 2011 8:16 AM
    • Marked as answer by akulka0 Wednesday, November 2, 2011 1:22 AM
    Monday, October 24, 2011 8:16 AM
  • I was trying to trap the Explorer events however I am not getting the output. I am just trying to display an message when any event happens. Below is the code where I am trying to achieve this:


            In my.cpp:
           
            _ATL_FUNC_INFO SelnChange= {CC_STDCALL,VT_EMPTY,0};
       
            In my.h:
           
            extern _ATL_FUNC_INFO SelnChange;
           
            typedef public IDispEventSimpleImpl<1, CMyRibbon, &__uuidof(Outlook::ExplorerEvents)> ExpEvents;

            void __stdcall OnSelectionChange()
            {
                MessageBoxW(NULL,L"There is a selection!",L"Outlook Addin",MB_OK);
            }
           
            BEGIN_SINK_MAP(MyClass)
                SINK_ENTRY_INFO(1, __uuidof(Outlook::ExplorerEvents), 0xf001, OnSelectionChange, &SelnChange)
            END_SINK_MAP()

            In OnConnection(in my.h) Method:
           
            HRESULT hr;
            hr = ExpEvents::DispEventAdvise((IDispatch*)testExplorer, &__uuidof(Outlook::ExplorerEvents));       
            if(hr == E_FAIL)
            {
                MessageBoxW(NULL,L"Selection Change Event failed",L"Outlook Addin",MB_OK);       
            }
           
            In OnDisconnection(in my.h) Method:


            ExpEvents::DispEventUnadvise((IDispatch*)testExplorer);
           
           
    Also I noticed in MSDN ExplorerEvents Interface the description for SelectionChange is given as "This is a member in an event interface in a COM coclass. It is not intended to be used in your code." Am I using the wrong interface?


    -AK
    Monday, October 24, 2011 10:21 PM
  • Where did you declare testExplorer? Is it still alive when an event is supposed to be executed?
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Monday, October 24, 2011 10:36 PM
  • Yes, it is alive. I stored it in OnConnection method.
    -AK
    Monday, October 24, 2011 10:39 PM
  • Figured it out. Made a mistake, did not invoke the callback function. But now if I invoke the 'OnSelectionChange' function the application is throwing me error

    pdispparams->cargs ==(UINT)info.nparams error

    I am using the same invoke function as given in the link http://msdn.microsoft.com/en-us/library/ee941475.aspx.

     


    -AK
    Tuesday, October 25, 2011 1:51 AM
  • Is GetEnabledCallback() a global function? Or is it a member of a class that implements the dispinterface?
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Tuesday, October 25, 2011 3:01 AM
  • GetEnabledCallback()  is a member of a class that implements the dispinterface.

     

     


    -AK
    Tuesday, October 25, 2011 7:23 PM
  • So it is your code that is throwing the exception?

    What are the values of pdispparams->cargs  and info.nparams?


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Tuesday, October 25, 2011 7:51 PM
  • I am getting value 0 for pdispparams->cargs and nothing in info.nparams.
    -AK
    Friday, October 28, 2011 9:23 PM
  • "Nothing" as in 0? Or null?
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Friday, October 28, 2011 9:28 PM
  • When I debug it throws me an error in atlcom.h and in that info.params  comes as

    nParams   CXX0030: Error: expression cannot be evaluated   


    -AK
    Friday, October 28, 2011 9:35 PM
  • I changed SelnChange to having 2 parameters.    

       In my.cpp:
           
            _ATL_FUNC_INFO SelnChange= {CC_STDCALL,VT_EMPTY,2,{VT_DISPATCH, VT_BOOL}};
       
       In my.h:
           
            extern _ATL_FUNC_INFO SelnChange;
           
            typedef public IDispEventSimpleImpl<1, CMyRibbon, &__uuidof(Outlook::ExplorerEvents)> ExpEvents;

            void __stdcall ::OnSelectionChange(IDispatch* ribbon, VARIANT_BOOL bEnabled)

            {
                MessageBoxW(NULL,L"There is a selection!",L"Outlook Addin",MB_OK);
            }

    This is where invoke is not working properly.

     

     

     


    -AK
    Friday, October 28, 2011 9:48 PM
  • Why 2? Ir is not supposde to have any parameters.
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Tuesday, November 1, 2011 10:43 PM
  • Yes, I realized that after posting the post. I corrected that with 0 parameters. It is working fine now. I am able to catch the events and also able to enable/disable the buttons.

    Thanks a lot!


    -AK
    Wednesday, November 2, 2011 1:21 AM