我正在开发一个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;
}
}
}
答案 0 :(得分:3)
将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;
}
}
}
答案 1 :(得分:1)
我改进了MD答案的代码 我没有收听TableLayoutPanel的MouseEvents,而是听那些控件。以下是可调整大小的行的代码:
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;
}
}
答案 2 :(得分:0)
我的回答是使用鼠标仅调整tablelayoutpanel的列,但可以轻松更新以对行执行相同操作。当然,我宁愿使用分割板作为行,但仍然。在代码中,我可以提供4列,但将其扩展到更多或更少是很容易的。 cursurToDefault事件将添加到tablelayoutpanel内容器控件的mousemove事件中。
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;
}
}
答案 3 :(得分:0)
根据原始代码编写模块
这使用字典和4个事件处理程序来处理多个tablelayoutpanel,以调整其行和列的大小。
其中包含一些代码,用于捕获屏幕外的内容,但不多。
阅读代码中的注释以获取更多信息
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