Click here to Skip to main content
15,894,825 members
Articles / Multimedia / GDI+

Multiple Image Sizes for ToolStrip Items

Rate me:
Please Sign up or sign in to vote.
4.74/5 (18 votes)
3 Aug 2009MIT3 min read 123.3K   6.9K   78   17
This 'ToolStrip' extension automatically selects an image using the selected image size.

IconToolStrip_demo

Introduction

Tool strips are a fantastic asset because they provide a tidy and user-friendly interface for the user. It is possible to add images to many of the different tool strip items. It is even possible to force such items to appear larger by adjusting the property ImageScalingSize, however at the cost of pixelisation.

Usually it is desirable to make our applications as accessible as possible. Larger tool strip items are fantastic for those with poorer sight, or even those who just simply enjoy the quality of larger icons. Unfortunately, the standard ToolStrip class does not provide Icon support. When an icon is specified, it is converted into an Image instance. Thus the benefits of using an icon are lost.

So I decided that it would be a nice idea to add multi-image support to the ToolStrip control. Whilst my primary focus was on adding some support for Icon, I thought it more desirable to generalize this by using the two interfaces IImageProvider and IMultipleImageProvider.

Design

When MultipleImageToolStrip is being updated, it calls upon available IImageProvider's to acquire images of the required size.

An IImageProvider exposes the two methods IsImageSupported and GetImage. When multiple icon providers are available, it is possible to access the required icon using a key. In the code supplied with this article, the key represents a ToolStripItem. The following illustration provides an overview of the design using a UML class diagram.

multi_image_tooltips/uml-overview.png

When no IImageProvider is available, the original ToolStripItem is maintained and stretched where necessary to match the overall tool strip size.

For my extension, I decided that four discreet sizes would ease the implementation of custom image providers. The available sizes are: Small (16 x 16), Medium (24 x 24), Large (32 x 32), and ExtraLarge (48 x 48). When the requested image size is not available, a default icon can be automatically substituted if the MultipleImageToolStrip.UseUnknownImageSizeIcon is set to true.

Images are selected as follows:

  • If an image provider is available from within the tool strip:
    • If the required image size is supported, that image is acquired.
    • If the required image size was not supported and UseUnknownImageSizeIcon is set, the default image provider is utilized.
    • When no image can be acquired using those criteria, the original image is simply stretched to match that of the scaled buttons.
  • If the above fails and the item is itself an IImageProvider then it is used to acquire the required image.
  • Finally if the items ToolStripItem.Tag is an IImageProvider then it is used to acquire the required image.

Using the Code

It is always a good idea to backup your project before trying something new!

To use the attached code simply:

  • Add the source files to your project.
  • Recompile your project.
  • Drag MultipleImageToolStrip onto your Form or UserControl from the tool box.
  • Add some buttons.
  • You should now have a ToolStrip which behaves much the same as before.

If you want to convert an existing ToolStrip into a MultipleImageToolStrip:

  • Find the ".designer.cs" file which is associated with your form or control.
  • Open it up and replace instances of ToolStrip with MultipleImageToolStrip.

To make items automatically resizable, add a handler for your form's (or control's) Load event. Take a look below for an example of how to do this:

C#
private void Form1_Load(object sender, EventArgs e)
{
    // Begin updating tool strip images. This is important because it prevents
    // the tool strip from refreshing after each image assignment.
    this.iconToolStrip.BeginUpdateImages();

    // Here it is possible to provide an 'IImageProvider' instance.
    this.iconToolStrip.AssignImage(toolStripBack, new IconImageProvider(
        Resources.arrow_left));

    // Or just provide icons themselves.
    this.iconToolStrip.AssignImage(toolStripForward, Resources.arrow_right);
    this.iconToolStrip.AssignImage(toolStripHome, Resources.home);
    this.iconToolStrip.AssignImage(toolStripStop, Resources.stop);

    // Finalize updating.
    this.iconToolStrip.EndUpdateImages();

    // Then to select an initial icon size.
    this.iconToolStrip.ImageSize = ImageSize.Medium;
}

