7

I've attempted to create a custom Panel with a border around it, whose Color can be changed in order to "highlight" the Panel under certain conditions.

The Panel will also need to communicate certain information via text. For this purpose, I've added a Label to the Panel. I've tried the prescribed methods for centering the Label but for some reason it always puts it to the top-left of the Panel. I can't set the Label's Dock to Fill because that covers up the custom border that's been created. So I need to make it so that the Label fits within the border.

The Label's Anchor is set to None and its Location is

new Point((ClientSize.Width - Size.Width)/2, (ClientSize.Height - Size.Height)/2);

The code for the custom Panel is:

public class CustomPanel : Panel
{
    public CustomPanel(int borderThickness, Color borderColor) : base()
    {
        SetStyle(ControlStyles.AllPaintingInWmPaint | 
                 ControlStyles.UserPaint | 
                 ControlStyles.OptimizedDoubleBuffer | 
                 ControlStyles.ResizeRedraw, true);

        BackColor = SystemColors.ActiveCaption;
        BorderStyle = BorderStyle.FixedSingle;
        Size = new Size(45, 45);
        Margin = new Padding(0);
        BorderThickness = borderThickness;
        BorderColor = borderColor;
    }

    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; }
}

And the Form code is:

private void NewPanelTest_Load(object sender, EventArgs e)
{
    CustomPanel cp = new CustomPanel(3, Color.Black);

    // Create new Label
    Label info = new Label()
    {
        Size = new Size(30, 30),
        Text = "Info",
        Anchor = AnchorStyles.None,
        TextAlign = ContentAlignment.MiddleCenter,
        Enabled = false,
        Font = new Font("Microsoft Sans Serif", 6),
        ForeColor = Color.White,
        Location = new Point(ClientSize.Width/2 - Width/2, ClientSize.Height/2 - Height/2)
    };

    cp.Controls.Add(info);

    this.Controls.Add(cp);
}

EDIT: I've looked at similar questions asked and tried changing the Label's properties but with no results.

// Create new Label
Label info = new Label()
{
    // Same code as before

    // Different code
    Left = (this.ClientSize.Width - Size.Width) / 2,
    Top = (this.ClientSize.Height - Size.Height) / 2,
    //Location = new Point(ClientSize.Width/2 - Width/2, ClientSize.Height/2 - Height/2)
};

I've also tried changing the Panel's Padding, also with no results.

Padding = new Padding(5);

EDIT: Attempt at programatically placing Label in center of Panel (yields results of X = 0, Y = 0)

// Create new Label
Label info = new Label()
{
    // Same code as before (excluding "Left", "Top", and "Location")
};
int X = (info.ClientSize.Width - info.Width) / 2;
int Y = (info.ClientSize.Height - info.Height) / 2;
info.Location = new Point(X, Y);
MessageBox.Show(info.Location.ToString());

