dynamically changing picture box - c#

i dynamically create several picture box, and EventHandler. when user click on pictureBox, the program should delete tрis item. (the item that the user selected)
i try do
for (int i = 1; i <= sunduki; i++)
{
PictureBox PBObj = new PictureBox();
PBObj.Location = new System.Drawing.Point(i * 100, 101);
PBObj.Name = "pictureBox" + i.ToString();
PBObj.Size = new System.Drawing.Size(108, 80);
PBObj.TabIndex = i;
PBObj.BackgroundImage = Image.FromFile(#"syndyk1.jpg");
PBObj.BackgroundImageLayout = ImageLayout.Zoom;
PBObj.Click += new System.EventHandler(pb_Click);
PB.Add(PBObj);
Controls.Add(PB[PB.Count - 1]);}
and in pb_click
private void pb_Click(object sender, EventArgs e)
{ PB[this].Visible = false; }
but i have an error. (PB is the list with pictureBox)

The sender argument will be the object that has been clicked, in this case it is the PictureBox object.
private void pb_Click(object sender, EventArgs e)
{
var pb = sender as PictureBox;
if(pb != null)
{
pb.Visible = false;
}
}
Note: This doesn't delete the picture box, but makes it not visible. Controls deletion is handled by the disposal of the form.

Related

How to assign the name of pictureBox in foreach loop

I have tried using Tag, Name, Text, IndexOf. Every time, I get the first name and that's it. Here is the code:
// Perform scanning
for (;;)
{
List<System.Drawing.Image> images = this.ScannerDevice.PerformScan().ToList();
// Show picture in window
this.Invoke((MethodInvoker)delegate
{
this.FrontImage = images[0];
foreach (System.Drawing.Image image in images)
{
PictureBox pf = new PictureBox();
pf.SizeMode = PictureBoxSizeMode.StretchImage; pf.Height = 150; pf.Width = 170;
pf.Image = image;
pf.Click += new EventHandler(pictureClicked);
flowLayoutPanel1.Controls.Add(pf);
pf.Tag=flowLayoutPanel1.Controls.Count;
}
ScanFinishedEventArgs eventArgs = new ScanFinishedEventArgs { AcceptScan = true };
this.ScanFinished?.Invoke(this, eventArgs);
label1.Text = Convert.ToString(flowLayoutPanel1.Controls.Count);
});
}
void pictureClicked(object sender, EventArgs e)
{
if (selectedPicture != null)
selectedPicture.BorderStyle = BorderStyle.None;
selectedPicture = (PictureBox)sender;
selectedPicture.BorderStyle = BorderStyle.FixedSingle;
pictureBox1.Image = selectedPicture.Image;
label2.Text = Convert.ToString(pf.Tag);
}
Also I would like to use that name later to be displayed in another label when I click on the certain picturebox.
Also I have tried using anonymous types but unable to use it with image objects. What am I doing wrong?
I've just done this and it seems to work. 3 images are added, each named according to the index value at the time. A label is set showing the image count. The picture clicked handler displays the name in a message box when the image is clicked.
private void button1_Click(object sender, EventArgs e)
{
int index = 0;
foreach (Image image in images.Images)
{
PictureBox pf = new PictureBox();
pf.SizeMode = PictureBoxSizeMode.StretchImage;
pf.Height = 50;
pf.Width = 50;
pf.Click += new EventHandler(PictureClicked);
pf.Name = index.ToString();
pf.Image = image;
flowLayoutPanel1.Controls.Add(pf);
index++;
}
lblImagecount.Text = index.ToString();
}
private void PictureClicked(object sender, EventArgs e)
{
MessageBox.Show(((PictureBox) sender).Name);
}

Making labels in array change backcolor on click using C# in Windows Forms

How can I change the BackColor of a label in an array when I click on it? Since there are multiple elements, I cannot manually activate each event for each individual label.
for (int i = 0; i < 361; i++)
{
board[i] = new Label();
board[i].Parent = pictureBox1;
board[i].Location = new Point(x, y);
board[i].Name = "label" + i;
board[i].BackColor = Color.Black;
//set size of labels
board[i].Size = new Size(30, 30);
//initialize click event handler
this.board[i].Click += new System.EventHandler(this.labelClick);
}
private void labelClick (object sender, EventArgs e)
{
foreach (Label i in board)
{
if (iteration % 2 == 0)
{
i.BackColor = Color.Black;
iteration++;
}
else if(iteration % 2 == 1)
{
i.BackColor = Color.White;
iteration++;
}
}
}
There are a few ways you can handle this. One way is to wire each Labels Click event up to the same event:
this.label1.Click += new System.EventHandler(this.label_Click);
this.label2.Click += new System.EventHandler(this.label_Click);
this.label3.Click += new System.EventHandler(this.label_Click);
In the label_Click event you can set the BackColor of each label OR just the one you clicked on.
// This will set each label's BackColor to Red.
private void label_Click(object sender, EventArgs e)
{
foreach (Label label in labelArray)
{
label.BackColor = Color.Red;
}
}
// This will set just the clicked on Label's BackColor to Red.
private void label_Click(object sender, EventArgs e)
{
Label label = sender as Label;
if (label != null)
{
label.BackColor = Color.Red;
}
}
var labels = new[]
{
// labels here
};
foreach (var label in labels)
{
label.Click += (sender, args) =>
{
var lbl = sender as Label;
Debug.Assert(lbl != null);
lbl.BackColour = Colors.Pink;
};
}

C# Drawing Lines with TextBox

I have an application where I can add a textBox on the screen and move it.
When I add more than two textBox, I double-click on top of two textbox and a line connects both.
My question is: How to make the line move along with the textBox?
code below:
public partial class principal : Form
{
int posMouseFormX, posMouseFormY;
int posMouseTXT_X, posMouseTXT_Y;
int posActTXT_X, posActTXT_Y;
bool txtPressionado = false;
int qntClick;
Pen myPen = new Pen(System.Drawing.Color.DarkGreen, 1);
Graphics Tela;
List<TextBox> listaNós = new List<TextBox>();
List<Point> origem = new List<Point>();
List<Point> destino = new List<Point>();
Point ponto1, ponto2;
ContextMenuStrip menu;
public principal()
{
InitializeComponent();
menu = new ContextMenuStrip();
menu.Items.Add("Remover");
menu.ItemClicked += new ToolStripItemClickedEventHandler(contextMenuStrip1_ItemClicked);
}
//TextBox event when the mouse moves over the TXT
private void txtMover_MouseMove(object sender, MouseEventArgs e)
{
TextBox textBox = sender as TextBox;
posMouseFormX = textBox.Location.X + e.Location.X;
posMouseFormY = textBox.Location.Y + e.Location.Y;
if (txtPressionado == true) moverTxt(textBox);
}
//Retrieve the X and Y coordinates where clicked within the component.
private void txtMover_MouseDown(object sender, MouseEventArgs e)
{
posMouseTXT_X = e.Location.X;
posMouseTXT_Y = e.Location.Y;
txtPressionado = true;
}
private void txtMover_MouseUp(object sender, MouseEventArgs e)
{
txtPressionado = false;
}
private void moverTxt(TextBox a)
{
a.Location = new System.Drawing.Point(posMouseFormX - posMouseTXT_X, posMouseFormY - posMouseTXT_Y);
posActTXT_X = a.Location.X;
posActTXT_Y = a.Location.Y;
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
}
//insert new TextBox
private void sb_Inserir_No_Click(object sender, EventArgs e)
{
TextBox noFilho = new TextBox();
noFilho = new System.Windows.Forms.TextBox();
noFilho.Location = new System.Drawing.Point(379, 284);
noFilho.Size = new System.Drawing.Size(100, 30);
noFilho.TabIndex = 20;
noFilho.Text = "";
noFilho.BackColor = Color.White;
posActTXT_X = noFilho.Location.X;
posActTXT_Y = noFilho.Location.Y;
this.Controls.Add(noFilho);
noFilho.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
noFilho.DoubleClick += new System.EventHandler(this.textBox1_Click);
noFilho.MouseUp += new System.Windows.Forms.MouseEventHandler(txtMover_MouseUp);
noFilho.MouseDown += new System.Windows.Forms.MouseEventHandler(txtMover_MouseDown);
noFilho.MouseMove += new System.Windows.Forms.MouseEventHandler(txtMover_MouseMove);
noFilho.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
noFilho.ContextMenuStrip = menu;
}
//event to resize the txt on the screen as the content.
private void textBox1_TextChanged(object sender, EventArgs e)
{
TextBox textBox1 = sender as TextBox;
Size size = TextRenderer.MeasureText(textBox1.Text, textBox1.Font);
textBox1.Width = size.Width + 10;
textBox1.Height = size.Height;
}
//Event to control the connection between two give us when double click on the textbox
private void textBox1_Click(object sender, EventArgs e)
{
TextBox textBox1 = sender as TextBox;
int meio = textBox1.Size.Width / 2;
Tela = CreateGraphics();
qntClick = qntClick + 1;
if (this.qntClick == 1)
{
origem.Add(ponto1);
ponto1 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
}
if (this.qntClick == 2)
{
qntClick = 0;
destino.Add(ponto2);
ponto2 = new Point(textBox1.Location.X + meio, textBox1.Location.Y);
DesenhaSeta(Tela, ponto1, ponto2);
}
}
//draw arrow between two TXT
void DesenhaSeta(Graphics Tela, Point x, Point y)
{
myPen.StartCap = LineCap.Triangle;
myPen.EndCap = LineCap.ArrowAnchor;
Tela.DrawLine(myPen, x, y);
}
private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
ContextMenuStrip menu = sender as ContextMenuStrip;
//recuperando o controle associado com o contextmenu
Control sourceControl = menu.SourceControl;
DialogResult result = MessageBox.Show("Tem Certeza que deseja remover o nó selecionado?", "Excluir", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if(result == DialogResult.Yes)
{
sourceControl.Dispose();
}
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// Determine whether the key entered is the F1 key. Display help if it is.
if (e.KeyCode == Keys.Space)
{
TextBox textBox1 = sender as TextBox;
novoNó tela = new novoNó(textBox1.Text);
tela.Show();
}
}
}
Each control, TextBox included has a Move, event. Put an Invalidate() call there!
The lines should be drawn in the Paint event of the container that holds the TextBoxes, probably the Form; if it is the Form indeed call this.Invalidate().
Please move the line drawing code out of the DoubleClick event into the Paint event or else the lines will not persist, say minimize/maximize events or other situation, when the system has to redraw the application!
You probably will need to create a data structure to maintain information about which TextBox-pairs need to be connected, maybe a List<Tuple> or a List<someStructure>. This would get filled/modified in the DoubleClick event, then call this.Invalidate() and in the Form.Paint you have a foreach loop over the list of TextBox-pairs..
If you are drawing on the Form do make sure to turn DoubleBuffered on!
Update: To compare the reults here is a minimal example the expects two TextBoxes on a Form:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
this.DoubleBuffered = true;
pairs.Add(new Tuple<Control, Control>(textBox1, textBox2));
}
List<Tuple<Control, Control>> pairs = new List<Tuple<Control, Control>>();
Point mDown = Point.Empty;
private void Form2_Paint(object sender, PaintEventArgs e)
{
foreach (Tuple<Control, Control> cc in pairs)
drawConnection(e.Graphics, cc.Item1, cc.Item2);
}
void drawConnection(Graphics G, Control c1, Control c2)
{
using (Pen pen = new Pen(Color.DeepSkyBlue, 3f) )
{
Point p1 = new Point(c1.Left + c1.Width / 2, c1.Top + c1.Height / 4);
Point p2 = new Point(c2.Left + c2.Width / 2, c2.Top + c2.Height / 4);
G.DrawLine(pen, p1, p2);
}
}
void DragBox_MouseDown(object sender, MouseEventArgs e)
{
mDown = e.Location;
}
void DragBox_MouseMove(object sender, MouseEventArgs e)
{
TextBox tb = sender as TextBox;
if (e.Button == MouseButtons.Left)
{
tb.Location = new Point(e.X + tb.Left - mDown.X, e.Y + tb.Top - mDown.Y);
}
}
void DragBox_MouseUp(object sender, MouseEventArgs e)
{
mDown = Point.Empty;
}
private void DragBox_Move(object sender, EventArgs e)
{
this.Invalidate();
}
}