When a tool strip item is permanently removed, the associated IImageProvider must also be manually removed. This decision was made because often an item is only removed temporarily and then reinserted.

If you always want to remove an associated IImageProvider when a tool item is removed, add a handler for the MultipleImageToolStrip.ItemRemove event:

C#
private void iconToolStrip_ItemRemoved(object sender, ToolStripItemEventArgs e)
{
    // Automatically remove associated image provider.
    this.iconToolStrip.RemoveImage(e.Item);
}

Alternatively the associated provider can be removed along with the item:

C#
public void RemoveToolStripItem(ToolStripItem item)
{
    // Remove item itself.
    this.iconToolStrip.Items.Remove(item);
    
    // Remove any associated provider.
    this.iconToolStrip.RemoveImage(item);
}

Points of Interest

The fantastic icons used in the demo application were kindly provided by glyFX from their free 'Vista Common' icon set. The required icons were combined together using the free IcoFX tool.

History

  • 16th June, 2008: Original version posted
  • 3rd August, 2009: Demo and source files updated
    • Member Guy..L found a performance issue when changing multiple tool icons in sequence. This problem should now have been resolved.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer Rotorz Limited
United Kingdom United Kingdom
I have been fascinated by software and video games since a young age when I was given my first computer, a Dragon 32. Since then I have experimented with numerous methods of development ranging from point-and-click type packages to C++. I soon realized that software development was what I wanted to do.

Having invested a lot of time into programming with various languages and technologies I now find it quite easy to pickup new ideas and methodologies. I relish learning new ideas and concepts.

Throughout my life I have dabbled in game and engine development. I was awarded a first for the degree "BEng Games and Entertainment Systems Software Engineering" at the University of Greenwich. It was good to finally experience video games from a more professional perspective.

Due to various family difficulties I was unable to immediately pursue any sort of software development career. This didn't stop me from dabbling though!

Since then I formed a company to focus upon client projects. Up until now the company has primarily dealt with website design and development. I have since decided that it would be fun to go back to my roots and develop games and tools that other developers can use for their games.