cp.Controls.Add(info);
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Nick08
  • 157
  • 1
  • 2
  • 10
  • Possible duplicate of [Centering controls within a form in .NET (Winforms)?](http://stackoverflow.com/questions/491399/centering-controls-within-a-form-in-net-winforms) – Breeze Aug 18 '16 at 17:11
  • 1
    Place label at middle and set Anchor Left,Right ,and autosize to false – Manu Varghese Aug 18 '16 at 17:12
  • I think my problem is with Location. Setting the Anchor and the AutoSize properties doesn't do anything. Is the calculation for the middle of the Panel that I have correct? – Nick08 Aug 18 '16 at 17:19
  • @Breeze I've looked at that already and the calculations there are basically the same as what I have. I've even tried implementing it using the Top and Left properties but no luck. I've also tried adjusting the Padding property but still nothing. – Nick08 Aug 18 '16 at 17:23
  • Of all the controls in the toolbox, Label and PictureBox are by far the most wasteful. Just point-and-click convenience, they are not worth the single line of code you save by a very long shot. Use TextRenderer.DrawText() instead. You need ResizeRedraw = true in the constructor. – Hans Passant Aug 18 '16 at 17:27
  • Your code won`t work if the form is resized as you have no anchor nor any code to handle resizing. As shown in an answer, this is trivial to do. Just set the correct properties. – Phil1970 Aug 18 '16 at 17:34
  • Using a `TableLayoutPanel` instead of `Panel` you can simply keep your control at the center of `TableLayoutPanel`. Also you can simply draw the border around TableLayoutPanel. Check the answer which I posted. I believe it's the best option :) – Reza Aghaei Aug 19 '16 at 20:26

4 Answers4

14

enter image description here

We can achive this by simple steps

  • Set Label Anchor to Left and Right
  • Set Label AutoSize to false ;
  • Set Label TextAlign to MiddleCenter;

now Place label middle of panel.

   int x = (panel1.Size.Width - label1.Size.Width) / 2;
    label1.Location = new Point(x, label1.Location.Y);
Manu Varghese
  • 791
  • 8
  • 25
  • Can you be more specific about how to place the Label in the Middle of the Panel programatically? I won't necessarily know how many Panels I'll need to create beforehand, so I need to create each one, and each Label, programatically. – Nick08 Aug 18 '16 at 17:33
  • 1
    int X =(Width of panel - width of label)/ 2 ; Label.Location = new Point(X, height); – Manu Varghese Aug 18 '16 at 17:35
  • Ok I've added that just after creating the Label. However now the Label disappears entirely. The Location is apparently (-9, 496)... – Nick08 Aug 18 '16 at 17:44
  • 1
    @NickV987 use `panel1.Size.Width` instead of `ClientSize` because `panel1` is the parent control of label – Manu Varghese Aug 18 '16 at 17:59
  • @ManuVarghese TableLayoutPanel has a special layout engine which allows you to keep a control at it's center simply by setting `Anchor` of the child to `None`. Take a look at the answer which I shared. – Reza Aghaei Aug 19 '16 at 20:29
4

Keep a Control vertically and horizontally at Center of Container

The most simple option is using a TableLayoutPanel with 1 column and 1 row instead of a Panel. Put the Label in it, then it's enough to set Anchor of label to None to have label always in center vertically and horizontally.

2 1

Also to paint custom borders, it's enough to handle CellPaint event of TableLayoutPanel and draw custom border:

private void tableLayoutPanel1_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
{
    var r = e.CellBounds;
    r.Width--;
    r.Height--;
    e.Graphics.DrawRectangle(Pens.Red, r);
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 1
    It's the most simple option available for centering a control in a parent using designer and most users are not aware of such feature in `TableLayoutPanel`. – Reza Aghaei Sep 16 '16 at 20:43
1

Hey this problem is pretty easy to solve. I assume that in the future you may have some more labels that you may have to center, so I made this function that accepts the label that you want to center and the parent panel. This code is for Visual C# Windows Forms Application. There are a few things that we have to do prior to calling this function. We need to:

  • Select the label and set its Anchor to left, right
  • Remove AutoSize
  • Set label TextAlign to MiddleCenter

This is the code that you need to write for our function

        public void Centroid(Label label, Panel parent)
        {
            int x = (parent.Size.Width - label.Size.Width) / 2;
            label.Location = new Point(x, label.Location.Y);
        }

and to call the function you have to type: Centroid(label1, panel1); This is assuming that you have a label named label1 & a panel named panel 1. You can substitute these values with anything as long as it is a label and a panel.

Hope this helps you :)

Manas Hejmadi
  • 63
  • 1
  • 8
1

I did a horizontal centres alignment of a panel and a label thus:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        label1 = new System.Windows.Forms.Label();
        this.SuspendLayout(); 
        this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 23F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(1401, 462);
        this.Controls.Add(this.label1);
        this.Font = new System.Drawing.Font("Times New Roman", 15.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
        this.Margin = new System.Windows.Forms.Padding(6, 5, 6, 5);
        this.Name = "Form1";
        this.Text = "Form1";
        this.ResumeLayout(false);
        this.PerformLayout();


        int borderThickness = 5;
        Color borderColor = Color.Cyan;
        CustomPanel panel1 = new CustomPanel(borderThickness, borderColor);
        panel1.BackColor = Color.Yellow;
        panel1.Location = new Point(400, 30);
        panel1.Size = new Size(300, 300);
        panel1.Parent = this;
        this.Controls.Add(panel1);

        label1.Name = "label1";
        label1.TabIndex = 0;
        label1.AutoSize = true;
        label1.ForeColor = Color.Black;
        label1.Text = "this is the text whose center I want to align";
        label1.Location = new Point(panel1.Location.X + panel1.Width / 2 - label1.Width / 2, 80);
        if (this.Controls.Contains(label1))
        {
            label1.BringToFront();
        }
    }

    private Label label1;
}

Since I posted the answer, I found out that in order the label to be aligned with the centre of the panel, the statement:

this.Controls.Add(label1);

MUST be located after the statement:

label1 = new Label();

and before the statement:

label1.Location = new Point(panel1.Location.X + panel1.Width / 2 - label1.Width / 2, 80);
user2102327
  • 59
  • 2
  • 6
  • 19