Tooltip for each items in a combo box

2019-01-17 04:14发布

I just want to add a tooltip for each item in a combo box. i am using c#.net windows application.

There is no option like

combobox.items[1].tooltip();

Is there any way to add tooltip it ?

9条回答
祖国的老花朵
2楼-- · 2019-01-17 04:55

My solution:

public class ToolTipComboBox: ComboBox
{
    #region Fields

    private ToolTip toolTip;
    private bool _tooltipVisible;
    private bool _dropDownOpen;
    #endregion

    #region Types

    [StructLayout(LayoutKind.Sequential)]
    // ReSharper disable once InconsistentNaming
    public struct COMBOBOXINFO
    {
        public Int32 cbSize;
        public RECT rcItem;
        public RECT rcButton;
        public ComboBoxButtonState buttonState;
        public IntPtr hwndCombo;
        public IntPtr hwndEdit;
        public IntPtr hwndList;
    }

    public enum ComboBoxButtonState
    {
        // ReSharper disable once UnusedMember.Global
        StateSystemNone = 0,
        // ReSharper disable once UnusedMember.Global
        StateSystemInvisible = 0x00008000,
        // ReSharper disable once UnusedMember.Global
        StateSystemPressed = 0x00000008
    }

    [DllImport("user32.dll")]
    public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);
    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);

    #endregion

    #region Properties

    private IntPtr HwndCombo
    {
        get
        {
            COMBOBOXINFO pcbi = new COMBOBOXINFO();
            pcbi.cbSize = Marshal.SizeOf(pcbi);
            GetComboBoxInfo(Handle, ref pcbi);
            return pcbi.hwndCombo;
        }
    }

    private IntPtr HwndDropDown
    {
        get
        {
            COMBOBOXINFO pcbi = new COMBOBOXINFO();
            pcbi.cbSize = Marshal.SizeOf(pcbi);
            GetComboBoxInfo(Handle, ref pcbi);
            return pcbi.hwndList;
        }
    }

    [Browsable(false)]
    public new DrawMode DrawMode
    {
        get { return base.DrawMode; }
        set { base.DrawMode = value; }
    }

    #endregion

    #region ctor

    public ToolTipComboBox()
    {
        toolTip = new ToolTip
        {
            UseAnimation = false,
            UseFading = false
        };

        base.DrawMode = DrawMode.OwnerDrawFixed;
        DrawItem += OnDrawItem;
        DropDownClosed += OnDropDownClosed;
        DropDown += OnDropDown;
        MouseLeave += OnMouseLeave;
    }

    #endregion

    #region Methods

    private void OnDropDown(object sender, EventArgs e)
    {
        _dropDownOpen = true;
    }

    private void OnMouseLeave(object sender, EventArgs e)
    {
        ResetToolTip();
    }

    private void ShowToolTip(string text, int x, int y)
    {
        toolTip.Show(text, this, x, y);
        _tooltipVisible = true;
    }

    private void OnDrawItem(object sender, DrawItemEventArgs e)
    {
        ComboBox cbo = sender as ComboBox;
        if (e.Index == -1) return;

        // ReSharper disable once PossibleNullReferenceException
        string text = cbo.GetItemText(cbo.Items[e.Index]);
        e.DrawBackground();

        if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
        {
            TextRenderer.DrawText(e.Graphics, text, e.Font, e.Bounds.Location, SystemColors.Window);

            if (_dropDownOpen)
            {
                Size szText = TextRenderer.MeasureText(text, cbo.Font);
                if (szText.Width > cbo.Width - SystemInformation.VerticalScrollBarWidth && !_tooltipVisible)
                {
                    RECT rcDropDown;
                    GetWindowRect(HwndDropDown, out rcDropDown);

                    RECT rcCombo;
                    GetWindowRect(HwndCombo, out rcCombo);

                    if (rcCombo.Top > rcDropDown.Top)
                    {
                        ShowToolTip(text, e.Bounds.X, e.Bounds.Y - rcDropDown.Rect.Height - cbo.ItemHeight - 5);
                    }
                    else
                    {
                        ShowToolTip(text, e.Bounds.X, e.Bounds.Y + cbo.ItemHeight - cbo.ItemHeight);
                    }
                }
            }
        }
        else
        {
            ResetToolTip();
            TextRenderer.DrawText(e.Graphics, text, e.Font, e.Bounds.Location, cbo.ForeColor);
        }

        e.DrawFocusRectangle();
    }

    private void OnDropDownClosed(object sender, EventArgs e)
    {
        _dropDownOpen = false;
        ResetToolTip();
    }

    private void ResetToolTip()
    {
        if (_tooltipVisible)
        {
            // ReSharper disable once AssignNullToNotNullAttribute
            toolTip.SetToolTip(this, null);
            _tooltipVisible = false;
        }
    }

    #endregion
}
查看更多
兄弟一词,经得起流年.
3楼-- · 2019-01-17 04:55