We have recently released our first game on iPhone/iPad called "Munchy Bunny!" (see: http://itunes.apple.com/us/app/munchy-bunny!/id516575993?mt=8). We hope to expand the game and release to additional platforms.

Also, check out our tile system extension for Unity! (see: http://rotorz.com/tilesystem/)

Comments and Discussions

 
GeneralMy vote of 5 Pin
csharpbd27-Aug-13 10:26
professionalcsharpbd27-Aug-13 10:26 
GeneralMy vote of 1 Pin
Member 871442126-Nov-12 3:10
Member 871442126-Nov-12 3:10 
GeneralMy vote of 5 Pin
another1121-Aug-10 23:32
another1121-Aug-10 23:32 
GeneralI am getting an error when building the project Pin
nmichalo6-Jan-10 23:21
nmichalo6-Jan-10 23:21 
GeneralRe: I am getting an error when building the project Pin
Lea Hayes7-Jan-10 6:43
Lea Hayes7-Jan-10 6:43 
QuestionIDE reports that error occurs on the line "using IconToolStrip.Properties;".Why? Pin
GoodLucy25-Sep-09 2:31
GoodLucy25-Sep-09 2:31 
AnswerRe: IDE reports that error occurs on the line "using IconToolStrip.Properties;".Why? Pin
Lea Hayes25-Sep-09 3:51
Lea Hayes25-Sep-09 3:51 
GeneralToolStripManager for MultipleImageToolStrip Pin
Guy..L3-Aug-09 1:25
Guy..L3-Aug-09 1:25 
GeneralRe: ToolStripManager for MultipleImageToolStrip Pin
Lea Hayes4-Aug-09 5:14
Lea Hayes4-Aug-09 5:14 
This isn't a feature that I want to add to the control itself, but here are some instructions that you can follow to add this functionality:

Step 1. Use the following version of "IconToolStrip.cs":
Step 2. In your form designer set the "SaveSettings" property to "True".
Step 3. Build & Run.

This code does not use the "ToolStripManager" class, I don't think that there is any easy way of extending this. Instead the following uses the application settings file. Please note that if two forms have a toolstrip of the same Name, they WILL conflict.

Let me know how you get on!

IconToolStrip.cs:
=================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Drawing;
using System.Runtime.Serialization;
using System.Windows.Forms;

using IconToolStrip.Properties;

namespace IconToolStrip
{
    public enum ImageSize
    {
        /// <summary>
        /// An image of 16x16 pixels.
        /// </summary>
        Small,
        /// <summary>
        /// An image of 24x24 pixels.
        /// </summary>
        Medium,
        /// <summary>
        /// An image of 32x32 pixels.
        /// </summary>
        Large,
        /// <summary>
        /// An image of 48x48 pixels.
        /// </summary>
        ExtraLarge,
    }

    /// <summary>
    /// Implementations of this interface must indicate whether or not the
    /// requested image size is supported. A default image override could
    /// be enforced should the provider report with no support.
    /// </summary>
    public interface IImageProvider
    {
        #region Methods

        /// <summary>
        /// Queries the image provider for support of a specific size.
        /// </summary>
        /// <param name="size">Indicated image size.</param>
        /// <returns>Returns true when the requested size is supported.</returns>
        bool IsImageSupported(ImageSize size);

        /// <summary>
        /// Fetches an image of the requested size.
        /// </summary>
        /// <param name="size">Size of image to obtain.</param>
        /// <returns>If supported, returns requested image. A value of null
        /// indicates that the requested size is not supported.</returns>
        Image GetImage(ImageSize size);

        #endregion
    }

    /// <summary>
    /// Implementations of this interface can provide access to multiple
    /// different images of multiple different sizes. A default image override
    /// could be enforced should the provider report with no support.
    /// </summary>
    public interface IMultipleImageProvider
    {
        #region Methods

        /// <summary>
        /// Queries the image provider for support of a specific size.
        /// </summary>
        /// <param name="key">Key used to identify an image.</param>
        /// <param name="size">Indicated image size</param>
        /// <returns>Returns true when the requested size is supported.</returns>
        bool IsImageSupported(object key, ImageSize size);

        /// <summary>
        /// Fetches an image of the requested size.
        /// </summary>
        /// <param name="key">Key used to identify an image.</param>
        /// <param name="size">Size of image to obtain.</param>
        /// <returns>If supported, returns requested image. A value of null
        /// indicates that the requested size is not supported.</returns>
        Image GetImage(object key, ImageSize size);

        #endregion

        #region Properties

        /// <summary>
        /// Gets count of registered image providers.
        /// </summary>
        int ImageProviderCount { get; }

        #endregion
    }

    /// <summary>
    /// Provides a collection which pairs image providers with a key object.
    /// The collection can be used to provide access to different images of
    /// different sizes.
    /// </summary>
    public class ImageProviderCollection : Dictionary<object, IImageProvider>, IMultipleImageProvider
    {
        #region Construction and destruction

        public ImageProviderCollection()
            : base()
        {
        }

        public ImageProviderCollection(int capacity)
            : base(capacity)
        {
        }

        public ImageProviderCollection(ImageProviderCollection collection)
            : base(collection)
        {
        }

        public ImageProviderCollection(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        #endregion

        #region IMultipleImageProvider Members

        /// <summary>
        /// Queries the image provider for support of a specific size.
        /// </summary>
        /// <param name="key">Key used to identify an image.</param>
        /// <param name="size">Indicated image size</param>
        /// <returns>Returns true when the requested size is supported.</returns>
        public bool IsImageSupported(object key, ImageSize size)
        {
            if (!this.ContainsKey(key))
                return false;
            return this[key].IsImageSupported(size);
        }

        /// <summary>
        /// Fetches an image of the requested size.
        /// </summary>
        /// <param name="key">Key used to identify an image.</param>
        /// <param name="size">Size of image to obtain.</param>
        /// <returns>If supported, returns requested image. A value of null
        /// indicates that the requested size is not supported.</returns>
        public Image GetImage(object key, ImageSize size)
        {
            if (!this.ContainsKey(key))
                throw new NullReferenceException();
            return this[key].GetImage(size);
        }

        /// <summary>
        /// Gets count of registered image providers.
        /// </summary>
        int IMultipleImageProvider.ImageProviderCount
        {
            get { return Count; }
        }

        #endregion
    }

    /// <summary>
    /// Allows an icon to be used to provide images of different sizes.
    /// </summary>
    public class IconImageProvider : IImageProvider
    {
        #region Construction and destruction

        public IconImageProvider(Icon icon)
        {
            this.m_sourceIcon = icon;
        }

        public IconImageProvider(System.IO.Stream stream)
        {
            this.m_sourceIcon = new Icon(stream);
        }

        public IconImageProvider(string fileName)
        {
            this.m_sourceIcon = new Icon(fileName);
        }

        public IconImageProvider(Type type, string resource)
        {
            this.m_sourceIcon = new Icon(type, resource);
        }

        #endregion

        #region Global Utility Methods

        /// <summary>
        /// A utility method which transforms an enumerated image value into
        /// a two-dimensional size.
        /// </summary>
        /// <param name="size">Requested image size.</param>
        /// <returns>Returns a two-dimensional size.</returns>
        public static Size GetIconSize(ImageSize size)
        {
            switch (size)
            {
                case ImageSize.Small:
                    return new Size(16, 16);
                case ImageSize.Medium:
                    return new Size(24, 24);
                case ImageSize.Large:
                    return new Size(32, 32);
                case ImageSize.ExtraLarge:
                    return new Size(48, 48);
                default:
                    throw new NotSupportedException("Invalid image size requested.");
            }
        }

        #endregion

        #region Events

        /// <summary>
        /// Raised when the icon property is changed.
        /// </summary>
        public OldNewEventHandler<Icon> IconChanged;

        /// <summary>
        /// Invoked the 'IconChanged' event.
        /// </summary>
        /// <param name="e">Provides access to old and new icons.</param>
        public virtual void OnIconChanged(OldNewEventArgs<Icon> e)
        {
            if (this.IconChanged != null)
                this.IconChanged(this, e);
        }

        #endregion

        #region IImageProvider Members

        /// <summary>
        /// Queries the image provider for support of a specific size.
        /// </summary>
        /// <param name="size">Indicated image size.</param>
        /// <returns>Returns true when the requested size is supported.</returns>
        public bool IsImageSupported(ImageSize size)
        {
            return true;
        }

        /// <summary>
        /// Fetches an image of the requested size.
        /// </summary>
        /// <param name="size">Size of image to obtain.</param>
        /// <returns>If supported, returns requested image. A value of null
        /// indicates that the requested size is not supported.</returns>
        public Image GetImage(ImageSize size)
        {
            Icon desiredSize = new Icon(SourceIcon, IconImageProvider.GetIconSize(size));
            return desiredSize.ToBitmap();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the source icon.
        /// </summary>
        public Icon SourceIcon
        {
            get { return this.m_sourceIcon; }
            set
            {
                if (value != this.m_sourceIcon)
                {
                    Icon oldIcon = this.m_sourceIcon;
                    this.m_sourceIcon = value;
                    OnIconChanged(new OldNewEventArgs<Icon>(oldIcon, value));
                }
            }
        }

        #endregion

        #region Attributes

        private Icon m_sourceIcon;

        #endregion
    }

    /// <summary>
    /// Provides event handlers with the current and proposed image sizes.
    /// Event handlers can decide whether or not to cancel this procedure.
    /// </summary>
    public class ImageSizeChangingEventArgs : CancelEventArgs
    {
        #region Construction and destruction

        public ImageSizeChangingEventArgs(ImageSize oldValue, ImageSize newValue)
            : base(false)
        {
            this.m_currentValue = oldValue;
            this.m_newValue = newValue;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the current image size.
        /// </summary>
        public ImageSize CurrentValue
        {
            get { return this.m_currentValue; }
        }

        /// <summary>
        /// Gets the proposed image size.
        /// </summary>
        public ImageSize NewValue
        {
            get { return this.m_newValue; }
        }

        #endregion

        #region Attributes

        private ImageSize m_currentValue;
        private ImageSize m_newValue;

        #endregion
    }

    public delegate void ImageSizeChangingEventHandler(object sender, ImageSizeChangingEventArgs e);

    /// <summary>
    /// This toolstrip implements the multiple image provider interface and thus
    /// provides support for automatic image changes based upon the selected
    /// image size.
    /// </summary>
    public class MultipleImageToolStrip : ToolStrip, IMultipleImageProvider, IImageProvider, IPersistComponentSettings
    {
        #region Construction and destruction

        public MultipleImageToolStrip()
        {
            this.m_imageProvider = new ImageProviderCollection();
            this.m_defaultProvider = this;

            this.m_settings = new PersistentIconToolStripSettings((this as IPersistComponentSettings).SettingsKey);
        }

        #endregion

        #region Constants

        public const ImageSize DefaultImageSize = ImageSize.Small;

        #endregion

        #region Events

        /// <summary>
        /// Raised when image size is about to be changed.
        /// </summary>
        public event ImageSizeChangingEventHandler ImageSizeChanging;
        /// <summary>
        /// Raised when image size is changed.
        /// </summary>
        public event OldNewEventHandler<ImageSize> ImageSizeChanged;
        /// <summary>
        /// Raised when the property 'UseUnknownImageSizeIcon' is changed.
        /// </summary>
        public event EventHandler UseUnknownImageSizeIconChanged;

        /// <summary>
        /// Invokes the 'ImageSizeChanging' event handler.
        /// </summary>
        /// <param name="e">Event arguments.</param>
        /// <returns>Returns true when proposed change is accepted.</returns>
        protected virtual bool OnImageSizeChanging(ImageSizeChangingEventArgs e)
        {
            if (e.Cancel)
                return false;

            ImageSizeChangingEventHandler handler = this.ImageSizeChanging;
            if (handler != null)
            {
                handler(this, e);
                return !e.Cancel;
            }

            return true;
        }

        /// <summary>
        /// Invokes the 'ImageSizeChanged' event handler.
        /// </summary>
        /// <param name="e">Event arguments.</param>
        protected virtual void OnImageSizeChanged(OldNewEventArgs<ImageSize> e)
        {
            OldNewEventHandler<ImageSize> handler = this.ImageSizeChanged;
            if (handler != null)
                this.ImageSizeChanged(this, e);
        }

        /// <summary>
        /// Invokes the 'UseUnknownImageSizeIconChanged' event handler.
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnUseUnknownImageSizeIconChanged(EventArgs e)
        {
            // Refresh toolstrip images from providers?
            if (!IsUpdatingImages)
                RefreshItemImages();

            // Raise the associated event handler.
            EventHandler handler = this.UseUnknownImageSizeIconChanged;
            if (handler != null)
                this.UseUnknownImageSizeIconChanged(this, e);
        }

        #endregion

        #region IMultipleImageProvider Members

        /// <summary>
        /// Queries the image provider for support of a specific size.
        /// </summary>
        /// <param name="key">Key used to identify an image.</param>
        /// <param name="size">Indicated image size</param>
        /// <returns>Returns true when the requested size is supported.</returns>
        public virtual bool IsImageSupported(object key, ImageSize size)
        {
            return ImageProvider.IsImageSupported(key, size);
        }

        /// <summary>
        /// Fetches an image of the requested size.
        /// </summary>
        /// <param name="key">Key used to identify an image.</param>
        /// <param name="size">Size of image to obtain.</param>
        /// <returns>If supported, returns requested image. A value of null
        /// indicates that the requested size is not supported.</returns>
        public virtual Image GetImage(object key, ImageSize size)
        {
            return ImageProvider.GetImage(key, size);
        }

        /// <summary>
        /// Gets count of registered image providers.
        /// </summary>
        public virtual int ImageProviderCount
        {
            get { return ImageProvider.Count; }
        }

        #endregion

        #region IImageProvider Members

        /// <summary>
        /// Queries the image provider for support of a specific size.
        /// </summary>
        /// <param name="size">Indicated image size.</param>
        /// <returns>Returns true when the requested size is supported.</returns>
        public virtual bool IsImageSupported(ImageSize size)
        {
            if (DefaultImageProvider == null)
                return false;
            if (DefaultImageProvider == this)
                return true;

            return DefaultImageProvider.IsImageSupported(size);
        }

        /// <summary>
        /// Fetches an image of the requested size.
        /// </summary>
        /// <param name="size">Size of image to obtain.</param>
        /// <returns>If supported, returns requested image. A value of null
        /// indicates that the requested size is not supported.</returns>
        public virtual Image GetImage(ImageSize size)
        {
            if (DefaultImageProvider == null)
                throw new NullReferenceException();

            if (DefaultImageProvider == this)
            {
                Size iconSize = IconImageProvider.GetIconSize(size);
                Icon iconResult = new Icon(Resources.stop, iconSize);
                return iconResult.ToBitmap();
            }

            return DefaultImageProvider.GetImage(size);
        }

        #endregion

        #region IPersistComponentSettings Members

        public void LoadComponentSettings()
        {
            // Read settings from the settings provider.
            Settings.Reload();
            ApplySettings();
        }

        public void ResetComponentSettings()
        {
            // Reset to the default image size.
            Settings.Reset();
            ApplySettings();
        }

        public void SaveComponentSettings()
        {
            // Save settings to the settings provider.
            RetrieveSettings();
            Settings.Save();
        }

        protected virtual void ApplySettings()
        {
            this.ImageSize = Settings.ImageSize;
        }

        protected virtual void RetrieveSettings()
        {
            Settings.ImageSize = this.ImageSize;
        }

        [DefaultValue(false)]
        public bool SaveSettings
        {
            get; set;
        }

        string IPersistComponentSettings.SettingsKey
        {
            get { return this.Name; }
            set { throw new NotSupportedException(); }
        }

        #endregion

        #region ToolStrip Overrides

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                try
                {
                    SaveComponentSettings();
                }
                finally
                {
                }
            }

            base.Dispose(disposing);
        }

        #endregion

        #region Methods

        /// <summary>
        /// Call to begin a batch image provider update more efficiently.
        /// Each 'BeginImageProviderUpdate' call <b>MUST</b> be paired with
        /// an 'EndImageProviderUpdate' call.
        /// </summary>
        public virtual void BeginUpdateImages()
        {
            IsUpdatingImages = true;
        }

        /// <summary>
        /// Call to end a batch image provider update. Please note that any
        /// image refreshements only occur when all nested updates are ended.
        /// </summary>
        /// <param name="refresh">Indicates if image sizes are to be refreshed.</param>
        public virtual void EndUpdateImages(bool refresh)
        {
            if (!IsUpdatingImages)
                throw new NotSupportedException();

            IsUpdatingImages = false;

            // Only apply updates when image providers have been changed.
            if (HasImagesChanged)
            {
                HasImagesChanged = false;

                // If no longer updating image providers (i.e. no nested calls), then
                // refresh the image sizes.
                if (!IsUpdatingImages && refresh)
                    RefreshItemImages();
            }
        }

        /// <summary>
        /// Call to end a batch image provider update. Please note that
        /// image refreshements only occur when all nested updates are ended.
        /// </summary>
        public void EndUpdateImages()
        {
            EndUpdateImages(true);
        }

        /// <summary>
        /// Assigns an image provider for the specified item.
        /// </summary>
        /// <param name="item">Associated toolstrip item.</param>
        /// <param name="provider">Image provider.</param>
        /// <returns>Returns true when successful.</returns>
        public bool AssignImage(ToolStripItem item, IImageProvider provider)
        {
            if (item == null || provider == null)
                throw new ArgumentException("One or more arguments were null references.");
            if (ContainsImage(item))
                return false;

            ImageProvider.Add(item, provider);
            HasImagesChanged = true;

            if (!IsUpdatingImages)
                RefreshItemImages();

            return true;
        }

        /// <summary>
        /// Assigns an image provider for the specified item.
        /// </summary>
        /// <param name="item">Associated toolstrip item.</param>
        /// <param name="item">Associated multi-icon.</param>
        /// <returns>Returns true when successful.</returns>
        public bool AssignImage(ToolStripItem item, Icon icon)
        {
            return AssignImage(item, new IconImageProvider(icon));
        }

        /// <summary>
        /// Unregisters an image provider.
        /// </summary>
        /// <param name="item">Associated toolstrip item.</param>
        /// <returns>Returns true when successful.</returns>
        public bool RemoveImage(ToolStripItem item)
        {
            if (ImageProvider.Remove(item))
            {
                HasImagesChanged = true;

                if (!IsUpdatingImages)
                    RefreshItemImages();
                return true;
            }
            return false;
        }

        /// <summary>
        /// Remove image providers which are not referenced with a <c>ToolStripItem</c>.
        /// </summary>
        /// <returns>Returns count of items removed.</returns>
        public int RemoveUnusedImages()
        {
            List<ToolStripItem> removeList = new List<ToolStripItem>();
            int count = 0;

            // Compile a list of all items which are to be removed.
            foreach (ToolStripItem key in ImageProvider.Keys)
                if (!Items.Contains(key as ToolStripItem))
                    removeList.Add(key);
            count = removeList.Count;

            // Remove each item from provider collection.
            foreach (ToolStripItem item in removeList)
                RemoveImage(item);

            // Make sure that the removal list is disposed of.
            removeList = null;
            return count;
        }

        /// <summary>
        /// Searches for the a provider which is associated with a toolstrip item.
        /// </summary>
        /// <param name="item">Toolstrip item.</param>
        /// <returns>Returns true when an associated provider is found.</returns>
        public bool ContainsImage(ToolStripItem item)
        {
            return ImageProvider.ContainsKey(item);
        }

        /// <summary>
        /// Forces all images sizes to be refreshed from the respective providers.
        /// </summary>
        protected void RefreshItemImages()
        {
            Size imageSize = IconImageProvider.GetIconSize(ImageSize);
            ImageScalingSize = imageSize;

            bool changesMade = false;
            IImageProvider imageProvider = null;
            
            SuspendLayout();

            foreach (ToolStripItem item in Items)
            {
                if (item.Size != imageSize)
                {
                    imageProvider = null;

                    // If an image provider was registered with the toolstrip then...
                    if (ContainsImage(item))
                    {
                        if (IsImageSupported(item, ImageSize))
                            item.Image = GetImage(item, ImageSize);
                        else if (UseUnknownImageSizeIcon && IsImageSupported(ImageSize))
                            item.Image = GetImage(ImageSize);

                        changesMade = true;
                    }
                    else if (item is IImageProvider)
                    {
                        imageProvider = item as IImageProvider;
                    }
                    else if (item.Tag is IImageProvider)
                    {
                        imageProvider = item.Tag as IImageProvider;
                    }

                    // If an alternative image provider was found, attempt to use that.
                    if (!changesMade && imageProvider != null)
                    {
                        if (imageProvider.IsImageSupported(ImageSize))
                        {
                            item.Image = imageProvider.GetImage(ImageSize);
                            changesMade = true;
                        }
                    }

                    // Were changes made?
                    if (changesMade)
                    {
                        // Automatically adjust the image scaling mode.
                        if (item.Image != null && item.Image.Size == imageSize)
                            item.ImageScaling = ToolStripItemImageScaling.None;
                        else
                            item.ImageScaling = ToolStripItemImageScaling.SizeToFit;
                    }
                }
            }

            ResumeLayout();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the default image provider.
        /// </summary>
        public IImageProvider DefaultImageProvider
        {
            get { return this.m_defaultProvider; }
            set { this.m_defaultProvider = value; }
        }

        /// <summary>
        /// Gets the active multiple image provider.
        /// </summary>
        protected ImageProviderCollection ImageProvider
        {
            get { return this.m_imageProvider; }
        }

        /// <summary>
        /// Gets or sets the active toolstrip item images sizes.
        /// </summary>
        public ImageSize ImageSize
        {
            get { return this.m_imageSize; }
            set
            {
                if (value != this.m_imageSize)
                {
                    ImageSizeChangingEventArgs e = new ImageSizeChangingEventArgs(this.m_imageSize, value);
                    if (OnImageSizeChanging(e))
                    {
                        // Adjust image scaling mode.
                        ImageScalingSize = IconImageProvider.GetIconSize(value);

                        // Adjust image size as specified.
                        this.m_imageSize = value;
                        RefreshItemImages();
                        OnImageSizeChanged(new OldNewEventArgs<ImageSize>(e.CurrentValue, value));
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets whether a default icon is used to represent unsupported
        /// image sizes.
        /// </summary>
        public bool UseUnknownImageSizeIcon
        {
            get { return this.m_useUnknownIcon; }
            set
            {
                if (value != this.m_useUnknownIcon)
                {
                    this.m_useUnknownIcon = value;
                    OnUseUnknownImageSizeIconChanged(EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Gets a value indicating if image providers are being updated.
        /// </summary>
        public bool IsUpdatingImages
        {
            get { return this.m_updatingProviders > 0; }
            private set { this.m_updatingProviders += value ? +1 : -1; }
        }

        /// <summary>
        /// Gets or sets a value indicating if one or more image providers have been changed.
        /// </summary>
        protected bool HasImagesChanged
        {
            get { return this.m_changesMade; }
            set { this.m_changesMade = value; }
        }

        /// <summary>
        /// Gets the settings store.
        /// </summary>
        protected PersistentIconToolStripSettings Settings
        {
            get { return this.m_settings; }
        }

        #endregion

        #region Attributes

        private ImageProviderCollection m_imageProvider;
        private IImageProvider m_defaultProvider;
        private ImageSize m_imageSize = MultipleImageToolStrip.DefaultImageSize;
        private bool m_useUnknownIcon = false;
        private int m_updatingProviders = 0;
        private bool m_changesMade = false;

        private PersistentIconToolStripSettings m_settings;

        #endregion
    }

    public class PersistentIconToolStripSettings : ApplicationSettingsBase
    {
        #region Construction and destruction

        public PersistentIconToolStripSettings(String settingsKey)
        {
            this.SettingsKey = settingsKey;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets image size of toolstrip.
        /// </summary>
        [UserScopedSetting, DefaultSettingValue("Small")]
        public ImageSize ImageSize
        {
            get { return (ImageSize)this["ImageSize"]; }
            set { this["ImageSize"] = value; }
        }

        #endregion
    }

}

GeneralRe: ToolStripManager for MultipleImageToolStrip [modified] Pin
Guy..L4-Aug-09 17:25
Guy..L4-Aug-09 17:25 
GeneralToolStrip flicker Pin
Guy..L2-Aug-09 12:03
Guy..L2-Aug-09 12:03 
GeneralRe: ToolStrip flicker Pin
Lea Hayes2-Aug-09 13:27
Lea Hayes2-Aug-09 13:27 
GeneralRe: ToolStrip flicker Pin
Guy..L2-Aug-09 13:49
Guy..L2-Aug-09 13:49 
GeneralThank You Pin
iccb101325-Jul-09 19:56
iccb101325-Jul-09 19:56 
QuestionIcon 16x16 32 x 32 Pin
Cliffer26-Feb-09 4:45
Cliffer26-Feb-09 4:45 
AnswerRe: Icon 16x16 32 x 32 Pin
Lea Hayes26-Feb-09 10:32
Lea Hayes26-Feb-09 10:32 
Questioninsert gripper into toolstrip Pin
rixwan19-Nov-08 3:02
rixwan19-Nov-08 3:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.