How to add a click event on dynamically created imagebox? - c#

I created around 12 picbox and label dynamically im able to retrieve data in the picbox and label from SQL. the picbox image in binary format and the row where imagestore in table also contain image title's in database.
The problem is that I want to add a click_event on picbox. ASAP I click on picbox a textbox1. text which I created must show the title of the image which is store in the SQL.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace library
{
public partial class showingmore : Form
{
private string passvalue;
public string passval
{
get { return passvalue; }
set { passvalue = value; }
}
public showingmore()
{
InitializeComponent();
}
MemoryStream ms;
byte[] photo_aray;
private void showingmore_Load_1(object sender, EventArgs e)
{
OleDbConnection con = new OleDbConnection("Provider=SQLOLEDB;User ID=sa;Password =12345678; Initial Catalog=library; server=raj; TRUSTED_CONNECTION=true;");
OleDbDataAdapter Adap = new OleDbDataAdapter("select * from movie ", con);
textBox1.Text = passvalue;
DataSet ds = new DataSet();
Adap.Fill(ds);
//textBox1.Text = ds.Tables[0].Rows[15][0].ToString(); // the working way to use ds to fill data
//textBox1.Text = ds.Tables[0].Rows[1];
//int icount = ds.Tables[0].Rows.Count;
//textBox1.Text = icount.ToString();
/**** Creating Label's and Picture Box ****/
int n = 12; // total time for running loop.
int j = 14; // y-axis co-ordinate label
int k = 479; // x-axis co-ordinate label
int l = 18; // y-axis co-ordinate label
// Creating label through loop's.
for (int i = 0; i < n; i++)
{
//Create label
Label labels = new Label();
PictureBox picbox = new PictureBox();
labels.Text = ds.Tables[0].Rows[i][0].ToString();
if (i <= 5)
{
//Position label on screen
labels.Location = new Point(j, k);
j = j + 228;
// Label text color
labels.ForeColor = Color.Gainsboro;
}
else
{
k = 782; // x-axis co-ordinate
labels.Location = new Point(l, k);
l = l + 228;
labels.ForeColor = Color.Gainsboro;
}
this.Controls.Add(labels);
}
n = 12; // total time for running loop.
j = 18; // y-axis co-ordinate
k = 246; // x-axis co-ordinate
l = 18; // y-axis co-ordinate
// Creating PictureBox through loop's.
for (int i = 0; i < n; i++)
{
//Create PictureBox
PictureBox picbox = new PictureBox();
picbox.Image = null;
if (ds.Tables[0].Rows[i][14] != System.DBNull.Value)
{
photo_aray = (byte[])ds.Tables[0].Rows[i][14];
MemoryStream ms = new MemoryStream(photo_aray);
picbox.Image = Image.FromStream(ms);
}
if (i <= 5)
{
//Position PictureBox on screen
picbox.Location = new Point(j, k);
picbox.Size = new Size(161, 220);
picbox.BackColor = Color.Gainsboro;
j = j + 228;
}
else
{
k = 543; // y-axis co-ordinate
picbox.Location = new Point(l, k);
picbox.Size = new Size(161, 220);
picbox.BackColor = Color.Gainsboro;
l = l + 228;
}
this.Controls.Add(picbox);
}
}
}
}

To get the click event for your dynamically created PictureBox, you can simple subscribe to the click event when you create it;
private void createPicBoxes()
{
for (int i = 0; i <= 12; i++)
{
PictureBox picBox = new PictureBox();
picBox.Click += picBox_Click;
}
}
static void picBox_Click(object sender, EventArgs e)
{
//do your stuff here which handles generically all of your picture boxes clicks.
}
In short, subscribing to the controls events like such means that whenever that action is performed, in your case a click event, the attached method will fire off.

Put this somewhere in the loop before adding the picbox to the Controls collection:
picbox.MouseClick += picbox_MouseClick;
Then, implement the handler for the click somewhere in your showingmore class:
private void picbox_MouseClick(object sender, MouseEventArgs e)
{
// Your code here.
}

Add event handler to the PictureBox when creating it.
Something like below
PictureBox picbox = new PictureBox();
picbox.Click += new EventHandler(this.picbox_Click);
void picbox_Click(object sender, System.EventArgs e)
{
//your code...
}

Related

How do I know which card is clicked?