Set backcolor to the button which user clicked

Hi all I am creating some button dynamically, and when user click on the button I need to set the BackColor for the selected button to some highlighted color, as per the code what I have written it is applying color for every button, instead of that I need to apply color for the user clicked button
My code for creating buttons is as follows
for(int i=0;i<5;i++)
{
Button btyDynamic = new Button();
btyDynamic .Click += new EventHandler(btyDynamic _Click);
btyDynamic .AutoSizeMode = AutoSizeMode.GrowAndShrink;
btyDynamic .AutoSize = true;
btyDynamic .Text = i.ToString();
btyDynamic .Tag = i.ToString();;
}
protected void btyDynamic(object sender, EventArgs e)
{
Button btn= sender as Button;
string strTag= btn.Tag.ToString();
switch(strTag)
{
case "0":
btn.BackColor=Color.LightSteelBlue;
break;
// Like this I am writing, now when in Case2 I need to remove the color of the first button and to show the backcolor of second button
}
}
You could store the last button selected and then reset the BackColor:
private Button _lastButtonSelected = null;
protected void btyDynamic(object sender, EventArgs e)
{
// Set new button back color
Button btn = sender as Button;
if(btn != null)
{
btn.BackColor = Color.LightSteelBlue;
}
// Reset last button color
if(_lastButtonSelected != null)
{
_lastButtonSelected.BackColor = ...; // Put default back color here
}
_lastButtonSelected = btn;
}
If you want the BackColor to remain LightSteelBlue if you click the same button twice, you just need to check that the _lastButtonSelected != btn as well.
you could make a foreach for all buttons, and remove background for all button not equal to sender. Suppose to save all buttons into an array (_AllButtons). you could write some code like this:
Button btn= sender as Button;
foreach(var currentButton in _AllButtons) {
if(currentButton !=btn) {
currentButton.BackColor=Color.Transparent;
}
}
A possible algorithm would be:
create the buttons once as you already do and bind the click event to one handler
in the click handler first reset all buttons to the standard background color
in the click handler find the currently clicked button using switch as you already do and set the color of this button
Sample code:
Action resetButtonColor = () =>
{
button1.BackColor = Colors.Red;
button2.BackColor = Colors.Red
button3.BackColor = Colors.Red;
};
resetButtonColor();
var selected = Colors.Green;
switch(strTag)
{
case "1": button1.BackColor = selected;
case "2": button2.BackColor = selected;
case "3": button3.BackColor = selected;
}
Then You must assign to the click event of this one button explicetely.
All others could have this handler, but the one button should not, because it is too generic handled in this way.
You can try this:
Color highLite = Color.Black;
public Form1()
{
InitializeComponent();
for (int i = 0; i < 20; i++)
{
Button b = new Button();
b.Text = i.ToString();
b.Tag = null;
b.Click += b_Click;
flowLayoutPanel1.Controls.Add(b);
}
}
void b_Click(object sender, EventArgs e)
{
Button b = sender as Button;
if (b == null)
return;
b.BackColor = highLite;
// clear backcolors
foreach (Control c in flowLayoutPanel1.Controls)
if (c != b)
c.BackColor = SystemColors.Control;
}
Make sure you are only setting backcolors of controls you want to set. Make the tag have something unique to tell you that you want to change it.
private Color offColor = Color.Red;
private Color onColor = Color.Blue;
private String btyPrefix = "bty";
private void btyDynamic_click(object sender, EventArgs e)
{
Control control = (Control)sender;
// enumerate this.Controls, but if they go into a different container, enumerate over that
this.Controls.OfType<Control>()
.Where(c => ((String)c.Tag).Contains(btyPrefix))
.ToList<Control>()
.ForEach(c =>
{
if (control == c)
c.BackColor = onColor;
else
c.BackColor = offColor;
}
);
}
private void Form1_Load(object sender, EventArgs e)
{
Button btyDontChange = new Button();
btyDontChange.AutoSize = true;
btyDontChange.AutoSizeMode = AutoSizeMode.GrowAndShrink;
btyDontChange.Text = "x";
btyDontChange.Tag = "something";
btyDontChange.Location = new Point(0, 0);
this.Controls.Add(btyDontChange);
for (int i = 0; i < 5; i++)
{
Button btyDynamic = new Button();
btyDynamic.Click += new EventHandler(btyDynamic_click);
btyDynamic.AutoSizeMode = AutoSizeMode.GrowAndShrink;
btyDynamic.AutoSize = true;
btyDynamic.Text = i.ToString();
btyDynamic.Tag = btyPrefix + i.ToString();
btyDynamic.Location = new Point((i+1) * 50, 0);
btyDynamic.BackColor = offColor;
this.Controls.Add(btyDynamic);
}
}

