Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine the cell being clicked on in a TableLayoutPanel?

I have a TableLayoutPanel and I want to add a control to the cell that I click on.

The problem is that I can't determine the cell that I click on at run time.

How do I determine the cell being clicked on?

like image 633
Ayman Sharaf Avatar asked Mar 16 '13 12:03

Ayman Sharaf


3 Answers

You can use GetColumnWidths and GetRowHeights methods to calculate the cell row and column index:

Point? GetRowColIndex(TableLayoutPanel tlp, Point point)
{
    if (point.X > tlp.Width || point.Y > tlp.Height)
        return null;

    int w = tlp.Width;
    int h = tlp.Height;
    int[] widths = tlp.GetColumnWidths();

    int i;
    for (i = widths.Length - 1; i >= 0 && point.X < w; i--)
        w -= widths[i];
    int col = i + 1;

    int[] heights = tlp.GetRowHeights();
    for (i = heights.Length - 1; i >= 0 && point.Y < h; i--)
        h -= heights[i];

    int row = i + 1;

    return new Point(col, row);
}

Usage:

private void tableLayoutPanel1_Click(object sender, EventArgs e)
{
    var cellPos = GetRowColIndex(
        tableLayoutPanel1,
        tableLayoutPanel1.PointToClient(Cursor.Position));
}

But notice that the click event only is raised if the cell does not already contain a control.

like image 173
Mohammad Dehghan Avatar answered Nov 10 '22 16:11

Mohammad Dehghan


This worked for me:

public TableLayoutPanel tableLayoutPanel { get; set; }

private void Form_Load(object sender, EventArgs e)
{
    foreach (Panel space in this.tableLayoutPanel.Controls)
    {
        space.MouseClick += new MouseEventHandler(clickOnSpace);
    }
}

public void clickOnSpace(object sender, MouseEventArgs e)
{

    MessageBox.Show("Cell chosen: (" + 
                     tableLayoutPanel.GetRow((Panel)sender) + ", " + 
                     tableLayoutPanel.GetColumn((Panel)sender) + ")");
}

Note that my tableLayoutPanel is declared globally so that I can just use it without having to pass it to each function. Also, both the tableLayoutPanel and each Panel within it are created completely programatically elsewhere (my form [design] is completely blank).

like image 34
Nick Avatar answered Nov 10 '22 15:11

Nick


My answer is based on @Mohammad Dehghan's answer above but has a couple of advantages:

  • It now takes into account vertical scrolling
  • The columns are in the correct order (starts at i=0 instead of i=length), meaning columns of different widths or heights are processed in the correct order

Here is the updated version of the code:

public Point? GetIndex(TableLayoutPanel tlp, Point point)
{
    // Method adapted from: stackoverflow.com/a/15449969
    if (point.X > tlp.Width || point.Y > tlp.Height)
        return null;

    int w = 0, h = 0;
    int[] widths = tlp.GetColumnWidths(), heights = tlp.GetRowHeights();

    int i;
    for (i = 0; i < widths.Length && point.X > w; i++)
    {
        w += widths[i];
    }
    int col = i - 1;

    for (i = 0; i < heights.Length && point.Y + tlp.VerticalScroll.Value > h; i++)
    {
        h += heights[i];
    }
    int row = i - 1;

    return new Point(col, row);
}
like image 2
Peter Gordon Avatar answered Nov 10 '22 16:11

Peter Gordon