I am making a Memory game in WPF and C#. It is going good till now. When I click (turn) 2 cards, I want my code to register that and when the images don't match then I want the back.png image to come back.
Now my code counts how many times there has been clicked but I don't know how to make the cards "turn" again and to make them go away when 2 images match. I have 16 images, 1 and 9 are pairs, 2 and 10 are pairs, and so on.
My plan was to make a method that is called resetCards().
This is my MainWindow.cs:
public partial class MainWindow : Window
{
private MemoryGrid grid;
public MainWindow()
{
InitializeComponent();
}
private void start_Click(object sender, RoutedEventArgs e)
{
grid = new MemoryGrid(GameGrid, 4, 4);
start.Visibility = Visibility.Collapsed;
}
This is my MemoryGrid.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace SpellenScherm
{
public class MemoryGrid
{
private Grid grid;
private int rows, cols;
public MemoryGrid(Grid grid, int rows, int cols)
{
this.grid = grid;
this.rows = rows;
this.cols = cols;
InitializeGrid();
AddImages();
}
private void InitializeGrid()
{
for (int i = 0; i < rows; i++)
{
grid.RowDefinitions.Add(new RowDefinition());
}
for (int i = 0; i < cols; i++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition());
}
}
private void AddImages()
{
List<ImageSource> images = GetImagesList();
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
Image back = new Image();
back.Source = new BitmapImage(new Uri("/images/back.png", UriKind.Relative));
back.MouseDown += new System.Windows.Input.MouseButtonEventHandler(CardClick);
back.Tag = images.First();
images.RemoveAt(0);
Grid.SetColumn(back, col);
Grid.SetRow(back, row);
grid.Children.Add(back);
}
}
}
static int numberOfClicks = 0;
private void resetCards()
{
}
private void CardClick(object sender, MouseButtonEventArgs e)
{
if (numberOfClicks < 2)
{
Image card = (Image)sender;
ImageSource front = (ImageSource)card.Tag;
card.Source = front;
numberOfClicks++;
}
if (numberOfClicks == 2)
{
resetCards();
numberOfClicks = numberOfClicks -2;
}
}
public List<ImageSource> GetImagesList()
{
List<ImageSource> images = new List<ImageSource>();
List<string> random = new List<string>();
for (int i = 0; i < 16; i++)
{
int imageNR = 0;
Random rnd = new Random();
imageNR = rnd.Next(1, 17);
if (random.Contains(Convert.ToString(imageNR)))
{
i--;
}
else
{
random.Add(Convert.ToString(imageNR));
ImageSource source = new BitmapImage(new Uri("images/" + imageNR + ".png", UriKind.Relative));
images.Add(source);
}
}
return images;
}
}
}
You can try this approach - keep two fields in your MemoryGrid class one for each of the images which show their front faces. (Let's call them Image1 and Image2). Then you can keep a track of which cards are flipped in the whole grid and pass them as arguments to your resetCards method as follows:
private void CardClick(object sender, MouseButtonEventArgs e)
{
if (numberOfClicks < 2)
{
Image card = (Image)sender;
ImageSource front = (ImageSource)card.Tag;
card.Source = front;
if(this.Image1 == null){
Image1 = card;
}
else if(this.Image2 == null){
Image2 = card;
}
numberOfClicks++;
}
if (numberOfClicks == 2)
{
resetCards(Image1, Image2);
numberOfClicks = numberOfClicks -2;
}
}

c# Dynamic panel on mouse

I am making a N*M size SUDOKU game. Every number are on a button.
When the program start all button is empty and I would like if I click to a button it is make a little panel on it with buttons for each number to choose one.
private void adatB_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int[] hely = button.Tag.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToArray();
Panel szamok = new Panel
{
Location = MousePosition,
Size = new Size(100, 100)
};
Controls.Add(szamok);
TableLayoutPanel minitabla = new TableLayoutPanel
{
Dock = DockStyle.Fill,
ColumnCount = szorzat,
RowCount = szorzat,
};
for (int i = 0; i < szorzat; i++)
{
minitabla.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
minitabla.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
}
szamok.Controls.Add(minitabla);
Button[,] szamokB = new Button[meret[0], meret[1]];
int d = 1;
for (int i = 0; i < meret[0]; i++)
{
for (int j = 0; j < meret[1]; j++)
{
szamokB[i, j] = new Button();
szamokB[i, j].Tag= hely[0]+","+hely[1];
szamokB[i, j].Text = d.ToString();
szamokB[i, j].Dock = DockStyle.Fill;
szamokB[i, j].Click += szamokB_Click;
minitabla.Controls.Add(szamokB[i, j], i, j);
d++;
}
}
}
private void szamokB_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int[] hely = button.Tag.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(Int32.Parse).ToArray();
adatB[hely[0], hely[1]].Text = button.Text;
}
The problem with it when I click a button the pane isn't created.
meret[0] variable is the N, meret[1] is M, adatB is the arry of buttons with the positons in tag.
And If I choosed the number how can I close that panel?
First of all, you should calculate the mouseposition correctly.
From MSDN:
Gets the position of the mouse cursor in screen coordinates.
You should use something like this:
Location = new Point(MousePosition.X - this.Location.X, MousePosition.Y - this.Location.Y)
You will probably need this, to bring your panel to the front:
Controls.Add(szamok);
szamok.BringToFront();
To close the panel you can store the chooser panel and you can remove it from the controls later, use something like this:
public partial class Form1 : Form
{
private Panel myPanel = null;
private void adatB_Click(object sender, EventArgs e)
{
...
Panel szamok = new Panel
{
Location = new Point(MousePosition.X - this.Location.X, MousePosition.Y - this.Location.Y),
Size = new Size(100, 100)
};
if (this.myPanel != null)
{
this.Controls.Remove(this.myPanel);
}
this.myPanel = szamok;
Controls.Add(szamok);
szamok.BringToFront();
...
}
private void szamokB_Click(object sender, EventArgs e)
{
if (this.myPanel != null)
{
this.Controls.Remove(this.myPanel);
this.myPanel = null;
}
...
}
}