How to determine click event for userdefine control array

I have created an Array of UserControls which have 1 PictureBox and 1 Button. Now I want to know which Button is pressed from the Array of UserControl.
UserControl u=new UserControl[20];
for (int j = 0; j < 20; j++)
{
u[j] = new UserControl();
u[j].BringToFront();
flowLayoutPanel1.Controls.Add(u[j]);
u[j].Visible = true;
u[j].button1.Click+=new EventHandler(sad);
}
private void sad(object sender, EventArgs e)
{
//how to determine which button from the array of usercontrol is pressed?
}
The sender parameter contains the Control instance that generated the event.
something like this:
private void sad(object sender, EventArgs e) {
var buttonIndex = Array.IndexOf(u, sender);
}
This should do close to what you want. I can modify as needed to suit your case.
FlowLayoutPanel flowLayoutPanel1 = new FlowLayoutPanel();
void LoadControls()
{
UserControl[] u= new UserControl[20];
for (int j = 0; j < 20; j++)
{
u[j] = new UserControl();
u[j].BringToFront();
flowLayoutPanel1.Controls.Add(u[j]);
u[j].Visible = true;
u[j].button1.Click +=new EventHandler(sad);
}
}
private void sad(object sender, EventArgs e)
{
Control c = (Control)sender;
//returns the parent Control of the sender button
//Could be useful
UserControl parent = (UserControl)c.Parent; //Cast to appropriate type
//Check if is a button
if (c.GetType() == typeof(Button))
{
if (c.Name == <nameofSomeControl>) // Returns name of control if needed for checking
{
//Do Something
}
}
//Check if is a Picturebox
else if (c.GetType() == typeof(PictureBox))
{
}
//etc. etc. etc
}
I think this gets you what you want:
if (sender is UserControl)
{
UserControl u = sender as UserControl();
Control buttonControl = u.Controls["The Button Name"];
Button button = buttonControl as Button;
}

Categories