Adding a label programmatically in C# - c#

I am trying to create a paddle using a label which must be done programmatically to a brick breaker game and my aim is so that no matter what desktop computer with different screen sizes I'm using, the paddle will always be in the bottom center of the screen but for some reason the paddle(label) is not showing. This is the code I'm using:
Screen userScreen = Screen.PrimaryScreen;
int screenWidth = userScreen.WorkingArea.Width;
int screenHeight = userScreen.WorkingArea.Height;
this.Width = screenWidth;
this.Height = screenHeight;
Label lblPaddle = new Label();
lblPaddle.BackColor = Color.White;
lblPaddle.BorderStyle = BorderStyle.FixedSingle;
//lblPaddle.Left = (this.ClientSize.Width - lblPaddle.Width) / 2;
//lblPaddle.Top = (this.ClientSize.Height - lblPaddle.Height) / 2;
//lblPaddle.Size = this.ClientSize;
int lblPaddleWidth = (int)(screenWidth * 0.15);
int lblPaddleHeight = lblPaddle.Height;
int lblPaddleXCoord = (screenWidth / 2) - (lblPaddleWidth / 2);
int lblPaddleYCoord = screenHeight - lblPaddleHeight - (int)(screenHeight * 0.1);
lblPaddle.SetBounds(lblPaddleXCoord, lblPaddleYCoord, lblPaddleWidth, lblPaddleHeight);
this.Controls.Add(lblPaddle);
The part where there are comments were different approaches I attempted in order to try and make it work.
Why is it not showing?

I have absolutely no problems with your code when called like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitLabel();
}
private void InitLabel()
{
Screen userScreen = Screen.PrimaryScreen;
int screenWidth = userScreen.WorkingArea.Width;
int screenHeight = userScreen.WorkingArea.Height;
this.Width = screenWidth;
this.Height = screenHeight;
// I added the following 2 lines because the form was below the task bar
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(0,0);
Label lblPaddle = new Label();
lblPaddle.Name = "lblPaddle";
lblPaddle.BackColor = Color.White;
lblPaddle.BorderStyle = BorderStyle.FixedSingle;
int lblPaddleWidth = (int)(screenWidth * 0.15);
int lblPaddleHeight = lblPaddle.Height;
int lblPaddleXCoord = (screenWidth / 2) - (lblPaddleWidth / 2);
int lblPaddleYCoord = screenHeight - lblPaddleHeight - (int)(screenHeight * 0.1);
lblPaddle.SetBounds(lblPaddleXCoord, lblPaddleYCoord, lblPaddleWidth, lblPaddleHeight);
this.Controls.Add(lblPaddle);
}
}
It ends up looking like this:
EDIT: If you're planning to do anything with it, I suggest giving it a name. I added it above.

For some odd reason this was not working. I spoke with a lecturer at my school and she also could not figure out what the problem was. Perhaps it was a bug of some sort. The only way I managed to resolve this was by creating another form and create another paddle and then I copied the code from the form I created to the original and it worked. Neither me nor the lecturer could figure out what the problem was. It was just plain weird since the code was basically the same.

Related

C# - ".FillRectangle" Not Completely Filling Rectangle

