SYSK 23: DropDownList with ToolTip that Automatically Shows Up as You Mouse-Over the Items in the Dropped Down List

Ever wished you had a freeware DropDownList control that, instead of having one hardcoded tool tip, changed the tool tip text as the user moves from item to item in the dropped down list?  Well, your wait is over.  I’m enclosing the code for such a control below. 

Warning:  all disclaimers apply!  Also, it’s intended to be a “starter” code; i.e. you could (and should) certainly add DataSource implementation to avoid using Add method in the loop…

You create and initialize the control same way you would the standard Windows Forms ComboBox.  To add items to the list, call
YourControlName.Add("item text", itemValue, "item tool tip");

Enjoy!

SourceCode:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace YourCompany.WinControls
{
public class DropDownListWithToolTip : ComboBox
{
private bool _droppedDown = false;
private System.Collections.Generic.List<string> _toolTips = new List<string>();
private int _prevDrawIndex = -1;
private ToolTip _tip = new ToolTip();

        public DropDownListWithToolTip()
: base()
{
this.DisplayMember = "Key";
this.ValueMember = "Value";

            this.DropDownStyle = ComboBoxStyle.DropDownList;
this.DropDown += new EventHandler(DropDownListWithToolTip_DropDown);
this.DropDownClosed += new EventHandler(DropDownListWithToolTip_DropDownClosed);

            base.DrawMode = DrawMode.OwnerDrawFixed;

            _tip.AutomaticDelay = 0;
_tip.AutoPopDelay = 10000;
_tip.InitialDelay = 10;
_tip.IsBalloon = true;
_tip.ReshowDelay = 10;
}

protected override void OnDrawItem(DrawItemEventArgs e)
{
object item;

            if (e.Index >= 0)
{
if (e.Index < Items.Count)
item = Items[e.Index];
else
item = this.Text;

                Rectangle bounds = e.Bounds;
int border = 1;
int height = Font.Height + 2 * border;

Rectangle textBounds = new Rectangle(
bounds.X + (border * 2),
bounds.Y,
bounds.Width - (border * 2),
bounds.Height);
if (RightToLeft == RightToLeft.Yes)
{
// For a RightToLeft checked list box, we want the text
// to be drawn at the left.
// So we override the X position.
textBounds.X = bounds.X;
}

                // Setup text font, color, and text
string text = "";
Color backColor = BackColor;
Color foreColor = ForeColor;
if (!Enabled)
{
foreColor = SystemColors.GrayText;
}
Font font = Font;

                object value = FilterItemOnProperty(item);

if (value != null)
{
text = value.ToString();
}

                if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
backColor = SystemColors.Highlight;
foreColor = SystemColors.HighlightText;
}

                // Draw the text
using (Brush b = new SolidBrush(backColor))
{
e.Graphics.FillRectangle(b, textBounds);
}

                Rectangle stringBounds = new Rectangle(
textBounds.X + 1,
textBounds.Y + border,
textBounds.Width - 1,
textBounds.Height - border * 2);

                using (StringFormat format = new StringFormat())
{
// Adjust string format for Rtl controls
if (RightToLeft == RightToLeft.Yes)
{
format.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
}

format.FormatFlags |= StringFormatFlags.NoWrap;

                    // Do actual drawing
using (SolidBrush brush = new SolidBrush(foreColor))
{
e.Graphics.DrawString(text, font, brush, stringBounds, format);
}
}

                // Draw the focus rect if required
if ((e.State & DrawItemState.Focus) == DrawItemState.Focus &&
(e.State & DrawItemState.NoFocusRect) != DrawItemState.NoFocusRect)
{
ControlPaint.DrawFocusRectangle(e.Graphics, textBounds, foreColor, backColor);
}
}

            if (this.DesignMode == false && e.Index != -1 && ((e.State & DrawItemState.Selected) == DrawItemState.Selected))
{
if (_droppedDown == true && _prevDrawIndex != e.Index)
{
_tip.Show(_toolTips[e.Index], this);
_prevDrawIndex = e.Index;
}
}
}

        void DropDownListWithToolTip_DropDownClosed(object sender, EventArgs e)
{
_droppedDown = false;

            _tip.Hide(this);
}

        void DropDownListWithToolTip_DropDown(object sender, EventArgs e)
{
_droppedDown = true;
}

        public void Add(string text, object value, string toolTip)
{
base.Items.Add(new KeyValuePair<string, object>(text, value));

            _toolTips.Add(toolTip);
}

        public new KeyValuePair<string, object> SelectedItem
{
get
{
KeyValuePair<string, object> result = new KeyValuePair<string,object>();

                if (this.SelectedIndex != -1)
result = (KeyValuePair<string, object>)base.SelectedItem;

                return result;
}
}

        public new string SelectedText
{
get
{
string result = "";

                if (this.SelectedIndex != -1)
result = SelectedItem.Key;

return result;
}
}

        public new object SelectedValue
{
get
{
object result = null;

                if (this.SelectedIndex != -1)
result = SelectedItem.Value;

                return result;
}
}

        public string ToolTip(int index)
{
string result = "";

            if (index >= 0 && index < _toolTips.Count)
result = _toolTips[index];

            return result;
}
}
}

DropDownListWithToolTip.zip