Below is c# code to show tool tip on item of combo box whose width is greater than width of combo box control. Tool tip will be shown once user hover on such combo box:

 this.combo_box1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
 this.combo_box1.DrawMode = DrawMode.OwnerDrawFixed;
 this.combo_box1.DrawItem += new DrawItemEventHandler(combo_box1_DrawItem);
 this.combo_box1.DropDownClosed += new EventHandler(combo_box1_DropDownClosed);
 this.combo_box1.MouseLeave += new EventHandler(combo_box1_Leave);

 void combo_box1_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0) { return; }
            string text = combo_box1.GetItemText(combo_box1.Items[e.Index]);
            e.DrawBackground();
            using (SolidBrush br = new SolidBrush(e.ForeColor))
            {
                e.Graphics.DrawString(text, e.Font, br, e.Bounds);
            }

            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected && combo_box1.DroppedDown)
            {
                if (TextRenderer.MeasureText(text, combo_box1.Font).Width > combo_box1.Width)
                {
                    toolTip1.Show(text, combo_box1, e.Bounds.Right, e.Bounds.Bottom);
                }
                else
                {
                    toolTip1.Hide(combo_box1);
                }
            }
            e.DrawFocusRectangle();
        }

        private void combo_box1_DropDownClosed(object sender, EventArgs e)
        {
            toolTip1.Hide(combo_box1);
        }

        private void combo_box1_Leave(object sender, EventArgs e)
        {
            toolTip1.Hide(combo_box1);
        }

        private void combo_box1_MouseHover(object sender, EventArgs e)
        {
            if (!combo_box1.DroppedDown && TextRenderer.MeasureText(combo_box1.SelectedItem.ToString(), combo_box1.Font).Width > combo_box1.Width)
            {
                toolTip1.Show(combo_box1.SelectedItem.ToString(), combo_box1, combo_box1.Location.X, combo_box1.Location.Y);
            }
        }

Here is the link for more details - http://newapputil.blogspot.in/2016/12/display-tooltip-for-combo-box-item-cnet.html

查看更多
我命由我不由天
4楼-- · 2019-01-17 04:58

There are actually a couple reasonable solutions to this question. An MSDN forum has a ComboBox Item highlight event post that contains two possibilities, one from nobugz and one from agrobler. Each of them provides code to subclass a ComboBox that is supposed to handle tool tips on individual items in the ComboBox's dropdown. Agrobler's solution looks more polished, in that he/she even includes some nice illustrations, but unfortunately it is not clear (at least to me) how to populate the crucial ToolTipMember property of the control.

Both of these solutions appear to allow arbitrary tooltips assigned to individual items. A more specific, but more common case, is where you simply want the tooltip to mirror the text of the item, when you know you may have items that are too long to fit the width of the ComboBox. In my own case, I have an instance of a ComboBox that holds complete file paths so it is easy to see where the contents could exceed the ComboBox's width.

Zhi-Xin Ye, in the MSDN forum post Windows Dropdown question, provides a solution that addresses this more specific problem and is much simpler. I reproduce the code here in its entirety. (Note that this code presupposes you have created a Form called Form1 and hooked up the load handler shown, and also added a ComboBox named comboBox1 and a tool tip handler toolTip1.)