couldn't change active tabPage with button c#

I have a MetroTabControl named mtcNewExpTabControl with four pages(mtpSettings, mtpNewExp, mtpTempImages, mtpCompareImages). I am starting New Experiment on mtpNewExp page and get image after clicking "StartExperiment" button. User can get many images. After completion of experiment, I add images to imageList1.Images.
When I click on the mtpTempImages tabPage mtcNewExpTabControl_SelectedIndexChanged triggered and images are displayed with combobox named with imageList1.Images.Keys[i]. I can show many combobox and picturebox pairs on mtpTempImages.
On mtpTempImages there is also a mtbCompareImages button. User can check checkboxes next to the picturebox named same with checboxName. After checking all the checkboxes needed to compared, user will click on the "Compare Images" button. I want to change active tabPage to mtpCompareImages without clicking on the tab. mtbCompareImages button should be enough for that. I can show images on mtpTempImages but I could not succeded that on mtpCompareImages tabpage. Active tabPage also do not change to mtpCompareImages tabPage. What should I do?
List<MetroCheckBox> cbxTempImages = new List<MetroCheckBox>();
List<MetroCheckBox> cbxCompareImages = new List<MetroCheckBox>();
List<PictureBox> pbxTempImages = new List<PictureBox>();
List<PictureBox> pbxCompareImages = new List<PictureBox>();
private void mtbCompareImages_Click(object sender, EventArgs e)
{
for (int i = 0; i < cbxTempImages.Count(); i++)
{
if (cbxTempImages[i].Checked == true)
{
imageListChecked.Images.Add(pbxTempImages[i].Name, pbxTempImages[i].Image);
}
}
this.mtcNewExpTabControl.SelectedTab = mtpCompareImages;
}
private void mtcNewExpTabControl_SelectedIndexChanged(object sender, EventArgs e)
{
if((MetroTabPage)this.mtcNewExpTabControl.SelectedTab == mtpTempImages)
{
for (int i = 0; i < imageList1.Images.Count; i++)
{
cbxTempImages.Add(new MetroCheckBox());
cbxTempImages[i].Name = imageList1.Images.Keys[i].ToString();
cbxTempImages[i].Size = new Size(15, 15);
cbxTempImages[i].BackColor = Color.Transparent;
cbxTempImages[i].Location = new Point(x, y);
//PictureBox pic = new PictureBox();
pbxTempImages.Add(new PictureBox());
pbxTempImages[i].Name = imageList1.Images.Keys[i].ToString();
pbxTempImages[i].Image = imageList1.Images[i];
pbxTempImages[i].SizeMode = PictureBoxSizeMode.StretchImage;
pbxTempImages[i].Location = new Point(x + 15, y);
x += 120;
if (x > this.pnlTempImages.Width - 120)
{
x = 10; y += 100;
}
this.pnlTempImages.Controls.Add(cbxTempImages[i]);
this.pnlTempImages.Controls.Add(pbxTempImages[i]);
}
}
else if((MetroTabPage)this.mtcNewExpTabControl.SelectedTab == mtpCompareImages)
{
x = 10; y = 10;
for (int i = 0; i < imageListChecked.Images.Count; i++)
{
cbxCompareImages.Add(new MetroCheckBox());
//MetroCheckBox cbxCI = new MetroCheckBox();
cbxCompareImages[i].Name = imageListChecked.Images.Keys[i].ToString();
cbxCompareImages[i].Size = new Size(15, 15);
cbxCompareImages[i].BackColor = Color.Transparent;
cbxCompareImages[i].Location = new Point(x, y);
//PictureBox picCI = new PictureBox();
pbxCompareImages.Add(new PictureBox());
pbxCompareImages[i].Name = imageListChecked.Images.Keys[i].ToString();
pbxCompareImages[i].Image = imageListChecked.Images[i];
pbxCompareImages[i].SizeMode = PictureBoxSizeMode.StretchImage;
pbxCompareImages[i].Location = new Point(x + 15, y);
x += 120;
if (x > this.pnlCompareImages.Width - 120)
{
x = 10; y += 100;
}
this.pnlCompareImages.Controls.Add(cbxCompareImages[i]);
this.pnlCompareImages.Controls.Add(pbxCompareImages[i]);
}
}
InitializeComponent();
}

