How do I apply events to a dynamically created picturebox? [duplicate] - c#

I am getting a list of pictures from a directory and storing the filenames in a List<String>. I then loop through each of these and create a PictureBox for each of them, I then add the same click event to each. The controls are in a FlowLayoutPanel
foreach(String file in this._files){
PictureBox box = new PictureBox();
box.Height = 50;
box.Width = 50;
box.ImageLocation = file;
box.SizeMode = PictureBoxSizeMode.Zoom;
box.Click += this.PictureClick;
this.flowLayoutPanel1.Controls.Add(box);
}
private void PictureClick(object sender, EventArgs e){
// how do I get the one that has been clicked and set its border color
}
How do I get the one that has been clicked and set its border color?

sender is the PictureBox that was clicked:
private void PictureClick(object sender, EventArgs e) {
PictureBox oPictureBox = (PictureBox)sender;
// add border, do whatever else you want.
}

The sender parameter is indeed your PictureBox, downcast to object. Access it this way:
var pictureBox = sender as PictureBox;
Drawing a border around it could not be so easy as you will have to either override the OnPaint method of the PictureBox, either handle the Paint event.
You can use this class to draw a black thin border around your image.
public class CustomBorderPictureBox : PictureBox
{
public bool BorderDrawn { get; private set; }
public void ToggleBorder()
{
BorderDrawn = !BorderDrawn;
Invalidate();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
if (BorderDrawn)
using (var pen = new Pen(Color.Black))
pe.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
}
}

Related

Dynamic click event on PictureBox

I am getting a list of pictures from a directory and storing the filenames in a List<String>. I then loop through each of these and create a PictureBox for each of them, I then add the same click event to each. The controls are in a FlowLayoutPanel
foreach(String file in this._files){
PictureBox box = new PictureBox();
box.Height = 50;
box.Width = 50;
box.ImageLocation = file;
box.SizeMode = PictureBoxSizeMode.Zoom;
box.Click += this.PictureClick;
this.flowLayoutPanel1.Controls.Add(box);
}
private void PictureClick(object sender, EventArgs e){
// how do I get the one that has been clicked and set its border color
}
How do I get the one that has been clicked and set its border color?
sender is the PictureBox that was clicked:
private void PictureClick(object sender, EventArgs e) {
PictureBox oPictureBox = (PictureBox)sender;
// add border, do whatever else you want.
}
The sender parameter is indeed your PictureBox, downcast to object. Access it this way:
var pictureBox = sender as PictureBox;
Drawing a border around it could not be so easy as you will have to either override the OnPaint method of the PictureBox, either handle the Paint event.
You can use this class to draw a black thin border around your image.
public class CustomBorderPictureBox : PictureBox
{
public bool BorderDrawn { get; private set; }
public void ToggleBorder()
{
BorderDrawn = !BorderDrawn;
Invalidate();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
if (BorderDrawn)
using (var pen = new Pen(Color.Black))
pe.Graphics.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);
}
}

How to hide/show the background image of pictureBox?

