C# change table row color when mouse hover

前端 未结 1 1197
耶瑟儿~
耶瑟儿~ 2021-01-26 19:06

I have a table layout panel in my winform, and I want to add an effect to the rows whenever the mouse is hover a row.

I think I need to make a Mouse_over action over the

相关标签:
1条回答
  • 2021-01-26 19:56

    Here is what you can do:

    As there actually are no Cells in a TableLayouPanel all you can do is

    • detect where th mouse is
    • paint the TLP in the CellPaint event.

    Since your TLP most likely will contain controls they also need to detect whether the mouse is on them..

    Here is an example:

    First a class level variable to store the current row:

     int tlpRow = -1;
    

    Next a CellPaint event that can color a row:

    private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
    {
        if (e.Row == tlpRow) 
            using (SolidBrush brush = new SolidBrush(Color.FromArgb(123, 234, 45, 67)))
                e.Graphics.FillRectangle(brush, e.CellBounds);
    }
    

    Next we need detection routines. First one for the TLP:

    bool testTLP(TableLayoutPanel tlp,  Point pt)
    {
        var rs = tableLayoutPanel1.RowStyles;
        var rh = 0f;
        for (int i = 0; i < rs.Count; i++)
        {
            if (pt.Y > rh && pt.Y <= rh + rs[i].Height )
            {
                if (tlpRow != i)
                {
                    tlpRow = i;
                    tableLayoutPanel1.Invalidate();
                    return true;
                }
            }
            rh += rs[i].Height;
        }
        tlpRow = -1;
        return false;
    }
    

    It loops over all rows and adds up the heights until it has found the right one. Then it stores the row index and triggers the CellPaint event.

    We can use the same routine for the controls:

    bool testTLP(TableLayoutPanel tlp)
    {
        Point point = tlp.PointToClient(Control.MousePosition);
        return testTLP(tlp, point);
    }
    

    We simply calculate the mouse position relative to the TLP and call the same test.

    Note that this test only for 1 level of nesting. If you have deeper nested control you may need to expand on the test somewhat..!

    We also need to call the tests; the TLP test can be called in the MouseMove:

    private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
    {
        testTLP(tableLayoutPanel1, e.Location);
    }
    

    The controls get hooked up all together maybe like this:

    void hookUpControls(TableLayoutPanel tlp)
    {
        foreach (Control ctl in tlp.Controls)
        {
            ctl.MouseMove += (s, e) => { testTLP(tlp); };
        }
    }
    

    I use the MouseMove event as the MouseEnter sometimes slipped through in my tests..

    If you add controls later you need to hook the up as well. Make sure not to hook one up multiple times!

    Most likely you want to reset the coloring when leaving the TLP:

    private void tableLayoutPanel1_MouseLeave(object sender, EventArgs e)
    {
        Point tplPoint = tableLayoutPanel1.PointToClient(Control.MousePosition);
        if (!tableLayoutPanel1.ClientRectangle.Contains(tplPoint))  tlpRow = -1;
        tableLayoutPanel1.Invalidate();
    }
    

    Result:

    Note: when you add Controls dynamically you need to hook the up as well. Here is an example:

    Label lbl = new Label() { Text = "newbie" };
    lbl.MouseMove += (ss, ee) => { testTLP(tlp, lbl); }; 
    tlp.Controls.Add(lbl, cellIDX, rowIDX);
    

    If you find the coloring flickers you can simply add a DoubleBuffered subclass:

    class DoubleBufferedTLP : TableLayoutPanel
    {
        public DoubleBufferedTLP()
        {
            DoubleBuffered = true;
        }
    }
    

    To do so you need to add to the project, compile, check to see it appears in the ToolBox. If you want to you can simply change the two sponts in the form_designer class..

    0 讨论(0)
提交回复
热议问题