1

i have a problem. I have a tableLayoutPanel with 2 rows and 2 colums. First colum is empty and in the second colum is something. I know detect a cell which was clicked, but i don't know how can i fill this clicked cell with red collor. Some suggestions? Here is my code:

private void tableLayoutPanel1_MouseClick(object sender, MouseEventArgs e)
    {
        int row = 0;
        int verticalOffset = 0;
        foreach (int h in tableLayoutPanel1.GetRowHeights())
        {
            int column = 0;
            int horizontalOffset = 0;
            foreach (int w in tableLayoutPanel1.GetColumnWidths())
            {
                Rectangle rectangle = new Rectangle(horizontalOffset, verticalOffset, w, h);
                if (rectangle.Contains(e.Location))
                {
                    MessageBox.Show(String.Format("row {0}, column {1} was clicked", row, column));

                    return;
                }
                horizontalOffset += w;
                column++;
            }
            verticalOffset += h;
            row++;
        }
    }
rene
  • 41,474
  • 78
  • 114
  • 152
Miloss
  • 29
  • 4
  • yes, i am using winforms – Miloss Mar 03 '16 at 17:04
  • Here's a good start on painting a particular cell. It's triggered off the paint event though, so we will have to extend it to work with a cell click.. [Stack Overflow Thread](http://stackoverflow.com/questions/14877012/changing-cell-colours-of-a-tablelayoutpanel-by-variables-during-runtime) – Nate M. Mar 03 '16 at 17:14
  • [Here is another link](http://stackoverflow.com/questions/35404110/mouse-move-on-a-cell-of-my-tablelayoutpanel/35410059?s=3|2.0026#35410059) you may find useful – TaW Mar 03 '16 at 17:29

2 Answers2

1

Using a List<T> to keep track of the cells already clicked:

   List<Point> clickedCells = new List<Point>();

..you can add the one you found to the list:

    if (rectangle.Contains(e.Location))
    {
        // *
        Point cell = new Point(column, row);
        if (!clickedCells.Contains(cell)) clickedCells.Add(cell);
        // **
        tableLayoutPanel1.Invalidate();
        return;
    }

To turn the color off and back on when clicked again you can add an else clause here (**):

         else clickedCells.Remove(cell);

and if only ever one cell should be painted either use only one Point or simply clear the list here (*)

        clickedCells.Clear();

Invalidating the TLP will trigger the CellPaint event, where the list is processed:

private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
    if (clickedCells.Contains(new Point(e.Column,e.Row)))
        e.Graphics.FillRectangle(Brushes.Red, e.CellBounds);
}

Note the the Points I use are not the pixel locations but the cell coordinates!

TaW
  • 53,122
  • 8
  • 69
  • 111
1

So.. the following code will work, but I don't particularly like it.. specifically, I am guessing there is a more graceful method of triggering the paint event, and passing arguments to said event. There are posts based on the CellPaint event, but I don't know offhand how to trigger it. So..

public partial class Form1 : Form
{
    Rectangle clicked = new Rectangle();
    bool wasClick = false;
    public Form1()
    {
        InitializeComponent();
    }

    private void tableLayoutPanel1_MouseClick(object sender, MouseEventArgs e)
    {
        int row = 0;
        int verticalOffset = 0;
        int clickx = e.X;
        int clicky = e.Y;
        foreach (int h in tableLayoutPanel1.GetRowHeights())
        {
            int column = 0;
            int horizontalOffset = 0;
            foreach (int w in tableLayoutPanel1.GetColumnWidths())
            {
                Rectangle rectangle = new Rectangle(horizontalOffset, verticalOffset, w, h);
                if (rectangle.Contains(e.Location))
                {
                    MessageBox.Show(String.Format("row {0}, column {1} was clicked", row, column));
                    clicked = rectangle;
                    wasClick = true;
                    tableLayoutPanel1.Invalidate(rectangle);
                    return;
                }
                horizontalOffset += w;
                column++;
            }
            verticalOffset += h;
            row++;
        }
    }

    private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
    {
        if (wasClick)
        {
            Graphics g = e.Graphics;
            Rectangle r = clicked;
            g.FillRectangle(Brushes.Red, r);
            wasClick = false;
        }

    }
}

Caveats are that when you click a red cell, it stays red, so you would need to add detection in regards to what cells are red / not red. Again, someone else may very well have a more elegant solution than this, so keep an eye out.

Nate M.
  • 822
  • 6
  • 14
  • I was going to delete, but went ahead and left this up. I would definitely go with the other solution though. I was unable to get the CellPaint event to trigger off an Invalidate call for some reason, probably because I was passing the rectangle into it if I had to guess. – Nate M. Mar 03 '16 at 18:02