C# Showing MetroFramework ToolTip on ToolStripItem

404 Views Asked by At

I`m trying to play around with MetroFramework for C# and show a nice ToolTip when a ToolStripItem is hovered, instead of the basic/regular tooltip offered.

However, I`m unable to show it "per item" because ToolStripItem has only "Owner" control property and it will show it across all items in the toolbar.

Example:

private void toolStripButton1_MouseHover(object sender, EventArgs e)
{
   var tooltip = new MetroFramework.Components.MetroToolTip();

   ToolStripItem tsi = (ToolStripItem)sender;

   tooltip.SetToolTip(tsi.Owner, "testing the tooltips");
}

Does anyone have a solution regarding this ? Or is it just not possible without editing the MetroFramework library ?

Your input is much appreciated.

1

There are 1 best solutions below

0
dr.null On BEST ANSWER

Based on the source code of this component, its derived from the System.Windows.Forms.ToolTip thus we can handle it the same way to fulfill this requirement.

First of all, you just need one instance of the MetroToolTip in a Form. Either use the designer to drop an instance, or create one in code and dispose of it when you close the Form.

To make it works per item:

  • At design time, set the ToolTipText properties of the ToolStrip / MenuStrip / ContextMenuStrip / StatusStrip items.

  • In the constructor or Form.Load event, get the ToolStripItem objects using a recursive method to subscribe to the Click, MouseHover, and MouseLeave events. Also, the ToolStripDropDownItem.DropDownOpening events are needed. We'll handle them to show and hide the tooltips.

Example

private readonly MetroToolTip mTt;

// ctor
public SomeForm()
{
    InitializeComponent();

    mTt = new MetroToolTip();

    // 3 strips just for demonstration.
    menuStrip1.ShowItemToolTips = false;
    toolStrip1.ShowItemToolTips = false;
    contextMenuStrip1.ShowItemToolTips = false;

    foreach (var item in GetAllToolStripItems(menuStrip1.Items)
        .Concat(GetAllToolStripItems(toolStrip1.Items))
        .Concat(GetAllToolStripItems(contextMenuStrip1.Items)))
    {
        if (!string.IsNullOrEmpty(item.ToolTipText))
        {
            item.AutoToolTip = false;
            item.Click += OnToolStripItemClick;
            item.MouseHover += OnToolStripItemMouseHover;
            item.MouseLeave += OnToolStripItemMouseLeave;
            if (item is ToolStripDropDownItem tsddi && tsddi.HasDropDown)
                tsddi.DropDownOpening += OnDropDownOpening;
        }
    }
}

// Clean up..
private void SomeForm_FormClosed(object sender, FormClosedEventArgs e) =>
    mTt.Dispose();

// Show the tooltip of the current item at a proper point.
private void OnToolStripItemMouseHover(object sender, EventArgs e)
{
    var s = sender as ToolStripItem;
    var p = Point.Add(Cursor.Position, new Size(0, Cursor.Size.Height));

    mTt.Show(s.ToolTipText, s.Owner, s.Owner.PointToClient(p));
}

// Hide the tooltip when the mouse pointer leaves the bounds of the current item.
private void OnToolStripItemMouseLeave(object sender, EventArgs e) =>
    mTt.Hide((sender as ToolStripItem).Owner);

// Hide the tooltip (if any) when a dropdown is about to open
// Otherwise it'll remain behind the dropdown window until the
// internal timer ticks.
private void OnDropDownOpening(object sender, EventArgs e) =>
    mTt.Hide((sender as ToolStripItem).Owner);

// For the ToolStrip control. To hide the tooltip right after clicking an item.
private void OnToolStripItemClick(object sender, EventArgs e) =>
    mTt.Hide((sender as ToolStripItem).Owner);

// A recursive method to get all the TSIs of any strip.
private static IEnumerable<ToolStripItem> GetAllToolStripItems(ToolStripItemCollection tsic)
{
    foreach (var tsi in tsic.Cast<ToolStripItem>())
    {
        yield return tsi;

        if (tsi is ToolStripDropDownItem tsddi && tsddi.HasDropDown)
            foreach (var ddi in GetAllToolStripItems(tsddi.DropDownItems))
                yield return ddi;
    }
}