none
How can I add the images to button using the ribbon xml? RRS feed

  • Question

  • Hi,

    How to add the custom images to the ribbon button in the tab and the context menu.

    I tried the link Adding Image to ribbon button but no luck :-(. I am designing the addin for Excel.

    Please someone help me in this.

    I am using .net 4.0 C# VSTO 2010 for office 2010

    Thanks


    Roopini


    • Edited by Roopini Monday, February 3, 2014 10:30 AM
    Monday, February 3, 2014 10:28 AM

Answers

  • Hello Roopini,

    What code and markup do you use for loading images? What image file format do you use for the custom UI?

    There are two possible ways for getting the job done. Both of them are described in the Customizing the 2007 Office Fluent Ribbon for Developers article in MSDN:

    1. The <customUI> element's loadImage attribute enables you to specify a callback that can load all images. After you set up this callback procedure, Office calls the callback procedure and passes the string from the image attribute for each control that loads images. You do not need to implement the getImage callback multiple times, such as one time for each control that requires images.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
      loadImage="GetImage">
    <!-- Later in the markup -->
       <button id="myButton" image="image.jpg" />

    To supply the button's image, Office calls the GetImage function. It passes the parameter "mypic.jpg" and expects an IPictureDisp object in return. By using this technique, you can write a single callback procedure that returns all the images your customization needs, without having to write each individual control's getImage callback. Note that the loadImage callback is not called again when you call the Ribbon's Invalidate method or InvalidateControl method. For the controls that need to change images dynamically at run time, use the getImage callback.

    For example, the callback might look like the following one:

    public stdole.IPictureDisp GetImage(string imageName)
    {
      return
        PictureConverter.IconToPictureDisp(Properties.Resources.MyIcon);
    }
    

    2. The second approach can be used when you need to load images dynamically. Instead of the image attribute you need to specify the callback function name:

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
      loadImage="GetImage">
    <!-- Later in the markup -->
       <button id="myButton" getImage="GetImageCallback.jpg" />

    The getImage callback method must return a stdole.IPictureDisp type, so you usually need to convert your images to this type. To perform these conversions, you can use the following PictureConverter class, which inherits from the AxHost class.

    internal class PictureConverter : AxHost
    {
      private PictureConverter() : base(String.Empty) { }
    
      static public stdole.IPictureDisp ImageToPictureDisp(Image image)
      {
        return (stdole.IPictureDisp)GetIPictureDispFromPicture(image);
      }
    
      static public stdole.IPictureDisp IconToPictureDisp(Icon icon)
      {
        return ImageToPictureDisp(icon.ToBitmap());
      }
    
      static public Image PictureDispToImage(stdole.IPictureDisp picture)
      {
        return GetPictureFromIPicture(picture);
      }
    }

    For example, the callback might look like the following one:

    public stdole.IPictureDisp GetImageCallback(IRibbonControl control)
    {
      return
        PictureConverter.IconToPictureDisp(Properties.Resources.MyIcon);
    }

    It is up to you wich way is to choose.

    • Edited by Eugene Astafiev Monday, February 3, 2014 11:08 AM typos
    • Marked as answer by Roopini Wednesday, February 5, 2014 8:45 AM
    Monday, February 3, 2014 11:06 AM

All replies

  • Hello Roopini,

    What code and markup do you use for loading images? What image file format do you use for the custom UI?

    There are two possible ways for getting the job done. Both of them are described in the Customizing the 2007 Office Fluent Ribbon for Developers article in MSDN:

    1. The <customUI> element's loadImage attribute enables you to specify a callback that can load all images. After you set up this callback procedure, Office calls the callback procedure and passes the string from the image attribute for each control that loads images. You do not need to implement the getImage callback multiple times, such as one time for each control that requires images.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
      loadImage="GetImage">
    <!-- Later in the markup -->
       <button id="myButton" image="image.jpg" />

    To supply the button's image, Office calls the GetImage function. It passes the parameter "mypic.jpg" and expects an IPictureDisp object in return. By using this technique, you can write a single callback procedure that returns all the images your customization needs, without having to write each individual control's getImage callback. Note that the loadImage callback is not called again when you call the Ribbon's Invalidate method or InvalidateControl method. For the controls that need to change images dynamically at run time, use the getImage callback.

    For example, the callback might look like the following one:

    public stdole.IPictureDisp GetImage(string imageName)
    {
      return
        PictureConverter.IconToPictureDisp(Properties.Resources.MyIcon);
    }
    

    2. The second approach can be used when you need to load images dynamically. Instead of the image attribute you need to specify the callback function name:

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
      loadImage="GetImage">
    <!-- Later in the markup -->
       <button id="myButton" getImage="GetImageCallback.jpg" />

    The getImage callback method must return a stdole.IPictureDisp type, so you usually need to convert your images to this type. To perform these conversions, you can use the following PictureConverter class, which inherits from the AxHost class.

    internal class PictureConverter : AxHost
    {
      private PictureConverter() : base(String.Empty) { }
    
      static public stdole.IPictureDisp ImageToPictureDisp(Image image)
      {
        return (stdole.IPictureDisp)GetIPictureDispFromPicture(image);
      }
    
      static public stdole.IPictureDisp IconToPictureDisp(Icon icon)
      {
        return ImageToPictureDisp(icon.ToBitmap());
      }
    
      static public Image PictureDispToImage(stdole.IPictureDisp picture)
      {
        return GetPictureFromIPicture(picture);
      }
    }

    For example, the callback might look like the following one:

    public stdole.IPictureDisp GetImageCallback(IRibbonControl control)
    {
      return
        PictureConverter.IconToPictureDisp(Properties.Resources.MyIcon);
    }

    It is up to you wich way is to choose.

    • Edited by Eugene Astafiev Monday, February 3, 2014 11:08 AM typos
    • Marked as answer by Roopini Wednesday, February 5, 2014 8:45 AM
    Monday, February 3, 2014 11:06 AM
  • Hi Eugene,

    I want to use five images for 5 different button,

    so can I use the 1st solution you have mentioned?


    Roopini

    • Marked as answer by Roopini Wednesday, February 5, 2014 8:45 AM
    • Unmarked as answer by Roopini Wednesday, February 5, 2014 8:45 AM
    Tuesday, February 4, 2014 2:24 AM
  • Hi,

    I added this in the header

    <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load" loadImage="Ribbon_LoadImage"> 
    
    <button id="btn2d" keytip="L" screentip="label" supertip="2D Part Visualization" label="2D" size="large"/>
    
       <contextMenu idMso="ContextMenuCell">
       <button id="btn1" label="my label"/>
    </customUI>

    and the code snippet i added in the callback is

     public Bitmap Ribbon_LoadImage(IRibbonControl control)
            {
                switch (control.Id)
                {
                    case "btn2": return new Bitmap(Properties.Resources._2D);
                    case "btn3": return new Bitmap(Properties.Resources._3D);
                    case "btn4": return new Bitmap(Properties.Resources._3Dm);
                    case "btn5": return new Bitmap(Properties.Resources.Filter);
                    case "btnOpt6": return new Bitmap(Properties.Resources.Settings);
                    case "btnInform7": return new Bitmap(Properties.Resources.Vis);
                    case "btnHelpPage": return new Bitmap(Properties.Resources.Help);
                }
                return null;
            }

    am I missing out something?


    Roopini


    • Edited by Roopini Tuesday, February 4, 2014 4:33 AM
    Tuesday, February 4, 2014 4:13 AM
  • Hi Roopini,

    Yes, you are on the right avenue. If you are not going to change images at runtime you can use the first solution provided above.

    Tuesday, February 4, 2014 7:39 PM
  • Roopini,

    The getImage callback should return an instance of the stdole.IPictureDisp interface. I provided a sample piece of code in my first reply to you:

    public stdole.IPictureDisp GetImage(string imageName)
    {
      return
        PictureConverter.IconToPictureDisp(Properties.Resources.MyIcon);
    }

    You can use the PictureConverter class as I already mentioned above:

    internal class PictureConverter : AxHost
    {
      private PictureConverter() : base(String.Empty) { }
    
      static public stdole.IPictureDisp ImageToPictureDisp(Image image)
      {
        return (stdole.IPictureDisp)GetIPictureDispFromPicture(image);
      }
    
      static public stdole.IPictureDisp IconToPictureDisp(Icon icon)
      {
        return ImageToPictureDisp(icon.ToBitmap());
      }
    
      static public Image PictureDispToImage(stdole.IPictureDisp picture)
      {
        return GetPictureFromIPicture(picture);
      }
    }

    Tuesday, February 4, 2014 7:42 PM