Reputation: 167
So basically I've got a game board going, represented by a TableLayoutPanel. Each cell of the TableLayoutPanel represents a space on the board and contains a Panel. Each Panel has a Label in it to display what is currently in that space (e.g. a character or building) and its BackColor represents what kind of terrain that space is (e.g. Land, Water, etc.). When the player attempts to move a character, each possible space that that character can move will become "highlighted." The player will then double click one of the highlighted spaces to move the character there.
In order to highlight a space, I add a Panel to the existing Panel (the one that already has a Label in it).
So to recap, TableLayoutPanel --> Panel --> Label, Panel.
The main problem I'm having is that I can't get the "highlight-Panel" to center within its parent Panel; it's always Top-Left Centered. I want to be able to see part of the BackColor of the parent Panel in order to make it easier for the player to decide where to go. Thus, setting Dock to Fill is not an option. The highlight-Panel is slightly smaller than the parent Panel, thereby allowing for the edges of the parent Panel's BackColor to be visible. Yes, Anchor is set to None.
The secondary problem is that I cannot get any of the Labels' text colors to change. I've tried changing it at initialization or more directly with a specific location using "tableLayoutPanel.GetControlFromPosition(16, 4).Controls[0].ForeColor = Color.White;" but nothing seems to work.
To be honest, I'm not interested in super complicated hack fixes. But if there's something simple or something I missed, I'd really appreciate some input. Thanks.
This is the code that creates the TableLayoutPanel, the Panels within that, and the Labels within each Panel:
// Create TableLayoutPanel to hold Panels
tableLayoutPanel = new TableLayoutPanel()
{
RowCount = 1,
ColumnCount = 1,
AutoSize = true,
AutoSizeMode = AutoSizeMode.GrowAndShrink,
Location = new Point(12, 12),
Dock = DockStyle.Fill,
AutoScroll = true,
};
// Add tableLayoutPanel to the form
this.Controls.Add(tableLayoutPanel);
// Reset and add rows/columns + styles
tableLayoutPanel.RowStyles.Clear();
tableLayoutPanel.ColumnStyles.Clear();
for (int i = 0; i < rows; i++)
{
tableLayoutPanel.RowCount++;
tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
}
tableLayoutPanel.RowCount--;
for (int j = 0; j < cols; j++)
{
tableLayoutPanel.ColumnCount++;
tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
}
tableLayoutPanel.ColumnCount--;
// Add Panels to TableLayoutPanel
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
// Create new Panel
Panel space = new Panel()
{
BackColor = SystemColors.ActiveCaption,
BorderStyle = BorderStyle.FixedSingle,
Margin = new Padding(0),
Size = new Size(45, 45)
};
space.MouseClick += new MouseEventHandler(clickOnSpace);
// Create new Label
Label info = new Label()
{
Size = new Size(93, 93),
Text = "Info",
Dock = DockStyle.Fill,
TextAlign = ContentAlignment.MiddleCenter,
Enabled = false,
Font = new Font("Microsoft Sans Serif", 6),
ForeColor = Color.White
};
// Add Label to Panel
space.Controls.Add(info);
// Add Panel to TableLayoutPanel
tableLayoutPanel.Controls.Add(space, j, i);
}
}
And the code that creates the highlight-Panel:
// Highlight potential positions using possibleMoves
private void Highlight(List<Tuple<int, int>> possibleMoves, int remaining)
{
int r = 0;
int c = 0;
foreach (Tuple<int, int> pair in possibleMoves)
{
r = pair.Item1;
c = pair.Item2;
// If highlight-Panel doesn't already exist
if (tableLayoutPanel.GetControlFromPosition(c, r).Controls.Count == 1)
{
// Create a Panel to highlight the space
Panel highlight = new Panel()
{
Name = "highlight",
Size = new Size(30, 30),
BackColor = Color.Yellow,
Anchor = AnchorStyles.None
};
highlight.MouseDoubleClick += new MouseEventHandler(doubleClickOnSpace);
// Add highlight Panel to space Panel
tableLayoutPanel.GetControlFromPosition(c, r).Controls.Add(highlight);
// Bring highlight Panel to front
tableLayoutPanel.GetControlFromPosition(c, r).Controls[1].BringToFront();
}
}
}
Upvotes: 4
Views: 2911
Reputation: 167
So I actually reached a less complicated method. Instead of having a Panel within a Panel, I opted for keeping my original Panel, and creating a custom Label, which has an outside border whose thickness and color can be changed. This way I don't have to keep track of too many controls, and the CustomLabel displays everything needed.
Code for CustomLabel:
public class CustomLabel : Label
{
// Constructors
// Default Constructor
public CustomLabel() : base() { }
public CustomLabel(bool drawBorder, int borderThickness, Color borderColor, Color textColor) : base()
{
if (drawBorder)
{
BorderThickness = borderThickness;
BorderColor = borderColor;
}
Size = new Size(36, 36);
Text = "Info";
Anchor = (AnchorStyles.Left | AnchorStyles.Right);
AutoSize = false;
TextAlign = ContentAlignment.MiddleCenter;
Enabled = false;
Font = new Font("Microsoft Sans Serif", 6);
ForeColor = TextColor;
BorderStyle = BorderStyle.FixedSingle;
Dock = DockStyle.Fill;
}
// Creates a border of specified thickness and color
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (BorderStyle == BorderStyle.FixedSingle)
{
int halfThickness = BorderThickness / 2;
using (Pen p = new Pen(BorderColor, BorderThickness))
{
e.Graphics.DrawRectangle(p, new Rectangle(halfThickness,
halfThickness,
ClientSize.Width - BorderThickness, ClientSize.Height - BorderThickness));
}
}
}
public int BorderThickness { get; set; }
public Color BorderColor { get; set; }
}
Code for adding CustomLabel to Panels:
// Add Panels to TableLayoutPanel
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
// Create new Panel
Panel space = new Panel()
{
Size = new Size(45, 45),
Dock = DockStyle.Fill,
Margin = new Padding(0),
ForeColor = Color.Red
};
space.MouseClick += new MouseEventHandler(MouseDownOnSpace);
CustomLabel info = new CustomLabel(false, 0, Color.Empty, Color.Red); // Create new CustomLabel
space.Controls.Add(info); // Add CustomLabel to Panel
tlp.Controls.Add(space, j, i); // Add Panel to TableLayoutPanel
}
}
Code for adjusting the CustomLabel:
((CustomLabel)tlp.GetControlFromPosition(col, row).Controls[0]).BorderThickness = 6;
((CustomLabel)tlp.GetControlFromPosition(col, row).Controls[0]).BorderColor = Color.Yellow;
tlp.GetControlFromPosition(col, row).Controls[0].Text = tlp.GetControlFromPosition(col, row).Controls[0].Text; // Transfer space information
tlp.GetControlFromPosition(col, row).Refresh(); // Refresh Panel to show changes
This is the end result: (As you can see, the ForeColor still doesn't change.)
Upvotes: 0
Reputation: 125197
... Thus, setting Dock to Fill is not an option.
In fact I believe setting Dock
to Fill
is really a good option!
Take a look at this image. It's a TableLayoutPanel
having 2 columns and 2 rows. And each cell contains a Pannel
which contains a Panel
which contains a Label
. Despite what you expect Dock
property of all controls has been set to Fill
!
I tell you settings for the first cell which you can see Red
, Black
and White
colors in it.
The cell contains:
Red area, a Panel
having:
○ BackColor
property set to Red
○ Margin
property set to all 0
○ Padding
property set to all 5
○ Dock
property set to Fill
Black area, a Panel
having:
○ BackColor
property set to Black
○ Margin
property set to all 0
○ Padding
property set to all 5
○ Dock
property set to Fill
White label, a Label
having:
○ BackColor
property set to White
○ Margin
property set to all 0
○ Padding
property set to all 0
○ Dock
property set to Fill
The structure of other cells are exactly the same, but the BackColor
of Label
and its parent (like the black one), to Transparent
, so you see the BackColor
of the most inner Panel
(like the red one).
Note
The answer is completely based on setting Dock
property to Fill
and setting suitable Padding
value for docked controls. But there is another elegant solution for keeping a control at center of a container automatically which is based on using a TableLayoutPanel
having 1 row and 1 column instead of panel, and then setting Anchor
property of child to None
. This way the child will be centered horizontally and vertically in the TableLayoutPanel
. You will find this post about it useful:
Upvotes: 3