Search code examples
c#winformstooltiptablelayoutpanel

Show text when hovering over cell in TableLayoutPanel - C#


I've got a programatically created TableLayoutPanel, with each of its cells containing a Panel. Each Panel has a custom Label. (The Labels' Enabled property is set to false; not sure if that makes a difference.) I'd like to display the text of the Label whenever the user hovers over it with the mouse.

From what I've read, a ToolTip is a good way to do this, but I haven't been able to get it to work.

The TableLayoutPanel is name "tlp" for short and is a member of the form for easier access (likewise with the ToolTip, which is name "toolTip").

For now I'm just trying to get any kind of text. I'll replace my string here with the Label's text once I can get it to work.

private void hoverOverSpace(object sender, EventArgs e)
{
    int row = tlp.GetRow((Panel)sender);
    int col = tlp.GetColumn((Panel)sender);

    toolTip.Show("Does this work?", tlp.GetControlFromPosition(col, row).Controls[0]);
    //toolTip.Show("Does this work?", tlp.GetControlFromPosition(col, row));
}

Neither of my attempts to display the ToolTip have been successful. Am I doing something wrong/is there a better method for doing what I'm trying to accomplish?

EDIT: I've attempted to add the toolTip to each Panel but still nothing is happening

// Add Panels to TableLayoutPanel
for (int i = 0; i < rows; i++)
{
    for (int j = 0; j < cols; j++)
    {
        // Create new Panel
        Panel space = new Panel()
       {
            Size = new Size(45, 45),
            Dock = DockStyle.Fill,
            Margin = new Padding(0)
        };

        space.MouseClick += new MouseEventHandler(clickOnSpace);

        CustomLabel info = new CustomLabel(false, 0, Color.White);      // Create new CustomLabel
        space.Controls.Add(info);   // Add CustomLabel to Panel
        tlp.Controls.Add(space, j, i);      // Add Panel to TableLayoutPanel

        toolTip = new ToolTip();
        toolTip.SetToolTip(space, info.Text);
    }
}

Solution

  • This answer is based on code presented in the answer to: tablelayoutPanel get cell location from mouse over, by: Aland Li Microsoft CSS.

        #region GetPosition
        // Modified from answer to: tablelayoutPanel get cell location from mouse over
        // By:  Aland Li Microsoft CSS
        // https://social.msdn.microsoft.com/Forums/windows/en-US/9bb6f42e-046d-42a0-8c83-febb1dcf98a7/tablelayoutpanel-get-cell-location-from-mouse-over?forum=winforms
    
    //The method to get the position of the cell under the mouse.
    private TableLayoutPanelCellPosition GetCellPosition(TableLayoutPanel panel, Point p)
    {
    
        //Cell position
        TableLayoutPanelCellPosition pos = new TableLayoutPanelCellPosition(0, 0);
        //Panel size.
        Size size = panel.Size;
        //average cell size.
        SizeF cellAutoSize = new SizeF(size.Width / panel.ColumnCount, size.Height / panel.RowCount);
    
        //Get the cell row.
        //y coordinate
        float y = 0;
        for (int i = 0; i < panel.RowCount; i++)
        {
            //Calculate the summary of the row heights.
            SizeType type = panel.RowStyles[i].SizeType;
            float height = panel.RowStyles[i].Height;
            switch (type)
            {
                case SizeType.Absolute:
                    y += height;
                    break;
                case SizeType.Percent:
                    y += height / 100 * size.Height;
                    break;
                case SizeType.AutoSize:
                    y += cellAutoSize.Height;
                    break;
            }
            //Check the mouse position to decide if the cell is in current row.
            if ((int)y > p.Y)
            {
                pos.Row = i;
                break;
            }
        }
    
        //Get the cell column.
        //x coordinate
        float x = 0;
        for (int i = 0; i < panel.ColumnCount; i++)
        {
            //Calculate the summary of the row widths.
            SizeType type = panel.ColumnStyles[i].SizeType;
            float width = panel.ColumnStyles[i].Width;
            switch (type)
            {
                case SizeType.Absolute:
                    x += width;
                    break;
                case SizeType.Percent:
                    x += width / 100 * size.Width;
                    break;
                case SizeType.AutoSize:
                    x += cellAutoSize.Width;
                    break;
            }
            //Check the mouse position to decide if the cell is in current column.
            if ((int)x > p.X)
            {
                pos.Column = i;
                break;
            }
        }
    
        //return the mouse position.
        return pos;
    }
    #endregion
    

    It uses the TableLayoutPanelCellPosition computed by the referenced code to obtain the Control at that position (if any) and display its Text property as a ToolTip on the TableLayoutPanel.MouseHover event.

    private void tableLayoutPanel1_MouseHover(object sender, EventArgs e)
    {
        Point pt = tableLayoutPanel1.PointToClient(Control.MousePosition);
        TableLayoutPanelCellPosition pos = GetCellPosition(tableLayoutPanel1, pt);
        Control c = tableLayoutPanel1.GetControlFromPosition(pos.Column, pos.Row);
        if (c != null)
        {
            toolTip1.Show(c.Text, tableLayoutPanel1, pt, 500);
        }
    }
    

    Edit:

    I missed that the TLP is populated with controls with their Dock property set to DockStyle.Fill`. Such controls place placed in the TLP will receive the Mouse Events instead of the TLP. So as fix, add this method.

    private void showtip(object sender, EventArgs e)
    {
        Point pt = tableLayoutPanel1.PointToClient(Control.MousePosition);
        TableLayoutPanelCellPosition pos = GetCellPosition(tableLayoutPanel1, pt);
        Control c = tableLayoutPanel1.GetControlFromPosition(pos.Column, pos.Row);
        if (c != null && c.Controls.Count > 0)
        {
            toolTip1.Show(c.Controls[0].Text, tableLayoutPanel1, pt, 500);
        }
    }
    

    Then wireup the each Panel and Label grouping like this:

    this.panel4.MouseHover += new System.EventHandler(this.showtip);
    this.label4.MouseHover += new System.EventHandler(this.showtip);