none
Problems implementing a custom image for a Ribbon Button in C++ (native) RRS feed

  • Question

  • I have a COM C++ Outlook add-in with a ribbon button. The button works like a dream, but I'd like to customize the button look to have a .jpg image to reflect branding. I've searched high and low on how to do this, but came up short in finding a how-to or something close to that. Most examples and docs refer to managed code (VBA, C#, VB).

    I've found that to add a custom button, add a callback function name to the ribbon xml and then in that callback, load the image. My breakpoint doesn't hit that I put on the OnGetExplorerButtonImage function. I'm posting to find out why that might be (or how do I investigate the problem) and how would I load a .jpg image? I don't have an .ico nor .bmp.

    STDMETHODIMP CFromCloud::OnGetExplorerButtonImage(IDispatch* ribbon, IPictureDisp** picture) {
    
        return S_OK;
    }
    

    IDL:

    [
    	object,
    	uuid(56CE81E4-0BCD-44FB-8630-BC803865ED69),
    	dual,
    	nonextensible,
    	pointer_default(unique)
    ]
    interface IFromCloud : IDispatch{
        HRESULT OnCloudClicked([in] IDispatch* pControl);
        HRESULT OnGetExplorerButtonImage([in]IDispatch* ribbon, [out]IPictureDisp** picture);
    };

    Ribbon button XML:

    <?xml version="1.0" encoding="us-ascii"?>
    <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
      <ribbon>
        <tabs>
          <tab idMso="TabMail">
            <group id="CloudGroup" label="FromCloud" insertAfterMso="GroupMailDelete">
              <button id="CloudButtton" label="Cloud File Services" onAction="OnCloudClicked" getImage="OnGetExplorerButtonImage" />
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>


    • Edited by Joel_Z Sunday, December 20, 2015 6:48 PM
    Sunday, December 20, 2015 6:47 PM

All replies

  • Hi Joel

    VBA is not managed code. VBA is COM and the "native" language for Office.

    As I recall, the optimal graphic format for button images is PNG.

    I'm not familiar with C++, but comparing the method signature you use with that in the documentation for getImage I see a discrepancy for the second parameter:

    HRESULT GetImage([in] IRibbonControl *pControl, [out, retval] IPictureDisp ** ppdispImage)

    The retval is missing in your code?


    Cindy Meister, Office Developer/Word MVP, <a href="http://blogs.msmvps.com/wordmeister"> my blog</a>

    Monday, December 21, 2015 5:42 PM
    Moderator
  • Monday, December 21, 2015 8:41 PM
  • Hi Joel

    VBA is not managed code. VBA is COM and the "native" language for Office.

    As I recall, the optimal graphic format for button images is PNG.

    I'm not familiar with C++, but comparing the method signature you use with that in the documentation for getImage I see a discrepancy for the second parameter:

    HRESULT GetImage([in] IRibbonControl *pControl, [out, retval] IPictureDisp ** ppdispImage)

    The retval is missing in your code?


    Cindy Meister, Office Developer/Word MVP, <a href="http://blogs.msmvps.com/wordmeister"> my blog</a>

    Yes, it was missing.

    VBA is not COM.

    Thursday, December 24, 2015 11:11 PM
  • I've worked through the problem past the point where the callback wasn't firing thanks to Cindy. The icon still doesn't load though. The OnGetExplorerButtonImage() function gets called and the picture has a valid pointer. See the attached image demonstrating the problem. "Cloud File Services" should be under the icon. But the icon is missing and the label is moved up. Any ideas on how I can fix this?

    STDMETHODIMP CFromCloud::OnGetExplorerButtonImage(IDispatch* ribbon, IPictureDisp** picture) {
        IID IID_Picture;
        HRESULT hRes = E_FAIL;
        IIDFromString(L"{7BF80980-BF32-101A-8BBB-00AA00300CAB}", &IID_Picture);
        HANDLE hBtnImg = LoadImage(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDB_FROMCLOUD), IMAGE_BITMAP, 65, 64, LR_DEFAULTSIZE); 
        if(NULL == hBtnImg) 
            return S_OK;
    
        PICTDESC picDesc            = {0}; 
        picDesc.bmp.hbitmap         = (HBITMAP)hBtnImg;
        picDesc.picType             = PICTYPE_BITMAP; 
        picDesc.cbSizeofstruct      = sizeof(picDesc); 
        OleCreatePictureIndirect(&picDesc, IID_Picture, true, reinterpret_cast<LPVOID*>(&picture));
        return S_OK;
    }
    <?xml version="1.0" encoding="us-ascii"?>
    <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
      <ribbon>
        <tabs>
          <tab idMso="TabMail">
            <group id="CloudGroup" label="FromCloud" insertAfterMso="GroupMailDelete">
              <button id="CloudButtton" label="Cloud File Services" screentip="FromCloud File Services List" onAction="OnCloudClicked" getImage="OnGetExplorerButtonImage" />
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>


    Tuesday, December 29, 2015 12:06 AM
  • Since this is in the Outlook interface would you like me to move the question to the Outlook for Developers forum?

    Cindy Meister, Office Developer/Word MVP, <a href="http://blogs.msmvps.com/wordmeister"> my blog</a>

    Monday, January 4, 2016 9:21 AM
    Moderator