I have a 2d array of LEDButton : Button.
I want to find out the index [x,y] of each buttons the user clicks.
I am new to Windows Forms and not used to working outside of a console so these GUI objects are very unfamiliar to me.
private void Form1_Load(object sender, EventArgs e)
{
LEDButton[,] leds = new LEDButton[11, 11];
for (int x = 0; x < leds.GetUpperBound(0); x++)
{
listBox1.Items.Add("x = " + x);
for (int y = 0; y < leds.GetUpperBound(1); y++)
{
leds[x, y] = new LEDButton()
{
Name = String.Format("Button{0}{1}", x, y),
TabIndex = 40 * x + y,
Location = new Point(40 * y + 50, 40 * x + 50)
};
leds[x, y].pointx = x;
leds[x, y].pointy = y;
}
}
// add buttons to controls
for (int x = 0; x < leds.GetUpperBound(0); x++)
{
for (int y = 0; y < leds.GetUpperBound(1); y++)
{
Controls.Add(leds[x, y]);
leds[x, y].Click += Form1_Click;
}
}
public class LEDButton : Button
{
public const int LEDWidth = 20;
public const int LEDHeight = 20;
public int pointx = 0;
public int pointy = 0;
public LEDButton()
{
BackColor = Color.FromArgb(0, 64, 0);
ForeColor = Color.Black;
FlatStyle = FlatStyle.Flat;
Size = new Size(LEDWidth, LEDHeight);
UseVisualStyleBackColor = false;
this.Click += LEDButton_Click; //throws error
}
}
I think I found my answer with the help of Lars.
Code should be
private void Form1_Click(object? sender, EventArgs e)
{
LEDButton btn = sender as LEDButton;
listBox2.Items.Add(btn.Name);
}
Related
I set the points and when the points of the same color form a square, I draw a polygon. But when a new square is formed, the old one disappears.
can you tell me how to make sure that when drawing a new polygon, the old one does not disappear?
in the checkpoint() function, I check whether there is a square of points of the same color and return e coordinates for drawing.
public partial class Form1 : Form
{
private Class1 Class1 = new Class1();
private CellState currentPlayer = CellState.Red;
public const int SIZE = 11;
public const int Icon_Size = 30;
public Form1()
{
InitializeComponent();
}
//ставит точки
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
var p = new Point((int)Math.Round(1f * e.X / Icon_Size), (int)Math.Round(1f * e.Y / Icon_Size));
if (Class1[p] == CellState.Empty)
{
Class1.SetPoint(p, currentPlayer);
currentPlayer = Class1.Inverse(currentPlayer);
Invalidate();
}
}
//рисуем
private void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.ScaleTransform(Icon_Size, Icon_Size);
//рисуем сеточку
using (var pen = new Pen(Color.Gainsboro, 0.1f))
{
for (int x = 1; x < SIZE; x++)
e.Graphics.DrawLine(pen, x, 1, x, SIZE - 1);
for (int y = 1; y < SIZE; y++)
e.Graphics.DrawLine(pen, 1, y, SIZE - 1, y);
}
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//рисуем точки
using (var brush = new SolidBrush(Color.White))
for (int x = 1; x < Form1.SIZE; x++)
for (int y = 1; y < Form1.SIZE; y++)
{
var p = new Point(x, y);
var cell = Class1[p];
if (cell != CellState.Empty)
{
brush.Color = StateToColor(cell);
e.Graphics.FillEllipse(brush, x - 0.2f, y - 0.2f, 0.4f, 0.4f);
}
}
using (var PenP = new Pen(Color.Black, 0.1f))
using (var brush = new SolidBrush(Color.White))
{
Class1.CheckPoint();
int i = Class1.CheckPoint()[0];
int j = Class1.CheckPoint()[1];
int cp = Class1.CheckPoint()[2];
if (cp == 1)
{
PenP.Color = Color.Red;
brush.Color = Color.IndianRed;
Point[] a = { new Point(i, j), new Point(i + 1, j), new Point(i + 1, j + 1), new Point(i, j + 1) };
e.Graphics.FillPolygon(brush, a);
e.Graphics.DrawPolygon(PenP, a);
}
if (cp == 2)
{
PenP.Color = Color.Blue;
brush.Color = Color.RoyalBlue;
Point[] a = { new Point(i, j), new Point(i + 1, j), new Point(i + 1, j + 1), new Point(i, j + 1) };
e.Graphics.FillPolygon(brush, a);
e.Graphics.DrawPolygon(PenP, a);
}
}
}
//условие смены цвета под ход игрока
Color StateToColor(CellState state, byte alpha = 255)
{
var res = state == CellState.Blue ? Color.Blue : Color.Red;
return Color.FromArgb(alpha, res);
}
}
I want to make a tiles based scrolling game in Visual Studio C# using forms. I know its not the best platform for this but those are set parameters. I suppose the easiest way to think of the end program is like pokemon 2d top down world scrolling.
I can create a 2d array of picture boxes and allocated images to them based on a text 2d array of tile ids. I can scroll the picture boxes and when they reach a certain place, jump back to the original location and display a shifted tile.
My issue is adding controls, it only adds a column rather than the full grid. I have tried using tables but with the same problem.
Has anyone done this type of large world scroller using VSC# and forms? Are there any tutorials or suggestions? Thanks.
EDIT - Code added'
public Form1()
{
InitializeComponent();
TableLayoutPanel wholescreen = new TableLayoutPanel();
wholescreen.Location = new System.Drawing.Point(0,0);
wholescreen.Size = new System.Drawing.Size(200,200);
wholescreen.RowCount = 2;
wholescreen.ColumnCount = 2;
Controls.Add(wholescreen);
PictureBox item = new PictureBox();
item.Size = new System.Drawing.Size(50, 50);
item.ImageLocation = "C:\\Users\\i.price\\Documents\\1.png";
for (int x = 0; x < 2; x++)
{
for (int y = 0; y < 2; y++)
{
item.Left = x * 50;
item.Top = y * 50;
wholescreen.Controls.Add(item,x,y);
}
}
}
'
another way i tried....'
int WIDTH = 3;
int HEIGHT = 3;
PictureBox[] grid = new PictureBox[9];
//PictureBox[,] grid = new PictureBox[3, 3];
//int[,] level1 = new int[2, 2] { { 1, 2 }, { 3, 4 } };
int playerx = 0;
public Form1()
{
InitializeComponent();
int y = 0;
int x = 0;
for (int cntr = 0; cntr < HEIGHT*WIDTH; cntr++)
{
if ((cntr % HEIGHT) == 0)
{
x++;
y = 0;
}
grid[cntr] = new PictureBox();
grid[cntr].Left = x * 50;
grid[cntr].Top = y * 50;
grid[cntr].ImageLocation = "C:\\Users\\i.price\\Documents\\1.png";
Controls.Add(grid[cntr]);
}
}
'
I think you are just creating one square and moving it around. Try...
private void Method2()
{
TableLayoutPanel wholescreen = new TableLayoutPanel();
wholescreen.BackColor = Color.AliceBlue;
wholescreen.Location = new System.Drawing.Point(0, 0);
wholescreen.Size = new System.Drawing.Size(200, 200);
wholescreen.RowCount = 2;
wholescreen.ColumnCount = 2;
Controls.Add(wholescreen);
PictureBox item;
// item.ImageLocation = "C:\\Users\\i.price\\Documents\\1.png";
for (int x = 0; x < 2; x++)
{
for (int y = 0; y < 2; y++)
{
item = new PictureBox();
item.Size = new System.Drawing.Size(50, 50);
item.BackColor = Color.Blue;
//item.Left = 0;
//item.Top = 0;
wholescreen.Controls.Add(item, x, y);
}
}
}
I'm beginner in programming and I want to create a little "game" with Panels.
(Later maybe I'll change for PictureBox, but for now it's OK)
Code:
private void Form1_Load(object sender, EventArgs e)
{
int size = 20;
int quantity = 10;
Random rnd = new Random();
for (int y = 0; y < quantity; y++)
{
for (int x = 0; x < quantity; x++)
{
Color randomColor = Color.FromArgb(
rnd.Next(256), rnd.Next(256), rnd.Next(256)
);
Panel panel = new Panel
{
Size = new Size(size, size),
Location = new Point(x * size, y * size),
BorderStyle = BorderStyle.FixedSingle,
BackColor = randomColor
};
Controls.Add(panel);
//panel.Click += Panel_Click;
}
}
}
I have two questions:
How can I set 5 pixel distance to each Panel from each other?
Should I place these panel creation in the constructor? I see people prefer that.
You have to include additional 5 pixels padding into Location:
...
int padding = 5;
...
Location = new Point(x * (size + padding), y * (size + padding))
...
Let's extract a method:
private void CreateGameField() {
int size = 20;
int padding = 5;
int quantity = 10;
Random rnd = new Random();
for (int y = 0; y < quantity; ++y)
for (int x = 0; x < quantity; ++x)
new Panel() {
Size = new Size(size, size),
Location = new Point(x * (size + padding), y * (size + padding)),
BorderStyle = BorderStyle.FixedSingle,
BackColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256)),
Parent = this, // instead of Controls.Add(panel);
};
}
Then
private void Form1_Load(object sender, EventArgs e) {
CreateGameField();
}
FromLoad event handler is a good place to create the game field; if you want you can place CreateGameField() in the constructor, but put it after InitializeComponent():
public Form1() {
InitializeComponent();
CreateGameField();
}
I want create a control that draws a table in panel . My code is:
public class PanelZ : System.Windows.Forms.Panel
{
public static void Draw()
{
Panel p = new Panel();
p.Width = 200;
p.Height = 200;
Graphics g = p.CreateGraphics();
Pen mypen = new Pen(Brushes.Black, 1);
Font myfont = new Font("tahoma", 10);
int lines = 9;
float x = 0;
float y = 0;
float xSpace = p.Width / lines;
float yspace = p.Height / lines;
for (int i = 0; i < lines + 1; i++)
{
g.DrawLine(mypen, x, y, x, p.Height);
x += xSpace;
}
x = 0f;
for (int i = 0; i < lines + 1; i++)
{
g.DrawLine(mypen, x, y, p.Width, y);
y += yspace;
}
}
..but it dosen't draw a table; so what should I do?
This will work. But the numbers ought to be properties, as should the pen and then some.. Also: Properties ought to start with an uppercase letter.
public class PanelZ : System.Windows.Forms.Panel
{
public PanelZ() // a constructor
{
Width = 200;
Height = 200;
DoubleBuffered = true;
lines = 9;
}
public int lines { get; set; } // a property
protected override void OnPaint(PaintEventArgs e) // the paint event
{
base.OnPaint(e);
Graphics g = e.Graphics;
Pen mypen = new Pen(Brushes.Black, 1);
Font myfont = new Font("tahoma", 10);
float x = 0;
float y = 0;
float xSpace = Width / lines;
float yspace = Height / lines;
for (int i = 0; i < lines + 1; i++)
{
g.DrawLine(mypen, x, y, x, Height);
x += xSpace;
}
for (int i = 0; i < lines + 1; i++)
{
g.DrawLine(mypen, 0, y, Width, y);
y += yspace;
}
}
}
At work in VS:
Note that this only colors pixels. There is no useful grid there, just pixels with color.. So, if you actually want to use the Font you define you will have to calculate the coodordinates and the bounding boxes.
How do I use a background worker in this for loop?
int tmax = 10;
int xmax = newbitmap.Width;
int ymax = newbitmap.Height;
for (int t = 0; t <= tmax; t += 1)
{
for (int x = 0; x < xmax; x++)
{
for (int y = 0; y < ymax; y++)
{
if ((x / xmax) > (t / tmax))
{
Color originalco = newbitmap2.GetPixel(x, y);
outp.SetPixel(x, y, originalco);
}
else
{
Color originalco3 = newbitmap.GetPixel(x, y); ;
outp.SetPixel(x, y, originalco3);
}
}
pictureBox1.Image = outp;
}
}
This loop is a wipe transition from right to left, but it doesn't display the transition.
That because the backgroundWorker works in a different thread. You can use backgroundworker.ReportProgress(0, outp)
So:
You need to register to the event BackgroundWorker.ProgressChanged from the events window in Vistual Studio, or with this line:
backgroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
The method:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
var outp = (Bitmap)e.UserState;
prictureBox.Image = outp;
}
Your code sould be then:
int tmax = 10;
int xmax = newbitmap.Width;
int ymax = newbitmap.Height;
for (int t = 0; t <= tmax; t += 1)
{
for (int x = 0; x < xmax; x++)
{
for (int y = 0; y < ymax; y++)
{
if ((x / xmax) > (t / tmax))
{
Color originalco = newbitmap2.GetPixel(x, y);
outp.SetPixel(x, y, originalco);
}
else
{
Color originalco3 = newbitmap.GetPixel(x, y); ;
outp.SetPixel(x, y, originalco3);
}
}
backgroundWorker1.ReportProgress(t, outp);
}
}
First, you should use direct pixel manipulation as described here: http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx
Then, you should use an array as lookup for all your threads which line has already been drawn and which hasn't. The threads look for a new line in this array and then draw it. But remember to lock the lookup array!
Your Do work method would look something like this: -
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
Bitmap newbitmap = (Bitmap)e.Argument;
int tmax = 10;
int xmax = newbitmap.Width;
int ymax = newbitmap.Height;
for (int t = 0; t <= tmax; t += 1)
{
for (int x = 0; x < xmax; x++)
{
for (int y = 0; y < ymax; y++)
{
if ((x / xmax) > (t / tmax))
{
Color originalco = newbitmap2.GetPixel(x, y);
outp.SetPixel(x, y, originalco);
}
else
{
Color originalco3 = newbitmap.GetPixel(x, y); ;
outp.SetPixel(x, y, originalco3);
}
}
pictureBox1.Image = outp;
}
}
bgWorker.ReportProgress(0,outp);
}
Then when your worker reports progress, it would raise the following event where you can safely update the UI:
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//UPDATE YOUR UI HERE
}
You can use the ReportProgress method of Background Worker to update the UI.
Read more