6

我正在开发一个 WinForm 项目并“尝试”创建一个 TableLayoutPanel,用户可以在运行时调整它的大小,就像 SplitContainer 的行为一样。我发现了一些部分执行此操作的代码,但它不完整。有人可以帮我吗?

提前致谢,-DA

这是我目前拥有的代码,来自我在 CodeProject 上找到的一个线程。我自己做的唯一不同的事情是创建一个继承自 TableLayoutPanel 的 customTableLayoutPanel。

public partial class Form1 : Form
{
    bool resizing = false;
    TableLayoutRowStyleCollection rowStyles;
    TableLayoutColumnStyleCollection columnStyles;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        rowStyles = tableLayoutPanel1.RowStyles;
        columnStyles = tableLayoutPanel1.ColumnStyles;
    }

    private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            resizing = true;
        }
    }

    private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (resizing)
        {
            columnStyles[0].SizeType = SizeType.Absolute;
            rowStyles[0].SizeType = SizeType.Absolute;
            rowStyles[0].Height = e.Y;
            columnStyles[0].Width = e.X;
        }
    }

    private void tableLayoutPanel1_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            resizing = false;
        }
    }
}
4

4 回答 4

5

将 Column SizeType 和 Row SizeType 属性设置为 Absolute 和 CellBorderStyle 作为你想要的,而不是在代码编写如下之后没有

public partial class Form1 : Form
{
    bool resizing = false;
    TableLayoutRowStyleCollection rowStyles;
    TableLayoutColumnStyleCollection columnStyles;
    int colindex = -1;
    int rowindex = -1;
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        rowStyles = tableLayoutPanel1.RowStyles;
        columnStyles = tableLayoutPanel1.ColumnStyles;
    }
    private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            rowStyles = tableLayoutPanel1.RowStyles;
            columnStyles = tableLayoutPanel1.ColumnStyles;
            resizing = true;
        }
    }

    private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
    {
        if (!resizing)
        {
            float width = 0;
            float height = 0;
            //for rows
            for (int i = 0; i < rowStyles.Count; i++)
            {
                height += rowStyles[i].Height;
                if (e.Y > height - 3 && e.Y < height + 3)
                {
                    rowindex = i;
                    tableLayoutPanel1.Cursor = Cursors.HSplit;
                    break;
                }
                else
                {
                    rowindex = -1;
                    tableLayoutPanel1.Cursor = Cursors.Default;
                }
            }
            //for columns
            for (int i = 0; i < columnStyles.Count; i++)
            {
                width += columnStyles[i].Width;
                if (e.X > width - 3 && e.X < width + 3)
                {
                    colindex = i;
                    if (rowindex > -1)
                        tableLayoutPanel1.Cursor = Cursors.Cross;
                    else
                        tableLayoutPanel1.Cursor = Cursors.VSplit;
                    break;
                }
                else
                {
                    colindex = -1;
                    if (rowindex == -1)
                        tableLayoutPanel1.Cursor = Cursors.Default;
                }
            }
        }
        if (resizing && (colindex>-1 || rowindex > -1))
        {
            float width = e.X;
            float height = e.Y;
            if (colindex > -1)
            {
                for (int i = 0; i < colindex; i++)
                {
                    width -= columnStyles[i].Width;
                }
                columnStyles[colindex].SizeType = SizeType.Absolute;
                columnStyles[colindex].Width = width;
            }
            if (rowindex > -1)
            {
                for (int i = 0; i < rowindex; i++)
                {
                    height -= rowStyles[i].Height;
                }

                rowStyles[rowindex].SizeType = SizeType.Absolute;
                rowStyles[rowindex].Height = height;
            }
        }
    }

    private void tableLayoutPanel1_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            resizing = false;
            tableLayoutPanel1.Cursor = Cursors.Default;
        }
    }
}
于 2014-05-09T06:28:51.857 回答
2

我改进了 MD 答案的代码。
我没有听 TableLayoutPanel 的 MouseEvents,而是听那些 Controls 的。这是可调整大小的的代码:

    TableLayoutPanel tlp;
    bool resizing;
    int rowindex = -1;
    int nextHeight;

    private void control_MouseDown(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            resizing = true;
        }
    }

    private void control_MouseMove(object sender, MouseEventArgs e)
    {
        Control c = (Control)sender;
        if (!resizing)
        {
            rowindex = -1;
            tlp.Cursor = Cursors.Default;

            if (e.Y <= 3)
            {
                rowindex = tlp.GetPositionFromControl(c).Row - 1;
                if (rowindex >= 0)
                    tlp.Cursor = Cursors.HSplit;
            }
            if (c.Height - e.Y <= 3)
            {
                rowindex = tlp.GetPositionFromControl(c).Row;
                if (rowindex < tlp.RowStyles.Count)
                    tlp.Cursor = Cursors.HSplit;
            }
        }
        if (resizing && rowindex > -1)
        {
            nextHeight = e.Y;
        }
    }

    private void control_MouseUp(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            if (nextHeight > 0)
                tlp.RowStyles[rowindex].Height = nextHeight;
            resizing = false;
        }
    }