I have a pictureBox with an image inside.
I want, when i click on a button the image should hide and click again to show the image.
In the pictureBox, using paint event i am drawing some lines.
So if im doing pictureBox1.Refresh(); it will draw the lines. I want that if i click on a button the image will not display on/off.
pictureBox1 = null; or pictureBox1.Image.Dispose(); doesn't work it's showing me big red x with white background.
To hide it:
pictureBox.Visible = false;
To hide/show it in a click event:
void SomeButton_Click(Object sender, EventArgs e)
{
pictureBox.Visible = !pictureBox.Visible;
}
For toggling the image in your PictureBox you can create a 1 pixel bitmap and assign it to the picture box when you want hide your image, then assign your image back again. I am a little unclear of what the second part of your question is asking, any drawing in the picturebox's Paint Event will remain unless you exclude it in the Paint Event based on some Condition. If you want to draw a line in the box an toggle it on/off from a button see my second example.
i.e.
public partial class Form1 : Form
{
Bitmap nullBitmap = new Bitmap(1, 1); // create a 1 pixel bitmap
Bitmap myImage = new Bitmap("Load your Image Here"); // Load your image
bool showImage; // boolean variable so we know what image is assigned
public Form1()
{
InitializeComponent();
pictureBox1.Image = myImage;
showImage = true;
}
private void button1_Click(object sender, EventArgs e)
{
if (showImage)
{
pictureBox1.Image = nullBitmap;
showImage = false;
}
else
{
pictureBox1.Image = myImage;
showImage = true;
}
}
}
Second Example
public partial class Form1 : Form
{
bool showLines;
public Form1()
{
InitializeComponent();
showLines = true;
}
private void button1_Click(object sender, EventArgs e)
{
if (showLines)
{
showLines = false;
pictureBox1.Invalidate();
}
else
{
showLines = true;
pictureBox1.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if(showLines)
e.Graphics.DrawLine(Pens.Purple, 0, 0, 100, 100);
}
}
picturebox1.BackgroundImage = null

2D Array of RectangleShapes

I am developing a very rudimentary drawing program: A 2D grid comprised of multiple RectangleShapes, around 20x30 pixels each, which when clicked change color based on user RGB input, which works just fine:
Color SelectedColor = new Color();
private void Pixel_1_1_Click(object sender, EventArgs e) // on Rectangle click
{
Pixel_1_1.FillColor = SelectedColor; // change to currently desired color.
}
Since the number of squares is rising dramatically, I'm looking for a way to arrange the "pixel" rectangles into a 2D array. (I really don't want to have to make a Pixel_Click method for every single Rectangle on the screen!) Hoping eventually to be able to call something like:
private void Pixel_[x]_[y]_Click(object sender, EventArgs e)
{
Pixel_[x]_[y].FillColor = SelectedColor;
}
My friends suggest the use of an anonymous delegate, but I don't understand how to fully use one to solve my problem.
What would be the best way to generate a 2D array of rectangles in a C# Windows Form? And once generated, how can I access them with a single method for variant values of x and y?
While you are probably correct in thinking of each rectangle as an object, it probably isn't correct to think of each rectangle as a windows control, especially since you have so many of them.
So try creating your own rectangle object:
public class MyRect {
public Color FillColor { get; set; }
public Rectangle Rectangle { get; set; }
public MyRect(Rectangle r, Color c) {
this.Rectangle = r;
this.FillColor = c;
}
}
Now you just need to keep a list of your objects and paint on a single Panel control (or PictureBox) all of your rectangles:
private List<MyRect> myRectangles = new List<MyRect>();
public Form1() {
InitializeComponent();
myRectangles.Add(new MyRect(new Rectangle(10, 10, 64, 16), Color.Blue));
myRectangles.Add(new MyRect(new Rectangle(20, 48, 16, 64), Color.Red));
}
private void panel1_Paint(object sender, PaintEventArgs e) {
foreach (MyRect mr in myRectangles) {
using (SolidBrush sb = new SolidBrush(mr.FillColor)) {
e.Graphics.FillRectangle(sb, mr.Rectangle);
}
}
}
To handle the "click" event of the rectangles, you just handle the MouseDown or MouseClick event of your container control and determine yourself which rectangle is being clicked on:
void panel1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
foreach (MyRect mr in myRectangles) {
if (mr.Rectangle.Contains(e.Location)) {
ChangeColor(mr, Color.Green);
}
}
panel1.Invalidate();
}
}
private void ChangeColor(MyRect mr, Color newColor) {
mr.FillColor = newColor;
}
If you want to maintain the rectangles as components on screen then you can assign all of them the same click event, the click event will have a little dropdown to pick an existing event. To know which recantangle was clicked use the sender parameter ((Pixel)sender).FillColor = SelectedColor;
For ease I would recommend using something like a panel and drawing rectangles on it, That means you only have a single click event to deal with. So now your question becomes "How do I draw a grid of rectangles on a panel" and "How do I know which rectangle was clicked"
So for the first part you could use this not the very efficient way.
Create a class which stores the information about your pixels
class MyPixel
{
public Color PixelColour;
public Rectangle Bounds;
}
Keep a list of them in memory
List<MyPixels> MyGrid = new List<MyPixels>();
then in the onpaint event of the panel Draw the pixels on the panel
foreach(MyPixel Pixel in MyGrid)
{
using(Brush B = new SolidBrush(Pixel.PixelColor))
{
e.Graphics.DrawRectangle(B, Pixel.Bounds);
}
}
Now in the click event you'll need to know which pixel was clicked
foreach(MyPixel Pixel in MyGrid)
{
if (Pixel.Bounds.Contains(e.Location))
{
PixelClicked(Pixel);
}
}
I believe you're going about this the wrong way. What you want to do is to draw directly into a bitmap. Here is some code that uses a PictureBox to allow the user to draw into it.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Pen _pen;
private bool _mouseDown;
private int _startX;
private int _startY;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
_pen = new Pen(Color.Black);
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
_mouseDown = true;
_startX = e.X;
_startY = e.Y;
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
_mouseDown = false;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (_mouseDown)
{
using (var graphics = Graphics.FromImage(pictureBox1.Image))
{
graphics.DrawLine(_pen, _startX, _startY, e.X, e.Y);
_startX = e.X;
_startY = e.Y;
}
pictureBox1.Invalidate();
}
}
}
}
This is the normal method to write a painting app and is quite performant as well. You can also easily save, write new tools or manipulate images better in this way.

