如果单元格中没有控件,如何获取用户单击的单元格。我真正需要的是当一个图像被单击但不在其中时出现在单元格位置。
我想它会与这个伪代码相似
myimage.location = get.cellLocation()
或者其他什么。谢谢你的帮助。
答案 0 :(得分:0)
问题是没有一个真正的"单元"集装箱集合。这些单元格基于ColumnCount
和RowCount
以及相应的ColumnStyles
和RowStyles
是动态的。
如果您的样式使用固定大小,您可以编写自己的方法来计算和存储每个单元格的详细信息 - 可能在每个单元格包含Rectangle
的结构或类中(将计算位置,并且可以从配对的ColumnStyle
和RowStyle
)以及Point
或2 int
中检索大小以存储列和行。然后,在MouseClick
的{{1}}事件中,您可以使用TableLayoutPanel
并使用e.Location
对所有单元格矩形进行检查。然后,使用Rectangle.Contains
的{{1}}方法移动控件。例如:
SetCellPosition
如果您的任何列或行具有动态大小调整(百分比等),那么您将需要做更多工作来计算每个列的详细信息。
如果定位可以改变,您需要重做计算。因此,您需要确保每组计算都是在可以从Resize事件等调用的方法内完成的。
如果你不想经历所有这些疯狂,你还可以做其他一些事情(也许更多,但这些只是我的头脑):
将相同的控件类型(例如TableLayoutPanel
)放入每个单元格中。单击一个时,将图像设置为源控件的图像。单击另一个时,清除前一个,然后设置新的。
通过将任何类型的控件(例如tableLayoutPanel1.SetCellPosition(pictureBox1, new TableLayoutPanelCellPosition(1, 1));
)放入每个单元格来进行一些控制交换魔术。单击一个时,将其从单元格中删除并将图像控件放入其中。单击另一个时,将其删除,将图像控件放在其位置,然后将第一个删除的控件放回原始单元格中。
我认为第一种选择是最简单的。但是,最后的方法取决于你。
答案 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
最终结果如下所示:
如果您知道所需的行数和列数,可以通过将 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
,您还可以使线条点缀,虚线等。