locked
implementing a custom image for a Ribbon Button in C++ (native/raw) RRS feed

  • Question

  • I'm having a problem loading an Outlook/office image on the Ribbon button. The OnGetExplorerButtonImage() function gets called and the IPictureDisp** picture  variable 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:43 AM

Answers

  • Joel,

    You should be using IID_IPictureDisp in the call to OleCreatePictureIndirect.  You should also return the IPictureDisp interface pointer (e.g., (LPVOID *) picture).

    It might be more clear if you use  a temporary pointer in the call to OleCreatePictureIndirect -

    CComPtr<IPictureDisp> pPic;

    OleCreatePictureIndirect(&picDesc, IID_IPictureDisp, TRUE, (LPVOID*) &pPic);

    if(pPic)

     *picture = pPic.Detach();



    • Edited by RLWA32 Tuesday, December 29, 2015 1:18 AM
    • Marked as answer by Joel_Z Tuesday, December 29, 2015 3:00 PM
    Tuesday, December 29, 2015 1:12 AM

All replies

  • Joel,

    You should be using IID_IPictureDisp in the call to OleCreatePictureIndirect.  You should also return the IPictureDisp interface pointer (e.g., (LPVOID *) picture).

    It might be more clear if you use  a temporary pointer in the call to OleCreatePictureIndirect -

    CComPtr<IPictureDisp> pPic;

    OleCreatePictureIndirect(&picDesc, IID_IPictureDisp, TRUE, (LPVOID*) &pPic);

    if(pPic)

     *picture = pPic.Detach();



    • Edited by RLWA32 Tuesday, December 29, 2015 1:18 AM
    • Marked as answer by Joel_Z Tuesday, December 29, 2015 3:00 PM
    Tuesday, December 29, 2015 1:12 AM
  • I had not called Detach(). I was uploading an example VS2015 project, but my signal sucks and its timing out doing an upload (cellular). I'll try these tips tomorrow and dig deeper into IID_IPictureDisp. Thank you! 
    Tuesday, December 29, 2015 2:36 AM
  • In your code there is no CComPtr object on which Detach() can be called.  It tries to use the parameter passed in as IPictureDisp **picture.  That's why my first suggestion was to change the way it used the picture parameter in the call to OleCreatePitureIndirect.
    Tuesday, December 29, 2015 4:19 AM
  • That was it. Awesome!

    As an aside for anyone re-using the Xml, add the Size attribute was needed.


    • Edited by Joel_Z Tuesday, December 29, 2015 3:36 PM
    Tuesday, December 29, 2015 3:05 PM