Dynamically added labels only show one

Ok so I decided to add controls to a panel on form_load based on labels in an array. Below is my code, but no matter how many files I upload through the button listener and reload this form, it only displays one label and nothing more. Why is it only displaying one? I have added a breakpoint and verified that the count does go up to 2, 3, etc.
Code:
public partial class Attachments : Form
{
ArrayList attachmentFiles;
ArrayList attachmentNames;
public Attachments(ArrayList attachments, ArrayList attachmentFileNames)
{
InitializeComponent();
attachmentFiles = attachments;
attachmentNames = attachmentFileNames;
}
private void Attachments_Load(object sender, EventArgs e)
{
ScrollBar vScrollBar1 = new VScrollBar();
vScrollBar1.Dock = DockStyle.Right;
vScrollBar1.Scroll += (sender2, e2) => { pnl_Attachments.VerticalScroll.Value = vScrollBar1.Value; };
pnl_Attachments.Controls.Add(vScrollBar1);
Label fileName;
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
pnl_Attachments.Controls.Add(fileName);
}
}
private void btn_AddAttachment_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
string fileName = openFileDialog1.FileName;
attachmentFiles.Add(fileName);
attachmentNames.Add(Path.GetFileName(fileName));
this.Close();
}
}
}
This is because the labels are all stacking on top of each other. You will need to specify a top for each one or use an auto-flow panel.
Adding the following line after creating the new label will ensure all labels are visible (you may have to adjust the multiplier depending on your font):
fileName.Top = (i + 1) * 22;
As competent_tech stated the labels are stacking on top of each other, but another approach is to modify the location value of the label.The benefit to this is you can control the absolute location of the label.
fileName.Location = new Point(x, y);
y += marginAmount;
x is the vertical position on the form and y is the horizontal location on the form. Then all that has to be modified is the amount of space you want in between each label in the marginAmount variable.
So in this for loop
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
pnl_Attachments.Controls.Add(fileName);
}
You could modify it to this:
for (int i = 0; i < attachmentNames.Count; i++)
{
fileName = new Label();
fileName.Text = attachmentNames[i].ToString();
fileName.Location = new Point(x, y);
y += marginAmount;
pnl_Attachments.Controls.Add(fileName);
}
Then all you have to do is define x, y, and the marginAmount.

picturebox array click event

Good day, I'm a beginner in programming and I want to create a simple chess game. I'm using windows forms in C#. I have no problem with declaring and initializing the array, but how do I set click events for each of the picureboxes? Before I was doing it in VS properties box. Here is my initializing code.
public void picbnox()
{
picturbox[0, 0] = new PictureBox();
picturbox[0, 0].Visible = true;
picturbox[0, 0].Location = new Point(15, 30);
picturbox[0, 0].Size = new Size(65, 65);
picturbox[0, 0].BorderStyle = BorderStyle.FixedSingle;
this.Controls.Add(picturbox[0, 0]);
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
picturbox[i, j] = new PictureBox();
picturbox[i, j].Visible = true;
picturbox[i, j].Location = new Point(i *70, j *70);
picturbox[i, j].Size = new Size(65, 65);
picturbox[i, j].BorderStyle = BorderStyle.FixedSingle;
this.Controls.Add(picturbox[i, j]);
}
}
}
You can add the picture box click event like this:
picturebox[0, 0].Click += picturebox_Click; // in your form load event, this is only for one picture box
void picturebox_Click(object sender, EventArgs e)
{
// do whatever you want to do when the picture box is clicked
}

Categories