I want to implement Nine Men's Morris Game.
I have a board with 24 pictureboxes and on the left and right side, 9 red pictureboxes and 9 green pictureboxes.
I want to add them in a list:
List<PictureBox> ls = new List<PictureBox>();
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Name = "pictureBox" + i;
ls.Add(p);
}
}
is it ok?
and is it possible to do something like this: I want to click on one of the 24 pictureboxes, and make the background of that picturebox to become one time green and one time red?
I mean recursive function or something like that that can recognize when i click on a picturebox, search in the list for that picturebox and changes his backcolor?
You don't need any pictureBox list here.
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Click += p_Click;
//of course, somecontrol.Controls.Add(p);
//for ex: this.Controls.Add(p);
}
-
void p_Click(object sender, EventArgs e)
{
((PictureBox)sender).BackColor = Color.Green;
}
EDIT
It seems you are trying to add an event handler to all pictureBoxes
**parentControl**.Controls.OfType<PictureBox>()
.ToList().ForEach(p => p.Click+=p_Click);
I assume the list of 24 PictureBoxes is supposed to represent the points on a nine man morris board where the player's men can be positioned.
I4V is right that all you need to do is add a click handler to each picture box. If you want to have the background alternate between green and red, keep your original list, but add the click handler in it
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Name = "pictureBox" + i;
p.Click += p_Click; // <----------
ls.Add(p);
}
And modify i4v's click handler to use the current background color to determine the new background color.
void p_Click(object sender, EventArgs e)
{
PictureBox p = (PictureBox)sender);
p.BackColor = p.BackColor == Color.Green ? Color.Red : Color.Green;
}
A couple of other points.
You don't set an initial background color, so it will be the default color until clicked on, when it will be set to Green (as Green isn't the default background color).
Why name your pictureboxes w/ their List index + 1? Why not just use the List index and the natural C# iteration from 0: for (int i = 0; i < 24; i++)?
The method you have outlined would not work, however there is another way to do the same thing using the sender object passed into the event handler:
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 1; i <= 24; i++)
{
PictureBox p = new PictureBox();
p.Name = "pictureBox" + i;
p.Click += PictureBox_Click;
}
}
void PictureBox_Click(object sender, EventArgs e)
{
PictureBox event_picturebox = (PictureBox)sender;
event_picturebox.BackColor = Color.White;
}
You just have to map every picture box you want to run this event to the same event, the event will then be able to perform actions on this pictureBox because a reference to it was passed in.
If you already have the picture boxes defined in the form, you just need to do something like:
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Click += PictureBox_Click;
pictureBox2.Click += PictureBox_Click;
// and keep going
// OR
// this is a bit dangerous if you don't want ALL
// your picture boxes to have this event
// also assumes that you know picturebox1 exists.
foreach (object f in this.Controls)
{
if (f.GetType().Equals(pictureBox1.GetType()))
{
((PictureBox)f).Click += button_Click;
}
}
}
Related
So I'm trying to figure out how to have the click of a button swap between 3 background colors in a windows application form. Managed to make it swap between 2, but struggling to move up to three.
The result of ~30 minutes of trying everything that came to mind: https://prnt.sc/1rka67i
The 2 color variation: https://prnt.sc/1rkakrm
In this case you could modify property of Form's backgroud on button click event like:
private void button1_Click(object sender, EventArgs e)
{
this.BackColor = Color.White; //for example
}
If you want to swap between 3 colors you could try like:
int counter = 0;
private void button1_Click(object sender, EventArgs e)
{
counter++;
if(counter == 1)
this.BackColor = Color.White; //for example
if(counter == 2)
this.BackColor = Color.Black; //for example
if(counter == 3){
this.BackColor = Color.Gray; //for example
counter = 0;
}
}
I'm creating dynamically a bunch of PictureBoxes by clicking a button in my form, but I'm not clear on how can I add an event to each one. Here's my idea
private void insertarBloqueToolStripMenuItem_Click(object sender, EventArgs e)
{
pbA = new PictureBox{
Name = "picturebox" + contB,
Image = new Bitmap(bloque),
Size = pbA.Image.Size,
};
pbA.MouseDown += new MouseEventHandler(pbA_MouseDown);
pbA.MouseUp += new MouseEventHandler(pbA_MouseUp);
pbA.MouseMove += new MouseEventHandler(pbA_MouseMove);
pbA.Paint += new PaintEventHandler(pbA_Paint);
pbA.Cursor = Cursors.Hand;
listaBloques.Add(pbA);
panel1.Controls.Add(pbA);
}
That's what I got, can you help me with that idea? And How can I can create a single method to move one PictureBox on the list? Thank you
Your idea is quite good!
But it would be enought to write (but yours works also fine):
pbA.Paint += pbA_Paint;// generally: ... += methodName;
And you have to create the event itselve. For example:
void pbA_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
//do some cool stuff!
}
If it is painted on any of the PictureBoxes then this method will be called. If you want to know which PictureBox has been painted on then simply write:
void pbA_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
PictureBox picBox_active = sender as PictureBox;
//do some cool stuff!
}
And for making one single method to move just one PictureBox you could give the desired object as a parameter:
void move(PictureBox picBox, int moveX, int moveY)
{
picBox.Location = new Point(moveX, moveY);
}
And you can call this method by:
PictureBox picBoxTest = new PictureBox();
move(picBoxTest, 5, 5);
And to make it clearer with an example:
void pbA_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
PictureBox picBox_active = sender as PictureBox;
move(picBox_active, 5, 5);
}
The PictureBox that has been painted will be moved to the coordinates 5,5.
Background
I have created 8 linklabels which are created using a loop which gets data from a database.
Each record fills a linklabel.
How ever how can I distinguish what linklabel has been clicked on?
Code
for (int i = 0; i <= rowCount - 1; i++)
{
LinkLabel Linklabel = new LinkLabel();
Linklabel.Text = ds.Tables[0].Rows[i]["code"].ToString();
Linklabel.Height = 15;
Linklabel.Width = 50;
Linklabel.AutoSize = true;
Linklabel.Location = new Point(10, (i + 1) * 30);
tabControl1.TabPages[0].Controls.Add(Linklabel);
// Add an event handler to do something when the links are clicked.
Linklabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
tabControl1.SelectedTab = tabPage2;
}
When clicking on any of the 8 linklabels that are drawn the same thing will happen.
What I would like to happen?
When clicking on any of the linklabels I would like to change a label.text to what the contents of the clicked linklabel was.
For example
If the first linklabel.text=("one") is clicked on label1.text becomes one.
If the second linkedlabel.text=("two") is clicked on label1.text becomes two.
You could use the sender argument in the callback which will point to the actual LinkLabel being clicked:
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
label1.text = ((LinkLabel)sender).Text;
}
Im trying to make an event of 8 picturebox together this is my code, but when i click it put always the same image, the event its been doing twice, i put a message on the event of pictureboxes and it appears twice.
public partial class Form1 : Form
{
int jug=1;
PictureBox[] PicBox = new PictureBox[9];
Image circu = Image.FromFile("Circulo1.png");
Image cruz = Image.FromFile("Cruz1.png");
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
PicBox[0] = this.pcb0;
PicBox[1] = this.pcb1;
PicBox[2] = this.pcb2;
PicBox[3] = this.pcb3;
PicBox[4] = this.pcb4;
PicBox[5] = this.pcb5;
PicBox[6] = this.pcb6;
PicBox[7] = this.pcb7;
PicBox[8] = this.pcb8;
for (int i = 0; i < 9; i++)
{
PicBox[i].Click += new System.EventHandler(PictureBoxes_Click);
}
}
private void PictureBoxes_Click(object sender, EventArgs e)
{
PictureBox p = (PictureBox)sender;
if (jug == 1)
{
jug = 2;
p.Image = cruz;
}
else
{
jug = 1;
p.Image = circu;
}
}
Try refreshing the pictureboxes with built in function. If that not solve the problem, set picturebox image property to null, then refresh and set the image you want.
Or you try setting click event on the design page of your ide, bind it the same function(in this case Pictureboxes_click)
There is no reason to enter the event twice. Your code actually works. I think maybe you have some other controls in your form which uses the same event. Just make sure that the event is being used only by the pictureboxes.
Another thing to do: Put breakpoint at the event and see what controls appear as sender. This will help you fix your problem.
Use pictureboxes' Tag property to understand which one is entering the event:
for (int i = 0; i < 9; i++)
{
PicBox[i].Tag = i;
}
When code enters the event, you can look at p.Tag to see which one triggered the event.
You have only 2 different images with single instances. Try to clone the images, so each PictureBox gets it's own instance of the image:
private void PictureBoxes_Click(object sender, EventArgs e)
{
PictureBox p = (PictureBox)sender;
if (jug == 1)
{
jug = 2;
p.Image = (Image)cruz.Clone();
}
else
{
jug = 1;
p.Image = (Image)circu.Clone();
}
}
Or you can replace the cloning by using the "FromFile"-method, which automatically creates the new instances:
p.Image = Image.FromFile("Circulo1.png");
I'm playing around abit with winforms and its controls and just discovered how to do custommade buttonclicks. However, there is a problem. I've got a loop, that's looping through a list of elements, and if a condition appears - I'm creating a button that will pop up a gridview.
public void draw(ref Panel inputPanel) //draws the eventline
{
int stepCounter = 0;
for (int i = 0; i < DaysList.Count-1; i++)
{
Button b1;
if (DaysList[i].Elements.Count > max)
{
b1 = new Button(); //Create the box
b1.Width = 120;
b1.Height = 40; //Set width and height
b1.Location = new Point(stepCounter + 35, 70); //Location
inputPanel.Controls.Add(b1); //
b1.Text = "Check event date in grid";
b1.Show();
b1.BringToFront();
b1.Click += new EventHandler((sender, e) => btn_Click(sender, e, DaysList[i].Elements));
stepCounter += 200;
}
}
}
That was my method for creating the buttons and a click event for the when my condition appears. The function that is passed to the eventhandler looks like this:
public void btn_Click(object sender, EventArgs e, List<EventElement> inputElems)
{
Button button = sender as Button;
DataGridForm window = new DataGridForm(inputElems);
window.Show();
}
public class EventElement
{
public EventElement()
{
}
public int Count{get;set;}
public string Date{get;set;}
}
The clickpart of the event is fine but whenever i click the spawned buttons, I get the wrong data into the gridview. As an example: The loop has created four buttons for me and they are presented on a straight line on the form. But whenever i click one of the buttons - dosnt matter which one of them, the button always return the data of the last spawned button. A more clear example: lets say we have the list inputElems looks like this:
inputElems[0].Count -> 2644
inputElems[1].Count -> 2131
inputElems[2].Count -> 8467
inputElems[3].Count -> 5462
When i now click the second button, the input to the second buttons parameter list should have the values (sender, e, 2131), right? but for some reason, the last argument gets the same like the 4th element in the list, even though i call the secondly created button.
I figured that it has something to do with me always calling the last added button_click to the eventhandler of the button, if so, how do I call different clicks from the EventHandler?
Instead of passing inputElems with the EventHandler, you can use Tag.
E.g. use:
b1.Tag=i;
Then in your click event handler:
public void btn_Click(object sender, EventArgs e)
{
Button button = sender as Button;
DataGridForm window = new DataGridForm(DaysList[int.Parse(button.Tag.ToString())].Elements);
window.Show();
}
The problem is that the for loop is out of scope, and thus unable to provide you with the data you're looking for. A more straight forward approach might be something like this:
public void draw(ref Panel inputPanel) //draws the eventline
{
int stepCounter = 0;
for (int i = 0; i < DaysList.Count-1; i++)
{
Button b1;
if (DaysList[i].Elements.Count > max)
{
b1 = new Button(); //Create the box
b1.Width = 120;
b1.Height = 40; //Set width and height
b1.Location = new Point(stepCounter + 35, 70); //Location
inputPanel.Controls.Add(b1); //
b1.Text = "Check event date in grid";
b1.Show();
b1.BringToFront();
b1.Tag = DaysList[i].Elements;
b1.Click += btn_Click;
stepCounter += 200;
}
}
}
and then in btn_Click, do this:
public void btn_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int inputElems = (List<EventElement>)button.Tag;
DataGridForm window = new DataGridForm(inputElems);
window.Show();
}