于 2016-04-05T12:42:29.460 回答
1

我的答案是使用鼠标仅调整 tablelayoutpanel 的列的大小,但可以轻松更新以对行执行相同的操作。当然,我宁愿对行使用拆分面板,但仍然如此。在代码中,我提供了 4 列,但将其扩展到或多或少很容易。cursurToDefault 事件将被添加到 tablelayoutpanel 内容器控件的 mousemove-event 中。

 private int beamMoving;
 private void tableLayoutPanel1_MouseMove(object sender, MouseEventArgs e)
    {
        this.Cursor = Cursors.VSplit;
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            int beam0 = (int)tableLayoutPanel1.ColumnStyles[0].Width;
            int beam1 = (int)tableLayoutPanel1.ColumnStyles[0].Width + (int)tableLayoutPanel1.ColumnStyles[1].Width;
            int beam2 = (int)tableLayoutPanel1.ColumnStyles[0].Width + (int)tableLayoutPanel1.ColumnStyles[1].Width + (int)tableLayoutPanel1.ColumnStyles[2].Width;

            switch (beamMoving)
            {
                case 0:
                    {
                        if (e.X > 0)
                        {
                            tableLayoutPanel1.ColumnStyles[0].Width = e.X;
                        }
                        break;
                    }
                case 1:
                    {
                        if (e.X - beam0 > 0)
                        {
                            tableLayoutPanel1.ColumnStyles[1].Width = e.X - beam0;
                        }
                        break;
                    }
                case 2:
                    {
                        if (e.X - beam1 > 0)
                        {
                            tableLayoutPanel1.ColumnStyles[2].Width = e.X - beam1;
                        }
                        break;
                    }
            }
        }
    }
    private void cursorToDefault(object sender, MouseEventArgs e)
    {
        this.Cursor = Cursors.Default;
    }

    private void tableLayoutPanel1_MouseDown(object sender, MouseEventArgs e)
    {
        int beam0 = (int)tableLayoutPanel1.ColumnStyles[0].Width;
        int beam1 = (int)tableLayoutPanel1.ColumnStyles[0].Width + (int)tableLayoutPanel1.ColumnStyles[1].Width;
        int beam2 = (int)tableLayoutPanel1.ColumnStyles[0].Width + (int)tableLayoutPanel1.ColumnStyles[1].Width + (int)tableLayoutPanel1.ColumnStyles[2].Width;
        if (e.X + 20 > beam0 && e.X - 20 < beam1)
        {
            beamMoving = 0;
        }
        if (e.X + 20 > beam1 && e.X - 20 < beam2)
        {
            beamMoving = 1;
        }
        if (e.X + 20 > beam2 && e.X - 20 < tableLayoutPanel1.Width)
        {
            beamMoving = 2;
        }                    
    }
于 2015-07-02T09:12:38.967 回答
0

根据原代码写了一个Module

这对多个 tablelayoutpanel 使用字典和 4 个事件处理程序来重新调整其行和列的大小。

那里有一些代码可以捕捉屏幕上的移动物体,但不多。

阅读代码中的注释以获取更多信息

Module modResizeableTableLayoutPanel

Private otlpdic As Dictionary(Of String, Integer()) = Nothing


 ''' <summary>
 ''' Adds the needed handlers for resizing the rows and columns of multiple
 ''' tablelayoutpanel uses the tag property
 ''' also requires primary controls in the cells to have a margin of 6... this is
 ''' a hack to detect when the mouse
 ''' is no longer over a divider and not over a control in the cell
 ''' All rows and columns require absolute positioning
 ''' </summary>
 ''' <param name="otlp">tablelayoutpanel</param>
 ''' <remarks></remarks>
Public Sub InitializeResizeableTableLayOutPanel(ByRef otlp As TableLayoutPanel)
    'create has if needed
    Call CreateTableLayoutPanelHash()

    'creat hash entry for TableLayoutPanel
    Call CreateHashEntryForTableLayoutPanel(otlp)

    'sets the border style to something that helps the mouse cursor detect.
    otlp.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single

    'hack to set margins on sub controls
    For Each con In otlp.Controls
        Select Case con.GetType
            Case GetType(FlowLayoutPanel)
                Dim obj As FlowLayoutPanel = DirectCast(con, FlowLayoutPanel)
                obj.Margin = New Padding(6)
            Case GetType(DataGridView)
                Dim obj As DataGridView = DirectCast(con, DataGridView)
                obj.Margin = New Padding(6)
            Case GetType(Button)
                Dim obj As Button = DirectCast(con, Button)
                obj.Margin = New Padding(6)
            Case GetType(GroupBox)
                Dim obj As GroupBox = DirectCast(con, GroupBox)
                obj.Margin = New Padding(6)
        End Select
    Next

    'add event handlers
    AddHandler otlp.MouseDown, AddressOf tlp_MouseDown
    AddHandler otlp.MouseUp, AddressOf tlp_MouseUp
    AddHandler otlp.MouseMove, AddressOf tlp_MouseMove
    AddHandler otlp.MouseLeave, AddressOf tlp_MouseLeave
