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);
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);
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.
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);
}
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 :)
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);
Related
I am creating a project that needs to have a vertical scroll bar with multiple pictures like the server explorer in discord:
For example:
how can I mimic in WinForms in C# (not only having pictures scrolling but also the pictures can have events attached to them?
First you need add a Parent Panel, i'm used the pnServers.
Set property value:
AutoScroll = True;
On Code Behind you can create a List of Rounded Pictures.
private void DiscordServerBarExample_Load(object sender, System.EventArgs e)
{
// Example, in your case this looping is based on return (Database, Api, ...).
for (int i = 1; i <= 10; i++)
{
Panel pnServer = new Panel()
{
Dock = DockStyle.Top,
Height = pnServers.Width,
Padding = new Padding(10)
};
RoundedPictureBox serverImage = new RoundedPictureBox()
{
SizeMode = PictureBoxSizeMode.CenterImage,
Dock = DockStyle.Fill
};
serverImage.Image = Properties.Resources._255352;
pnServer.Controls.Add(serverImage);
pnServers.Controls.Add(pnServer);
}
}
Rounded Picture Box Code:
public class RoundedPictureBox : PictureBox
{
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(0, 0, Width - 1, Height - 1);
Region rg = new Region(gp);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawEllipse(new Pen(new SolidBrush(this.BackColor), 1), 0, 0, this.Width - 1, this.Height - 1);
Region = rg;
}
}
}
And this is final result.
So I'm creating some panels with the following code
private void button1_Click(object sender, EventArgs e)
{
int xlocation = 5;
for (int i = 0; i < 10; i++)
{
Panel panel = new Panel();
{
panel.Name = string.Format("{0}", i);
panel.Text = string.Format(i.ToString());
panel.BackColor = Color.White;
panel.Location = new System.Drawing.Point(xlocation, 30);
panel.Width = flowLayoutPanel1.Width;
panel.Height = 50;
panel.MouseEnter += new System.EventHandler(this.panel_MouseEnter);
flowLayoutPanel1.Controls.Add(panel);
Label label = new Label();
label.Location = new System.Drawing.Point(15, 10);
label.AutoSize = true;
label.Font = new System.Drawing.Font("Calibri", 13F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label.ForeColor = System.Drawing.Color.FromArgb(64, 64, 64);
label.Text = string.Format("{0}", "GNU" + i);
panel.Controls.Add(label);
Label label10 = new Label();
label10.Location = new System.Drawing.Point(15, 35);
label10.AutoSize = true;
label10.Font = new System.Drawing.Font("Calibri", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
label10.ForeColor = System.Drawing.Color.FromArgb(64, 64, 64);
label10.Text = string.Format("{0}", "hest");
panel.Controls.Add(label10);
}
xlocation = xlocation + 85;
}
}
The problem is when I resize my form, my flowLayoutPanel obviously gets bigger, but the panels inside doesn't.
I have tried using the
private void Form1_Resize(object sender, EventArgs e)
{
}
But it doesn't seem to work.
Any answer is much appreciated!
Thanks!
You can either use the Anchor property and set it to Right and Left, or can dock each panel to parent control. Something like this should work:
Panel panel = new Panel();
panel.Dock = DockStyle.Top; // Docks the panel to top, and fills to the width of Parent control
panel.Anchor = (AnchorStyles.Right | AnchorStyles.Left); // Set anchor to right and left
I found a solution. I just created a list with my panels like so
List<Panel> pnls = new List<Panel>();
And just did like so to make them follow the width of my flowlayoutpanel, so you can actually use a flowlayoutpanel ;-)
private void Kontrol_Resize(object sender, EventArgs e)
{
for (int i = 0; i < pnls.Count; i++)
{
pnls[i].Width = activityData.Width - 24;
pnls[i].Height = activityData.Height / 4;
}
}
I already made a rounded button and now im trying to create a rounded textbox. I searched some questions but all is in VB and I don't know that language. And converters are weird. So I tried creating a rounded textbox. So I set the UserPaint to true so I can use OnPaint. It works beautifully on my buttons but it glitches out on my textboxes. It has 2 issues:
The font size is always the same size no matter what I set it to.
And when onpaint is called but the text doesn't change it deletes it. That is mostly when I hover my mouse over it.
Code:
class RoundedTextBox : TextBox
{
public Color color = Color.White;
public int borderRadius = 25;
public RoundedTextBox()
{
SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
RectangleF Rect = new RectangleF(0, 0, this.Width, this.Height);
SolidBrush brush = new SolidBrush(color);
GraphicsPath GraphPath = Functions.FillRoundedRectangle(e.Graphics, brush, Rect, borderRadius);
this.Region = new Region(GraphPath);
}
}
How I add my textbox:
RoundedTextBox usernameTextbox = new RoundedTextBox();
usernameTextbox.Location = new Point(14, 217);
usernameTextbox.Font = new Font(usernameTextbox.Font.FontFamily, 20);
usernameTextbox.Size = new Size(282, this.Height);
usernameTextbox.color = Color.White;
usernameTextbox.Name = "usernameTextbox";
usernameTextbox.Text = "test";
textboxes.Add(usernameTextbox);
usernameTextbox.BackColor = Color.White;
usernameTextbox.borderRadius = 20;
this.Controls.Add(usernameTextbox);
Gif of the problem
This question already has answers here:
how to change the check image on a checkbox
(5 answers)
Closed 2 years ago.
I want to change the border color and the background of the square and the color of the check mark, but not the text. To better understand, what I want to accomplish is the following example:
checkBox1.Checked = false
checkBox1.Checked = true
Thanks so much to everyone of you responds exactly to this request!
You can simply draw the checkmark in the Paint event:
private void checkBox1_Paint(object sender, PaintEventArgs e)
{
Point pt = new Point(e.ClipRectangle.Left + 2, e.ClipRectangle.Top + 4);
Rectangle rect = new Rectangle(pt, new Size(22, 22));
if (checkBox1.Checked)
{
using (Font wing = new Font("Wingdings", 14f))
e.Graphics.DrawString("ü", wing, Brushes.DarkOrange,rect);
}
e.Graphics.DrawRectangle(Pens.DarkSlateBlue, rect);
}
for this to work you need to:
set Apperance = Appearance.Button
set FlatStyle = FlatStyle.Flat
set TextAlign = ContentAlignment.MiddleRight
set FlatAppearance.BorderSize = 0
set AutoSize = false
If you want to re-use this it will be best to subclass the checkbox and override the OnPaint event there. Here is an example:
public ColorCheckBox()
{
Appearance = System.Windows.Forms.Appearance.Button;
FlatStyle = System.Windows.Forms.FlatStyle.Flat;
TextAlign = ContentAlignment.MiddleRight;
FlatAppearance.BorderSize = 0;
AutoSize = false;
Height = 16;
}
protected override void OnPaint(PaintEventArgs pevent)
{
//base.OnPaint(pevent);
pevent.Graphics.Clear(BackColor);
using (SolidBrush brush = new SolidBrush(ForeColor))
pevent.Graphics.DrawString(Text, Font, brush, 27, 4);
Point pt = new Point( 4 , 4);
Rectangle rect = new Rectangle(pt, new Size(16, 16));
pevent.Graphics.FillRectangle(Brushes.Beige, rect);
if (Checked)
{
using (SolidBrush brush = new SolidBrush(ccol))
using (Font wing = new Font("Wingdings", 12f))
pevent.Graphics.DrawString("ü", wing, brush, 1,2);
}
pevent.Graphics.DrawRectangle(Pens.DarkSlateBlue, rect);
Rectangle fRect = ClientRectangle;
if (Focused)
{
fRect.Inflate(-1, -1);
using (Pen pen = new Pen(Brushes.Gray) { DashStyle = DashStyle.Dot })
pevent.Graphics.DrawRectangle(pen, fRect);
}
}
You may need to tweek the sizes of the control and the font.. And if you want to you expand the code to honor the TextAlign and the CheckAlign properties.
And if you need a three-state control you can adapt the code to display a third state appearance, especially if you think of one that looks better than the original..
You have to write your own checkbox. By making a custom control in which there's a blue square(possibly inherits from Button) that toggles between checked and not checked images by an OnClick event and place a label next to it.
I am creating a new user control. My control extends a StackPanel, and for now consists of another StackPanel in which I'm adding some Rectangles. I would like the inner StackPanel to be horizontally centered within the control, and the Rectangles to be vertically aligned with the bottom of the inner StackPanel. My code is below, but it results in the inner StackPanel aligned to the left of the control, and the Rectangles are aligned at the top of the inner StackPanel.
public partial class ComponentStacker : StackPanel
{
private StackPanel tokenHolder;
public ComponentStacker(int numTokens)
{
this.Orientation = Orientation.Horizontal;
tokenHolder = new StackPanel();
this.Children.Add(tokenHolder);
tokenHolder.Background = new SolidColorBrush(Colors.DarkKhaki);
tokenHolder.HorizontalAlignment = HorizontalAlignment.Center;
for (int i = 0; i < numTokens; i++)
{
Rectangle rect = new Rectangle();
rect.Width = 15;
rect.Height = 10;
rect.Margin = new Thickness(5, 5, 5, 0);
rect.Fill = new SolidColorBrush(Colors.Red);
rect.VerticalAlignment = VerticalAlignment.Bottom;
this.tokenHolder.Children.Add(rect);
}
this.Background = new SolidColorBrush(Colors.Goldenrod);
this.Margin = new Thickness(10);
}
}
My first question is : why not add the rectangle directly to your stackPanel ?
i mean no tokenHolder stuff and :
this.Children.Add(rect);
instead of
this.tokenHolder.Children.Add(rect);
Switch on the code helped me for those kind of things :
http://www.switchonthecode.com/tutorials/wpf-tutorial-creating-a-custom-panel-control
I found the problem. It's the line:
this.Orientation = Orientation.Horizontal;
When I changed it to Orientation.Vertical, the inner tokenPanel centered nicely.