如何从表格布局面板vb.net获取单元格

时间:2016-04-26 19:33:15

标签: vb.net tablelayoutpanel

如果单元格中没有控件,如何获取用户单击的单元格。我真正需要的是当一个图像被单击但不在其中时出现在单元格位置。

我想它会与这个伪代码相似

myimage.location = get.cellLocation()

或者其他什么。谢谢你的帮助。

2 个答案:

答案 0 :(得分:0)

问题是没有一个真正的"单元"集装箱集合。这些单元格基于ColumnCountRowCount以及相应的ColumnStylesRowStyles是动态的。

如果您的样式使用固定大小,您可以编写自己的方法来计算和存储每个单元格的详细信息 - 可能在每个单元格包含Rectangle的结构或类中(将计算位置,并且可以从配对的ColumnStyleRowStyle)以及Point或2 int中检索大小以存储列和行。然后,在MouseClick的{​​{1}}事件中,您可以使用TableLayoutPanel并使用e.Location对所有单元格矩形进行检查。然后,使用Rectangle.Contains的{​​{1}}方法移动控件。例如:

SetCellPosition

如果您的任何列或行具有动态大小调整(百分比等),那么您将需要做更多工作来计算每个列的详细信息。

如果定位可以改变,您需要重做计算。因此,您需要确保每组计算都是在可以从Resize事件等调用的方法内完成的。

如果你不想经历所有这些疯狂,你还可以做其他一些事情(也许更多,但这些只是我的头脑):

  1. 将相同的控件类型(例如TableLayoutPanel)放入每个单元格中。单击一个时,将图像设置为源控件的图像。单击另一个时,清除前一个,然后设置新的。

  2. 通过将任何类型的控件(例如tableLayoutPanel1.SetCellPosition(pictureBox1, new TableLayoutPanelCellPosition(1, 1)); )放入每个单元格来进行一些控制交换魔术。单击一个时,将其从单元格中删除并将图像控件放入其中。单击另一个时,将其删除,将图像控件放在其位置,然后将第一个删除的控件放回原始单元格中。

  3. 我认为第一种选择是最简单的。但是,最后的方法取决于你。

答案 1 :(得分:0)

根据您对国际象棋的需求而定接受点击的样式表,我创建了这个。我没有必要,但我认为这将是一个有趣的转移。此示例创建 63 单元格,因此它非常接近您想要的内容。由于它是在运行中计算的,因此您应该能够根据需要进行重新设计。

首先,您的表单将设置为PictureBox(更容易渲染而不计算边距和诸如此类别)picBoard,另一个PictureBox称为picTile,然后名为Label的{​​{1}}停靠在底部,充当状态栏。我的lblDetails看起来像这样:

InitializeComponent

以下是 private void InitializeComponent() { this.picBoard = new System.Windows.Forms.PictureBox(); this.picTile = new System.Windows.Forms.PictureBox(); this.lblDetails = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.picBoard)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit(); this.SuspendLayout(); // // picBoard // this.picBoard.Location = new System.Drawing.Point(12, 21); this.picBoard.Name = "picBoard"; this.picBoard.Size = new System.Drawing.Size(360, 280); this.picBoard.TabIndex = 0; this.picBoard.TabStop = false; // // picTile // this.picTile.BackColor = System.Drawing.Color.Red; this.picTile.Location = new System.Drawing.Point(143, 67); this.picTile.Name = "picTile"; this.picTile.Size = new System.Drawing.Size(51, 51); this.picTile.TabIndex = 1; this.picTile.TabStop = false; this.picTile.Visible = false; // // lblDetails // this.lblDetails.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.lblDetails.Dock = System.Windows.Forms.DockStyle.Bottom; this.lblDetails.Location = new System.Drawing.Point(0, 326); this.lblDetails.Name = "lblDetails"; this.lblDetails.Size = new System.Drawing.Size(393, 23); this.lblDetails.TabIndex = 2; this.lblDetails.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(393, 349); this.Controls.Add(this.lblDetails); this.Controls.Add(this.picTile); this.Controls.Add(this.picBoard); this.Name = "Form1"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; this.Text = "Grid Test"; ((System.ComponentModel.ISupportInitialize)(this.picBoard)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit(); this.ResumeLayout(false); } 代码的全部内容,以及底部的自定义类Form(我并不想单独制作)。请记住,这只是我匆忙创建的东西,看看它对你来说有多难。如果您对正在发生的事情有任何疑问,请询问。