private void Form1_Load(object sender, EventArgs e)
{
    this.comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
    this.comboBox1.DrawItem += new DrawItemEventHandler(comboBox1_DrawItem);
}

void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    string text = this.comboBox1.GetItemText(comboBox1.Items[e.Index]);
    e.DrawBackground();
    using (SolidBrush br = new SolidBrush(e.ForeColor))
    { e.Graphics.DrawString(text, e.Font, br, e.Bounds); }

    if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
    { this.toolTip1.Show(text, comboBox1, e.Bounds.Right, e.Bounds.Bottom); }
    else { this.toolTip1.Hide(comboBox1); }
    e.DrawFocusRectangle();
}

While simple and concise, this code does suffer from one defect (as is pointed out in a reply on the above MSDN thread): as you move the mouse (without clicking) from one dropdown item to the next, only every other one shows a persistent tooltip! The fix is only hinted at by yet another entry on that thread, so I thought it would be useful to provide the full, corrected code here:

private void Form1_Load(object sender, EventArgs e)
{
    comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
    comboBox1.DrawItem += comboBox1_DrawItem;
    comboBox1.DropDownClosed += comboBox1_DropDownClosed;
}

private void comboBox1_DropDownClosed(object sender, EventArgs e)
{
    toolTip1.Hide(comboBox1);
}

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    if (e.Index < 0) { return; } // added this line thanks to Andrew's comment
    string text = comboBox1.GetItemText(comboBox1.Items[e.Index]);
    e.DrawBackground();
    using (SolidBrush br = new SolidBrush(e.ForeColor))
    { e.Graphics.DrawString(text, e.Font, br, e.Bounds); }
    if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
    { toolTip1.Show(text, comboBox1, e.Bounds.Right, e.Bounds.Bottom); }
    e.DrawFocusRectangle();
}

Besides removing a few redundant portions of code (e.g. the "this" qualifier) the primary difference is moving the toolTip1.Hide call into the DropDownClosed event handler. Taking it out of the DrawItem handler eliminates the defect mentioned above; but then you need to close it when the drop down closes, otherwise the last displayed tooltip will remain onscreen.

2012.07.31 Addendum

Just wanted to mention that I have since created a composite ComboBox that incorporates this tooltip capability so if you use my library you have no code to write at all. Just drag a ComboBoxWithTooltip onto the Visual Studio designer and you are done. Drill down to ComboBoxWithTooltip on my API page or download my open-source C# library to get started. (Note that the patch for the bug Andrew caught will be in release 1.1.04, due out soon.)

查看更多
欢心
5楼-- · 2019-01-17 04:58

If you are loading from a datasource, get the data into datatable and set the same to combobox. My datatable has three columns ID,NAME,DEFINITION. Below is my code :

InputQuery = "select * from ds_static_frequency";
        TempTable = UseFunc.GetData(InputQuery);

        cmbxUpdateFrequency.DataSource = TempTable;
        cmbxUpdateFrequency.DataTextField = "NAME";
        cmbxUpdateFrequency.DataValueField = "ID";
        cmbxUpdateFrequency.DataBind();

        foreach (DataRow dr in TempTable.Rows)
        {                
            int CurrentRow = Convert.ToInt32(dr["ID"].ToString());
            cmbxUpdateFrequency.Items[CurrentRow - 1].ToolTip = dr["Definition"].ToString();               
        }    
查看更多
Explosion°爆炸
6楼-- · 2019-01-17 05:06

You will need to create your own UserControl.

Having a ToolTip for each item in a combobox is an unusual requirement; perhaps you could use a 2 column combobox instead?

查看更多
手持菜刀,她持情操
7楼-- · 2019-01-17 05:14
private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
    ToolTip toolTip1 = new ToolTip();
    toolTip1.AutoPopDelay = 0;
    toolTip1.InitialDelay = 0;
    toolTip1.ReshowDelay = 0;
    toolTip1.ShowAlways = true;
    toolTip1.SetToolTip(this.comboBox1, comboBox1.Items[comboBox1.SelectedIndex].ToString()) ;
}
查看更多
登录 后发表回答