I'm using the following code as just a test for how I might use a custom progress bar in the future - it actually isn't a progress bar at all, but rather a picturebox that the code draws a rectangle on, and then fills up based on a timer.
The problem is, I'm reaching 100% before the box is filled. I've tinkered around, but not been able to locate the issue. What am I doing wrong? See code below, and imgur screenshot of the behavior on my system.
Thanks.
public partial class frmLoading : Form
{
System.Windows.Forms.Timer tLoading = new System.Windows.Forms.Timer();
Double pbLoadingUnit;
int pbLoadingWIDTH, pbLoadingHEIGHT, pbLoadingComplete;
Bitmap bmpLoading;
Graphics gLoading;
private void frmLoading_Load(object sender, EventArgs e)
{
pbLoadingWIDTH = pictureLoading.Width;
pbLoadingHEIGHT = pictureLoading.Height;
pbLoadingUnit = pbLoadingWIDTH / 100;
pbLoadingComplete = 0;
bmpLoading = new Bitmap(pbLoadingWIDTH, pbLoadingHEIGHT);
tLoading.Interval = 32;
tLoading.Tick += new EventHandler(this.tLoading_Tick);
tLoading.Start();
}
private void tLoading_Tick(object sender, EventArgs e)
{
gLoading = Graphics.FromImage(bmpLoading);
gLoading.Clear(Color.DarkSlateGray);
gLoading.FillRectangle(Brushes.DodgerBlue, new Rectangle(0, 0, (int)(pbLoadingComplete * pbLoadingUnit), pbLoadingHEIGHT));
gLoading.DrawString(pbLoadingComplete + "%", new Font("Segoe UI Semibold", pbLoadingHEIGHT / 2), Brushes.White, new PointF(pbLoadingWIDTH / 2 - pbLoadingHEIGHT, pbLoadingHEIGHT / 10));
pictureLoading.Image = bmpLoading;
pbLoadingComplete++;
if (pbLoadingComplete > 100)
{
gLoading.Dispose();
tLoading.Stop();
}
}
You should change this
pbLoadingUnit = pbLoadingWIDTH / 100;
to this
pbLoadingUnit = Convert.ToDouble(pbLoadingWIDTH) / 100;
I assume your picture width is not a multiple of a hundred.
With your old code, your pbLoadingUnit will be generate as integer since you divide integer to integer.
You may use this too :
double div = 100;
pbLoadingUnit = pbLoadingWIDTH / div;
OR
pbLoadingUnit = pbLoadingWIDTH / Convert.ToDouble(100);
The point is, you should get the double value of pbLoadingUnit.
For more information about numeric casting, you may see this link dotnetperls.com/numeric-casts
Try to put the following lines in OnResize() event of the frmLoading:
pbLoadingWIDTH = pictureLoading.Width;
pbLoadingHEIGHT = pictureLoading.Height;
pbLoadingUnit = pbLoadingWIDTH / 100;
Chances are you're getting the initial size of the pictureLoading during Load()... and not the actual width when it shows up and displayed in your form.
Also let tloading.Start() happens when you already get the appropriate size of you pictureLoading object.
you have to add this variable int pbmodal;
then calculate MOD of the unit
on form load add
pbmodal = pbLoadingWIDTH % 100;
when the completed is 100% add the modal.
Difference of division
`if (pbLoadingComplete > 100)
{
gLoading.FillRectangle(Brushes.DodgerBlue, new Rectangle(0, 0, (int)(pbLoadingComplete * pbLoadingUnit) + pbmodal, pbLoadingHEIGHT));
gLoading.DrawString(pbLoadingComplete-1 + "%", new Font("Segoe UI Semibold", pbLoadingHEIGHT / 2), Brushes.White, new PointF(pbLoadingWIDTH / 2 - pbLoadingHEIGHT, pbLoadingHEIGHT / 10));
pictureLoading.Image = bmpLoading;
}`

List of labels does not display in Picture Box

I have a problem with Labels in VisulaStudio.
The version of VisualStudio I use is 2012.
The problem is, I need to show a grid and label the lines. The code I wrote seams identical to the solution of a similar problem here. It doesn't give me any compiler errors, but the labels still do not display in the pictureBox.
private void aResize()
{
Size clientSize = this.ClientSize;
int hToDraw, wToDraw;
hToDraw = clientSize.Height - 2 * marginOfTab;
wToDraw = clientSize.Width - 2 * marginOfTab;
tabControl1.Size = new Size(wToDraw, hToDraw);
piB1.Size = new Size(wToDraw, hToDraw);
piB1.Image = new Bitmap(piB1.Size.Width, piB1.Size.Height);
using (Graphics g = Graphics.FromImage(piB1.Image))
{
g.FillRectangle(new SolidBrush(Color.LightGray), 0, 0, W, H);
Pen gridPen = new Pen(Color.White, 1f);
int hDrawingStep = hToDraw / 10 -1;
int wDrawingStep = wToDraw / 10 -1;
for (int local = 1; local < 11; local++)
{
g.DrawLine(gridPen, 0, hDrawingStep*local, wToDraw, hDrawingStep*local); //horizontal axix
g.DrawLine(gridPen, wDrawingStep*local, 0, wDrawingStep*local , hToDraw); //vertical axis
Label localLabel = new Label();
localLabel.Name = "la" + local;
localLabel.Visible = true;
localLabel.Text = (local*100).ToString();
localLabel.Location = new Point((int)local*hDrawingStep, (int)10);
labelList.Add(localLabel);
}
}
}
All variables which are not declared in the code above are declared earlier. I didn't want to paste in too much. Thanks for any suggestion.
You don't set any parent for your localLabel, so how could it be rendered? Try this right before adding your localLabel to your labelList:
//...
localLabel.Parent = piB1;
labelList.Add(localLabel);

How can i set the Form to be in the Center of the Screen?

I'm using this code:
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
//this.Location = new Point(form1_location_on_x, form1_location_on_y);
//this.StartPosition = FormStartPosition.CenterScreen;
Either the line
this.Location = new Point(form1_location_on_x, form1_location_on_y);
or the line
this.StartPosition = FormStartPosition.CenterScreen;
are working when I'm on my original screen resolution 1920x1080, but once I'm changing the resolution to 1024x768, the Form is on the right bottom corner not hidden I see it all but it's not in the center.
form1_location_on_x and on_y are:
form1_location_on_x = this.Location.X;
form1_location_on_y = this.Location.Y;
The question is what should I do to make it work on any other resolution like 1024x768 or any others? I tried many changes but nothing worked so far.
Size screenSize = Screen.PrimaryScreen.WorkingArea.Size;
Location = new Point(screenSize.Width / 2 - Width / 2, screenSize.Height / 2 - Height / 2);
Make sure that you set StartPosition = FormStartPosition.Manual;
Tested and working with 1920x1080 and 1024 x 768
You could calculate the top and left position of your form using this formula:
int formWidth = yourForm.Width;
int formHeight = yourForm.Height;
int screenH = (Screen.PrimaryScreen.WorkingArea.Top +
Screen.PrimaryScreen.WorkingArea.Height) / 2;
int screenW = (Screen.PrimaryScreen.WorkingArea.Left +
Screen.PrimaryScreen.WorkingArea.Width) / 2;
int top = screenH - formWidth / 2;
int left = screenW - formHeight / 2;
yourForm.Location = new Point(top, left);
Of course, these days, you have the problem of dual monitors.
I don't know if you want your form to appear always on the primary screen or you want the form appear in the current screen (the one where the form is currently displayed). In this second case you need to find where your form is displayed
private void CenterForm(Form yuorForm)
{
foreach(var s in Screen.AllScreens)
{
if(s.WorkingArea.Contains(yourForm.Location))
{
int screenH = s.WorkingArea.Height / 2;
int screenW = s.WorkingArea.Width / 2;
int top = (screenH + s.WorkingArea.Top) - formWidth / 2;
int left = (screenW + s.WorkingArea.Left) - formHeight / 2;
yourForm.Location = new Point(top, left);
break;
}
}
}
EDIT: Thanks to #alex I will complete the answer with the information on SystemEvents class
If you want to be notified by the system when the user suddenly change the resolution of your screen you could subscribe to the event SystemEvents.DisplaySettingsChanged (using Microsoft.Win32; needed)
SystemEvents.DisplaySettingsChanged += new EventHandler(SystemEvents_DisplaySettingsChanged);
and then handle the reposition of your form in the event
// This method is called when the display settings change.
void SystemEvents_DisplaySettingsChanged(object sender, EventArgs e)
{
RecenterForm(yourForm);
}
try using one of these after the resize:
this.CenterToScreen();
or
this.CenterToParent();
You can use StartPosition property of Form objects. It determines the position of a form. Set it's value to CenterScreen if you want your form to open in the center of the screen

How to set Location of another Control proportionally

My problem is : I have 2 Panels (panel1,panel2) where panel1.Size = new Size(200, 200); and Panel2.Size = new Size(600, 600); where both panel's have within a CustomControl which can get Dragged and change it Possition (szbControl1 ,szbControl2) .
My Question is ,how can i set szbControl2.Location properly (proportionally)based on szbControl1.Location where szbControl1 parent is panel1 and szbControl2 parent is panel2 ,like if i move the szbControl1 at bottom also szbControl2 should be at bottom.
So far i tried this :
private void sizeAbleCTR2_LocationChanged(object sender, EventArgs e)
{
int smallX = (sizeAbleCTR2.Location.X * panel1.Size.Width) / 100;
int smallY = (sizeAbleCTR2.Location.Y * panel1.Size.Height) / 100;
int largeX = (smallX * panel2.Width) / 100;
int largeY = (smallY * panel2.Height) / 100;
sizeAbleCTR1.Location = new Point(largeX,largeY);
}
like using the Percentage but it's not working .
The code you provided does not take into account the size of the szbControls. The ratio of the (location/the differences of the sizes) should be equal.
private void sizeAbleCTR2_LocationChanged(object sender, EventArgs e)
{
float srcHeightDiff = panel2.Height - sizeAbleCTR2.Height;
float dstHeightDiff = panel1.Height - sizeAbleCTR1.Height;
int locY = (int)(dstHeightDiff * (sizeAbleCTR2.Location.Y / srcHeightDiff));
float srcWidthDiff = panel2.Width - sizeAbleCTR2.Width;
float dstWidthDiff = panel1.Width - sizeAbleCTR1.Width;
int locX = (float)(dstWidthDiff * (sizeAbleCTR2.Location.X / srcWidthDiff));
sizeAbleCTR1.Location = new Point(locX, locY);
}

Performance issue when adding controls to a panel in C#

I am creating a panel and then adding some labels/buttons to it to form a grid. The issue is that if I add more than say 25x25 items to the panel, there is a terrible performance hit. I can resize the form ok but when I scroll the panel to see all the labels the program lags, the labels/buttons tear or flicker, and sometimes it can make the program unresponsive. I have tried adding the controls to a "DoubleBufferedPanel" that I created. This seems to have no effect. What else could I do? Sorry for such a large code listing. I didn't want to waste anyone's time.
namespace GridTest
{
public partial class Form1 : Form
{
private const int COUNT = 50;
private const int SIZE = 50;
private Button[,] buttons = new Button[COUNT, COUNT];
private GridPanel pnlGrid;
public Form1()
{
InitializeComponent();
pnlGrid = new GridPanel();
pnlGrid.AutoScroll = true;
pnlGrid.Dock = DockStyle.Fill;
pnlGrid.BackColor = Color.Black;
this.Controls.Add(pnlGrid);
}
private void Form1_Load(object sender, EventArgs e)
{
int x = 0;
int y = 0;
int offset = 1;
for (int i = 0; i < COUNT; i++)
{
for (int j = 0; j < COUNT; j++)
{
buttons[i, j] = new Button();
buttons[i, j].Size = new Size(SIZE, SIZE);
buttons[i, j].Location = new Point(x, y);
buttons[i, j].BackColor = Color.White;
pnlGrid.Controls.Add(buttons[i, j]);
x = x + SIZE + offset;
}
x = 0;
y = y + SIZE + offset;
}
}
}
}
Also, the GridPanel class:
namespace GridTest
{
public class GridPanel : Panel
{
public GridPanel()
: base()
{
this.DoubleBuffered = true;
this.ResizeRedraw = false;
}
}
}
If you must add controls at run time, based on some dynamic or changing value, you might want to consider creating an image on the fly, and capturing mouse click events on its picturebox. This would be much quicker and only have one control to draw rather than hundreds. You would lose some button functionality such as the click animation and other automatic properties and events; but you could recreate most of those in the generation of the image.
This is a technique I use to offer users the ability to turn on and off individual devices among a pool of thousands, when the location in a 2-dimensional space matters. If the arrangement of the buttons is unimportant, you might be better offering a list of items in a listview or combobox, or as other answers suggest, a datagridview with button columns.
EDIT:
An example showing how to add a graphic with virtual buttons. Very basic implementation, but hopefully you will get the idea:
First, some initial variables as preferences:
int GraphicWidth = 300;
int GraphicHeight = 100;
int ButtonWidth = 60;
int ButtonHeight = 20;
Font ButtonFont = new Font("Arial", 10F);
Pen ButtonBorderColor = new Pen(Color.Black);
Brush ButtonTextColor = new SolidBrush(Color.Black);
Generating the image:
Bitmap ControlImage = new Bitmap(GraphicWidth, GraphicHeight);
using (Graphics g = Graphics.FromImage(ControlImage))
{
g.Clear(Color.White);
for (int x = 0; x < GraphicWidth; x += ButtonWidth)
for (int y = 0; y < GraphicHeight; y += ButtonHeight)
{
g.DrawRectangle(ButtonBorderColor, x, y, ButtonWidth, ButtonHeight);
string ButtonLabel = ((GraphicWidth / ButtonWidth) * (y / ButtonHeight) + x / ButtonWidth).ToString();
SizeF ButtonLabelSize = g.MeasureString(ButtonLabel, ButtonFont);
g.DrawString(ButtonLabel, ButtonFont, ButtonTextColor, x + (ButtonWidth/2) - (ButtonLabelSize.Width / 2), y + (ButtonHeight/2)-(ButtonLabelSize.Height / 2));
}
}
pictureBox1.Image = ControlImage;
And responding to the Click event of the pictureBox:
// Determine which "button" was clicked
MouseEventArgs em = (MouseEventArgs)e;
Point ClickLocation = new Point(em.X, em.Y);
int ButtonNumber = (GraphicWidth / ButtonWidth) * (ClickLocation.Y / ButtonHeight) + (ClickLocation.X / ButtonWidth);
MessageBox.Show(ButtonNumber.ToString());
I think you won't be able to prevent flickering having 625 buttons (btw, windows) on the panel. If such layout is mandatory for you, try to use the DataGridView, bind it to a fake data source containing the required number of columns and rows and create DataGridViewButtonColumns in it. This should work much more better then your current result ...

Categories

Resources