How to do a background for a label will be without color?

I want to add a label to my form , and I want it without any color- I want just it's text to be visible, I don't find this option in the label's properties, can anyone help me please?
Do you want to make the label (except for the text) transparent? Windows Forms (I assume WinForms - is this true) doesn't really support transparency. The easiest way, sometimes, is Label's Backcolor to Transparent.
label1.BackColor = System.Drawing.Color.Transparent;
You will run into problems though, as WinForms really doesn't properly support transparency. Otherwise, see here:
http://www.doogal.co.uk/transparent.php
http://www.codeproject.com/KB/dotnet/transparent_controls_net.aspx
http://www.daniweb.com/code/snippet216425.html
Setting the parent of a usercontrol prevents it from being transparent
Good luck!
If you picture box in the background then use this:
label1.Parent = pictureBox1;
label1.BackColor = Color.Transparent;
Put this code below InitializeComponent(); or in Form_Load Method.
Ref: https://www.c-sharpcorner.com/blogs/how-to-make-a-transparent-label-over-a-picturebox1
You are right. but here is the simplest way for making the back color of the label transparent
In the properties window of that label select Web.. In Web select Transparent
:)
this.label1.BackColor = System.Drawing.Color.Transparent;
Let's view 2 possible cases.
Background is a color.
Double-Click the form background in VS constructor. Then, write this code:
/*
This code will set all your object's background color to the same as the form.
This should be written in the body of <FormName>_Load(object, EventArgs).
*/
Control[] objs = new Control[] { /* your object list, e. g { myLabel, myPicture } */ };
foreach (Control control in objs) {
control.BackColor = Color.Transparent;
// OR
control.BackColor = this.BackColor;
}
Background is a PictureBox.
This is also easy. We just need to make all objects as children of your PictureBox and set it's color to transparent. Code:
/*
This code will set all your object's background to transparent and show the PBox.
This should be written in the body of <FormName>_Load(object, EventArgs)'s foreach loop.
Put everything before it the same as in 1st code fragment.
*/
control.Parent = back;
control.BackColor = Color.Transparent;
Let's see the pictures.
Color
Before
After
PictureBox
Before
After (here foreground were changed, don't mind this)
Generally, labels and textboxes that appear in front of an image is best organized in a panel. When rendering, if labels need to be transparent to an image within the panel, you can switch to image as parent of labels in Form initiation like this:
var oldParent = panel1;
var newParent = pictureBox1;
foreach (var label in oldParent.Controls.OfType<Label>())
{
label.Location = newParent.PointToClient(label.Parent.PointToScreen(label.Location));
label.Parent = newParent;
label.BackColor = Color.Transparent;
}
This uses Graphics.CopyFromScreen so the control needs to be added when it's visable on screen.
public partial class TransparentLabelControl : Label
{
public TransparentLabelControl()
{
this.AutoSize = true;
this.Visible = false;
this.ImageAlign = ContentAlignment.TopLeft;
this.Visible = true;
this.Resize += TransparentLabelControl_Resize;
this.LocationChanged += TransparentLabelControl_LocationChanged;
this.TextChanged += TransparentLabelControl_TextChanged;
this.ParentChanged += TransparentLabelControl_ParentChanged;
}
#region Events
private void TransparentLabelControl_ParentChanged(object sender, EventArgs e)
{
SetTransparent();
if (this.Parent != null)
{
this.Parent.ControlAdded += Parent_ControlAdded;
this.Parent.ControlRemoved += Parent_ControlRemoved;
}
}
private void Parent_ControlRemoved(object sender, ControlEventArgs e)
{
SetTransparent();
}
private void Parent_ControlAdded(object sender, ControlEventArgs e)
{
if (this.Bounds.IntersectsWith(e.Control.Bounds))
{
SetTransparent();
}
}
private void TransparentLabelControl_TextChanged(object sender, EventArgs e)
{
SetTransparent();
}
private void TransparentLabelControl_LocationChanged(object sender, EventArgs e)
{
SetTransparent();
}
private void TransparentLabelControl_Resize(object sender, EventArgs e)
{
SetTransparent();
}
#endregion
public void SetTransparent()
{
if (this.Parent!= null)
{
this.Visible = false;
this.Image = this.takeComponentScreenShot(this.Parent);
this.Visible = true;
}
}
private Bitmap takeComponentScreenShot(Control control)
{
Rectangle rect = control.RectangleToScreen(this.Bounds);
if (rect.Width == 0 || rect.Height == 0)
{
return null;
}
Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
return bmp;
}
}
An easy way to have a label with a picture behind it is to use the Image Property of the label itself. This will print the text over the top of the picture, and enable you to align the image (top/bottom/left/right/centre) as required.picture

How do I add a mouse over tooltip to an Image using .DrawImage()

Hey all, I am not sure if this is possible, but I am trying to dynamically add a tooltip to an image using the Graphics method - DrawImage. I dont see any properties or events for when the image is moused over or anything so I don't know where to begin. I am using WinForms (in C# - .NET 3.5). Any ideas or suggestions would be appreciated. Thanks.
I would guess that you have some sort of UserControl and you call DrawImage() in the OnPaint method.
Given that, your tooltip will have to controlled explicitly. Basically, create a Tooltip on your Form, give that to your control via a property, show the tooltip when your control received a MouseHover event and hide the tooltip when you receive a MouseLeave event.
Something like this:
public partial class UserControl1 : UserControl
{
public UserControl1() {
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
// draw image here
}
public ToolTip ToolTip { get; set; }
protected override void OnMouseLeave(EventArgs e) {
base.OnMouseLeave(e);
if (this.ToolTip != null)
this.ToolTip.Hide(this);
}
protected override void OnMouseHover(EventArgs e) {
base.OnMouseHover(e);
if (this.ToolTip == null)
return;
Point pt = this.PointToClient(Cursor.Position);
String msg = this.CalculateMsgAt(pt);
if (String.IsNullOrEmpty(msg))
return;
pt.Y += 20;
this.ToolTip.Show(msg, this, pt);
}
private string CalculateMsgAt(Point pt) {
// Calculate the message that should be shown
// when the mouse is at thegiven point
return "This is a tooltip";
}
}
Remember, you have to store bounds of the Image that you are drawing
and in the mouseMove event check if the location of current Mouse cursor at that region, then display ToolTip else hide it.
ToolTip t;
private void Form1_Load(object sender, EventArgs e)
{
t = new ToolTip(); //tooltip to control on which you are drawing your Image
}
Rectangle rect; //to store the bounds of your Image
private void Panel1_Paint(object sender, PaintEventArgs e)
{
rect =new Rectangle(50,50,200,200); // setting bounds to rect to draw image
e.Graphics.DrawImage(yourImage,rect); //draw your Image
}
private void Panel1_MouseMove(object sender, MouseEventArgs e)
{
if (rect.Contains(e.Location)) //checking cursor Location if inside the rect
{
t.SetToolTip(Panel1, "Hello");//setting tooltip to Panel1
}
else
{
t.Hide(Panel1); //hiding tooltip if the cursor outside the rect
}
}

Categories

Resources