CellDetails

最终结果如下所示:

Dynamic Grid Example

如果您知道所需的行数和列数,可以通过将 public partial class Form1 : Form { List<CellDetails> cells = new List<CellDetails>(); // Defines the size of each cell. const int cCellSize = 40; int boardLeft = 0; int boardTop = 0; public Form1() { InitializeComponent(); picTile.Size = new Size(cCellSize, cCellSize); picBoard.MouseMove += PicBoard_MouseMove; picBoard.MouseClick += PicBoard_MouseClick; picBoard.Paint += PicBoard_Paint; CreateCells(); boardLeft = picBoard.Location.X; boardTop = picBoard.Location.Y; } private void PicBoard_Paint(object sender, PaintEventArgs e) { if (cells.Count > 0) { bool alt = false; SolidBrush cellBrush1 = new SolidBrush(Color.LightGray); SolidBrush cellBrush2 = new SolidBrush(Color.DarkGray); foreach (CellDetails cell in cells) { e.Graphics.FillRectangle((alt ? cellBrush1 : cellBrush2), cell.Dimension); alt = !alt; } cellBrush1.Dispose(); cellBrush2.Dispose(); } } private void PicBoard_MouseClick(object sender, MouseEventArgs e) { CellDetails cell = FindCell(e); if (cell != null && cell.Location.X > -1 && cell.Location.Y > -1) { picTile.Location = new Point(cell.Dimension.X + boardLeft, cell.Dimension.Y + boardTop); picTile.Visible = true; } else { picTile.Visible = false; } } private void PicBoard_MouseMove(object sender, MouseEventArgs e) { CellDetails cell = FindCell(e); string details; if (cell == null || cell.Location.X < 0 || cell.Location.Y < 0) { details = "Could not find cell"; } else { details = string.Format("Row: {0}, Col: {1}", cell.Location.Y, cell.Location.X); } lblDetails.Text = String.Format("{0}, {1} = {2}", e.X, e.Y, details); } private CellDetails FindCell(MouseEventArgs e) { CellDetails ret = null; foreach (CellDetails cell in cells) { if (cell.Dimension.Contains(e.Location)) { ret = cell; break; } } return ret; } private void CreateCells() { CellDetails cell; Point cellLoc; int rows = (picBoard.ClientSize.Height / cCellSize); int cols = (picBoard.ClientSize.Width / cCellSize); // Loop through the rows for (int row = 0; row < rows; row++) { // Loop through the columns for (int col = 0; col < cols; col++) { cell = new CellDetails(); cellLoc = new Point(); cellLoc.Y = row + 1; cellLoc.X = col + 1; cell.Location = cellLoc; cell.Dimension = new Rectangle(col * cCellSize, row * cCellSize, cCellSize, cCellSize); cells.Add(cell); } } lblDetails.Text = String.Format("Generated {0} cells.", cells.Count); } } public class CellDetails { public CellDetails() { } public Rectangle Dimension { get; set; } public Point Location { get; set; } } 除以计数而不是预定义的单元格大小来计算单元格宽度/高度。如果您可以调整大小,这也会有所帮助,这会导致不同的单元格大小。只需更改代码以计算该方式,然后在调整大小后调用ClientSize。您可能也想在顶部添加CreateCells之类的行。

它可能不需要提及,但万一有其他人出现:如果您只需要对不可见单元格进行命中测试(无渲染),则可以完全删除if (cells.Count > 0) cells.Clear();事件。如果您想要网格线而不是填充框,请将Paint更改为FilledRectangle,并使用DrawRectangle代替Pen。使用SolidBrush,您还可以使线条点缀,虚线等。