End Sub

''' <summary>
''' Clear the dictionary/hashtable that keeps track of needed variables to control the resizing 
''' </summary>
''' <remarks></remarks>
Public Sub ResetResizeableTableLayOutPanelData()
    otlpdic.Clear()
    otlpdic = Nothing
    Call CreateTableLayoutPanelHash()
End Sub

Private Sub CreateTableLayoutPanelHash()
    If otlpdic Is Nothing Then
         otlpdic = New Dictionary(Of String, Integer())
    End If
End Sub

Private Sub CreateHashEntryForTableLayoutPanel(ByRef otlp As TableLayoutPanel)
    If Not otlp.Tag Is Nothing AndAlso otlpdic.ContainsKey(otlp.Tag) Then

    Else
        Dim tmpguid As Guid = Guid.NewGuid

        otlp.Tag = tmpguid.ToString

        otlpdic.Add(otlp.Tag, {0, -1, -1})
    End If
End Sub

Public Sub tlp_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs)
    If e.Button = System.Windows.Forms.MouseButtons.Left Then
        Dim otlp As TableLayoutPanel = DirectCast(sender, TableLayoutPanel)
        Call CreateHashEntryForTableLayoutPanel(otlp)
        Dim tmpdata As Integer() = otlpdic.Item(otlp.Tag)
        tmpdata(0) = -1

    End If
End Sub


Public Sub tlp_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs)
    Dim otlp As TableLayoutPanel = DirectCast(sender, TableLayoutPanel)
    Call CreateHashEntryForTableLayoutPanel(otlp)
    Dim tmpdata As Integer() = otlpdic.Item(otlp.Tag)

    'Dim rowStyles = 
        'columnStyles = TableLayoutPanel1.ColumnStyles

    If Not tmpdata(0) Then

        Dim width As Double = 0
        Dim height As Double = 0
        'for rows
        For i As Integer = 0 To otlp.RowStyles.Count - 1

            height += otlp.RowStyles(i).Height

            If (e.Y > height - 2 And e.Y < height + 2) Then

                tmpdata(1) = i
                otlp.Parent.Cursor = Cursors.HSplit
                Exit For
            Else
                tmpdata(1) = -1
                otlp.Parent.Cursor = Cursors.Default
            End If
        Next
        'for columns
        For i As Integer = 0 To otlp.ColumnStyles.Count - 1

            width += otlp.ColumnStyles(i).Width
            If e.X > width - 2 And e.X < width + 2 Then

                tmpdata(2) = i
                If (tmpdata(1) > -1) Then
                    otlp.Parent.Cursor = Cursors.Cross
                Else
                    otlp.Parent.Cursor = Cursors.VSplit
                    Exit For
                End If
            Else

                tmpdata(2) = -1
                If (tmpdata(1) = -1) Then
                    otlp.Parent.Cursor = Cursors.Default
                End If
            End If
        Next
    End If
    If (tmpdata(0) And (tmpdata(2) > -1 Or tmpdata(1) > -1)) Then

        Dim Width As Double = e.X
        Dim Height As Double = e.Y

        If e.X > otlp.Width - 100 Then
            Exit Sub
        End If

        If e.Y > otlp.Height - 100 Then
            Exit Sub
        End If



        If (tmpdata(2) > -1) Then
            For i As Integer = 0 To tmpdata(2) - 1

                Width -= otlp.ColumnStyles(i).Width
            Next
            otlp.ColumnStyles(tmpdata(2)).SizeType = SizeType.Absolute


            If Width < 10 Then
                Width = 10
            End If

            If Width > otlp.Width - 100 Then
                Width = otlp.Width - 100
            End If



            otlp.ColumnStyles(tmpdata(2)).Width = Width
        End If
        If (tmpdata(1) > -1) Then

            For i As Integer = 0 To tmpdata(1) - 1

                Height -= otlp.RowStyles(i).Height
            Next
            otlp.RowStyles(tmpdata(1)).SizeType = SizeType.Absolute

            If Height < 10 Then
                Height = 10
            End If

            If Height > otlp.Height - 100 Then
                Height = otlp.Height - 100
            End If


            otlp.RowStyles(tmpdata(1)).Height = Height
        End If
    End If
End Sub


Public Sub tlp_MouseLeave(sender As Object, e As System.EventArgs)
    Dim otlp As TableLayoutPanel = DirectCast(sender, TableLayoutPanel)
    otlp.Parent.Cursor = Cursors.Default
End Sub

Public Sub tlp_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs)
    If e.Button = System.Windows.Forms.MouseButtons.Left Then
        Dim otlp As TableLayoutPanel = DirectCast(sender, TableLayoutPanel)
        Dim tmpdata As Integer() = otlpdic.Item(otlp.Tag)
        tmpdata(0) = 0
        otlp.Parent.Cursor = Cursors.Default
    End If
End Sub
End Module
于 2020-05-10T01:59:12.250 回答