Clear all Bitmap drawings using push button - c#

I made several drawings using Windows forms application visual studio Bitmap, my goal is to clear all drawings when I press the push button (make the background clear)
The Following code is not exactly what my original code but this is how I created each drawing
Rectangle area;
Bitmap creature;//this only one drawing but I have several
Graphics scG;
Bitmap background;
private void Form1_Load(object sender, EventArgs e)
{
background = new Bitmap(Width, Height);
area = new Rectangle(50, 50, 50, 50);
creature = new Bitmap(#"C:\Users\Desktop\Image.png");
}
public Bitmap Draw()
{
Graphics scG = Graphics.FromImage(background);
scG.DrawImage(creature, area);
return background;
}
}
private void Button_Click(object sender, EventArgs e)
{
// I want to clear all the drawings by push this button
}

There is no way to remove things drawn on a bitmap.
Why don't just dump the old background bitmap and create a new one?

this is duplicate , see this link :
How to delete a drawn circle in c# windows form?
or test these Code :
Graphics.Clear();
or
Control.Invalidate();
or
this.Invalidate();

The real way is to use event Paint:
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(creature, area); // draw your image here...
}
To delete, just do nothing in Form1_Paint, and call Refresh();

Related

C# custom picturebox control

I work on a project where I need to constantly get bitmaps and draw them on a picturebox.
The idea is to draw a first initial bitmap, then retrive the rest of the bitmap and draw them above the initial one. (The first one still displayed in the picturebox, so I want to draw them on the first bitmap).
I tried to design a custom control, to implement the OnPaint event, but the second time the event is fired, it draws the second block and completely conceals the image which had been drawn before.
public class RapidPictureBox: PictureBox
{
public pictureBox1Control()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
}
public Bitmap block = null;
public int x = 0, y = 0;
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(block, x, y);
}
}
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.block = new Bitmap("3.png"); //first initial image
pictureBox1.block = new Bitmap("2.png"); //draw on the initial one.
}
I'm not sure what's wrong in the code. I use the e EventArgs to draw a new block everytime I need but it seems the new drawing compeletly hides the previous bitmap.
you can create a graphics object from the picturebox,then redraw it over the current image
initial =new Bitmap("test.png");
pictureBox1.Image = initial;
var graphics = pictureBox1.CreateGraphics(); //create a graphic objec
graphics.DrawImage(block, x,y);//that's the second method
What you should do is overlay the new image on previous image.
Let's say there is a primary image (first image) and you want to print next image(overlapping image) on that same primary image. Use following method to do that.
private Bitmap GetOvelappedImages(Bitmap primaryImage, Bitmap overlappingImage)
{
//create graphics from main image
using (Graphics g = Graphics.FromImage(primaryImage))
{
//draw other image on top of main Image
g.DrawImage(overlappingImage, new Point(0, 0));
}
return primaryImage;
}
then set this new image to pictureBox1.block.
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.block = GetOverlappedImages(new Bitmap("3.png"),new Bitmap("2.png")); //draw on the initial one.
}
That should work for you.
Note: You should dispose images after they are used.
Update:
You need to redraw whole image because, OnPaint is called only when current image shown on picture box needs to be redrawn.
The OnPaint method is overridden to repaint the image each time the form is painted; otherwise the image would only persist until the next repainting.
Read documentation for OnPaint here
The problem with your code is that you are not adding pictures to the control you are replacing them.
Side Note: With the code you have you are not disposing of the Bitmap objects set in the PictureBoxes image and so this could cause memory leaks.
You can create a similar control LayeredPictureBox. This will get all of the images and draw them on top of each other. It will have poor performance and the images will need to have transparency to look layered but you get the idea:
public class LayeredPictureBox : PictureBox
{
public LayeredPictureBox()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.ResizeRedraw, true);
}
public List<Bitmap> blocks = new List<Bitmap>();
public int x = 0, y = 0;
protected override void OnPaint(PaintEventArgs e)
{
foreach (Bitmap block in blocks)
{
e.Graphics.DrawImage(block, x, y);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
RapidPictureBox pictureBox1 = new RapidPictureBox();
pictureBox1.Dock = DockStyle.Fill;
Controls.Add(pictureBox1);
pictureBox1.blocks.Add(new Bitmap("3.png")); //first initial image
pictureBox1.blocks.Add(new Bitmap("2.png")); //draw on the initial one.
}
Another option is to merge all of the images together on adding them and then just drawing that image into the PictureBox.

copying free hand drawing from panel in visual studio 2013

I want to draw free hand in a form (picture box) on visual studio and copy the same figure (that I draw) on another panel/picture box.
Also they should not be dots forming one line but a continuous line. Please help.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Pen p_white;
bool draw = true;
private Graphics objgraphics;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Pen p_black = new Pen(new SolidBrush(Color.Black));
if (draw)
{
objgraphics = panel1.CreateGraphics();
}
}
/*private void panel1_MouseDown(object sender, MouseEventArgs e)
{
bool draw = true;
}*/
private void panel1_MouseMove_1(object sender, MouseEventArgs e)
{
Rectangle rEllipse = new Rectangle();
switch (e.Button)
{
case MouseButtons.Left:
rEllipse.X = e.X;
rEllipse.Y = e.Y;
rEllipse.Width = 5;
rEllipse.Height = 5;
objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse);
break;
case MouseButtons.Right:
rEllipse.X = e.X;
rEllipse.Y = e.Y;
rEllipse.Width = 3;
rEllipse.Height = 3;
objgraphics.DrawEllipse(System.Drawing.Pens.Black, rEllipse);
break;
default:
return;
}
}
/*private void panel1_MouseUp(object sender, MouseEventArgs e)
{
bool draw = false;
} */
private void form_Paint(object sender, EventArgs e)
{
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
Pen p_black = new Pen(new SolidBrush(Color.Black));
if (draw)
{ objgraphics = panel1.CreateGraphics();
}
}
private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
Looking at your code I'm afraid I have to say: This is all wrong.
Sorry to be so blunt, but you must never use control.CreateGraphics!!
The first thing to do is to throw away the Graphics objgraphics object.
It is (almost) always wrong to store a Graphics object!
Instead, you have to use the one you get from the e.Graphics parameter in the Paint events of your controls.
Note that Graphics doesn't contain any graphics, it is a tool used to draw onto an associated Bitmap or a control's surface.
The next thing is to do is to understand about drawing freehand lines. Often one can see the code you have; but it is useless and only an example of how many stupid things you find in introductions. Forget it. It will always look like crap as the circles simply never look smooth and as soon as you move the mouse faster the pseudo-lines completely fall apart.
There is a nice method DrawCurve that will draw smooth lines. You feed it a Pen and an array of Points.
This is what we will use.
Let's return to the basics: How to create a graphic? Now we know that you need to call DrawCurve in the Paint event:
e.Graphics.DrawCurve(somePen, somePointsArray);
This brings up the next questions:
what's somePen
what's somePointsArray
There is a hidden third question:
what about drawing more lines?
The first one is simple; you create a Pen with a stroke width of 5.5 pixels as
Pen somePen = new Pen(Color.Blue, 5.5f);
If you want to you can give it a linestyle (dashes), too.
Now for the array: In its simplest form this is easy as well.
In the MouseMove event you store the current Location in a list of points. First, we declare it at class level:
List<Point> currentLine = new List<Point>();
Then we start filling it as long as the left button is pressed:
private void panel1_MouseMove_1(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
currentLine.Add(e.Location);
panel1.Invalidate();
}
}
Note the last line: Calling Invalidate on a control triggers the system to invoke the Paint event. It may look complicated but this is the only correct way as it guarantees that the very same drawing will also happen when some other reason makes it necessary.
We need to draw because we have changes the data that should be drawn. But there are many outside reasons, most notoriously the Minimize/maximize sequence that will clear the drawing and trigger the Paint event, too. So we need to cooperate with the way windows draws its controls! Only this way the graphics will persist.
Also, note we don't use an array as we don't know how many Points we will need. Instead, we use a List and later cast it to Array.
Let's code the Paint event for our simple case:
private void panel1_Paint(object sender, PaintEventArgs e)
{
using (Pen somePen = new Pen(Color.Blue, 5.5f) )
if (currentLine.Count > 1) e.Graphics.DrawCurve(yourPen , currentLine.ToArray());
}
Note that I have created the Pen in a using clause. This is a cheap and safe way to ensure that the Pen is disposed of properly.
Also note how we cast the List to an Array!
The above code alone would work and allow you free-hand drawing a line.
But what about the next line? It should not connect to the first one so we can't just add more points!
So we need not just one list of points but more than that, in fact, a list of lists of points is called for:
List<List<Point>> curves = new List<List<Point>>();
And we add the current curve to it whenever the mouse is released:
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (currentLine.Count > 1) curves.Add(currentLine.ToList()); // copy!!
currentLine.Clear();
panel1.Invalidate();
}
Note how I use a cast from List to List to enforce a copy or else only the reference would be assigned and then, in the next line cleared..
Again we trigger the Paint event as the final thing to do.
We now should change the Paint event to display all the lines, both the one currently being drawn and all the earlier ones..:
private void panel1_Paint(object sender, PaintEventArgs e)
{
using (Pen somePen = new Pen(Color.Blue, 5.5f) )
{
if (currentLine.Count > 1) e.Graphics.DrawCurve(somePen, currentLine.ToArray());
foreach (List<Point> lp in curves)
if (lp.Count > 1) e.Graphics.DrawCurve(somePen, lp.ToArray());
}
}
Now we are basically done with the free-hand drawing part.
So we return to your original question: How can you copy the drawing to a second Panel?
Well, you have stored everything in the curves data structure.
So you have two options: Either simply use the same data in the panel2_Paint event or if you need to copy and change the data to, maybe adapt to a different size.
Here are the things still missing:
Saving the data, saving the drawing (Serialize, DrawToBitMap)
Drawing with varying pens & colors (create a drawAction class to store all you need)
Using other tools like Line or Rectangle (create a drawAction class)
Clearing the drawing (see below)
Undo and Redo (look into Stacks an Queues)
Caching when there are a great number of lines ( draw the first portion into a BackgroundImage Bitmap)
Here is a clearing code:
curves.Clear(); currentLine .Clear(); panel1.Invalidate();
I noted that your original code lets you draw with two different stroke widths using the left and right button. This alone shows that this code is not very good. Who would a) think of that and b) be satisfied with only two stroke widths.
Please read this post where I explain a little about creating a class that can store a pen width, a color etc so that you can change then between lines you draw.

C# transparent image above 2 images

I have make a playbar for my new MP3 player but I have a problem as shown in attachement
and this is my simple code :
public void setpercent(int percent)
{
pic1.Width = pic2.Width / 100 * percent;
pic3.Left = pic1.Width - ( pic3.Width /2);
}
I thought to use Graphics but I can't move it after.
and the method of ".Parent" doesn't work in this case.
In the Load() event of your Form, modify the Region() property of pic3 so that it becomes circular instead of rectangular. This can be done by construction a GraphicsPath and adding an Ellipse to it. If this doesn't line up properly with your image, then manually determine the correct bounding box for the ellipse and use that instead:
private void Form1_Load(object sender, EventArgs e)
{
System.Drawing.Drawing2D.GraphicsPath GP = new System.Drawing.Drawing2D.GraphicsPath();
GP.AddEllipse(pic3.ClientRectangle);
pic3.Region = new Region(GP);
}

How to do Free hand Image Cropping in C# window application?

How to do Free hand Image Cropping in C# window application??
Okay, you provided very small amount of information, but I'll assume that you are using winforms. There are some tasks dealing with freehand-technique such as:
Drawing
Drag-n-dropping
Cropping
Selecting
They all are very similar. Let's assume that you have a PictureBox and want to crop an image inside it.
// Current selection
private Rectangle _cropRectangle;
// Starting point
private Point _cropStart;
// Dragging flag
private bool _isDragging;
private void pBox_MouseDown(object sender, MouseEventArgs e)
{
_cropRectangle = new Rectangle(e.X, e.Y, 0, 0);
_isDragging = true;
}
private void pBox_MouseUp(object sender, MouseEventArgs e)
{
_isDragging = false;
}
private void pBox_MouseMove(object sender, MouseEventArgs e)
{
if (!_isDragging)
return;
_cropRectangle = new Rectangle(Math.Min(_cropStart.X, e.X),
Math.Min(_cropStart.Y, e.Y),
Math.Abs(e.X - _cropStart.X),
Math.Abs(e.Y - _cropStart.Y));
pBox.Invalidate();
}
private void pBox_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(Pens.Red, _cropRectangle);
}
What happens: I make use of three mouse events (MouseDown, MouseUp, MoseMove) and the Paint event. Basically, whenever you want to do anything from the above list, you'll have handle these four events.
I tried to keep the code short and self-explanatory. There are four event handlers working with three instance fields. The fields are used to store the current state of dragging process.
Feel free to customize the code, especially the pBox_Paint handler. Mine just draws a thin red rectangle around selected area. You might want to do something more elaborate here.
Whenever you're done with your rectangle, you can call the Crop method:
private Image Crop()
{
Bitmap croppedImage = new Bitmap(_cropRectangle.Width, _cropRectangle.Height);
using (Graphics g = Graphics.FromImage(croppedImage))
{
g.DrawImage(pBox.Image, 0, 0, _cropRectangle, GraphicsUnit.Pixel);
}
return croppedImage;
}
It creates a new Bitmap and put the selected portion of source image into it. The returned Image object might be used in any manner you like.
EDIT: trying to simplify the code I made some mistakes earlier, fixed now.
You can use Graphics.DrawImage to draw a cropped image onto the graphics object from a bitmap.
Rectangle cropRect = new Rectangle(...);
Bitmap src = Image.FromFile(fileName) as Bitmap;
Bitmap target = new Bitmap(cropRect.Width, cropRect.Height);
using(Graphics g = Graphics.FromImage(target))
{
g.DrawImage(src, cropRect,
new Rectangle(0, 0, target.Width, target.Height),
GraphicsUnit.Pixel);
}
You can also refer the full code for this....
Refer this *Link*

A PictureBox Problem

I have a problem:
I have 3 picture boxes with 3 different images as in Image
what can i set to pictureBox3 so both images look same.....
EDITED:
I want to move pictureBox3 on pictureBox2,
So there is no Option to merge them to single image
Make sure the image in pictureBox3 is transparent. Set the BackColor to transparent. In code, set the Parent property of the pictureBox3 to be pictureBox2. Adjust the Location coordinates of pictureBox3 since they will be relative to the coordinates of pictureBox2 once you've changed the Parent.
private void Form1_Load(object sender, EventArgs e)
{
pictureBox3.Parent = pictureBox2;
pictureBox3.Location =
new Point(
pictureBox3.Location.X
- pictureBox2.Location.X,
pictureBox3.Location.Y
- pictureBox2.Location.Y);
}
In designer you will not see the transparency, but at runtime you will.
Update
In the image, the left side shows the designer view, the right side is the runtime version.
Another update
I really don't understand how it would be possible that this doesn't work for you. I suppose there must be something we are doing different. I'll describe the exact steps to take to create a working sample. If you follow the exact same steps, I wonder if we'll get the same results or not. Next steps describe what to do and use two images I found on the net.
Using Visual Studio 2008, create a New Project using template Windows Forms Application. Make sure the project is targeted at the .NET Framework 3.5.
Set the Size of the Form to 457;483.
Drag a PictureBox control onto the form. Set its Location to 0;0 and its Size to 449;449.
Click the ellipsis besides its Image property, click the Import... button and import the image at http://a.dryicons.com/files/graphics_previews/retro_blue_background.jpg (just type the URL in the File name text box and click Open). Then click OK to use the image.
Drag another PictureBox onto the form, set its Location to 0;0 and its Size to 256;256. Also set its BackColor property to Transparent.
Using the same method as described above, import image http://www.axdn.com/redist/axiw_i.png which is a transparent image.
Now place the following code in the form's OnLoad event handler:
private void Form1_Load(object sender, EventArgs e)
{
pictureBox2.Parent = pictureBox1;
}
That's it! If I run this program I get a transparent image on top of another image.
I'll add another example that according to the updated requirement allows for moving image3.
To get it working, put an image with transparency in Resources\transp.png
This uses the same image for all three images, but you can simply replace transparentImg for image1 and image2 to suitable images.
Once the demo is started the middle image can be dragged-dropped around the form.
public partial class Form1 : Form
{
private readonly Image transparentImg; // The transparent image
private bool isMoving = false; // true while dragging the image
private Point movingPicturePosition = new Point(80, 20); // the position of the moving image
private Point offset; // mouse position inside the moving image while dragging
public Form1()
{
InitializeComponent();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(231, 235);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
this.pictureBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseDown);
this.pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseMove);
this.pictureBox1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseUp);
this.Controls.Add(this.pictureBox1);
transparentImg = Image.FromFile("..\\..\\Resources\\transp.png");
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.DrawImageUnscaled(transparentImg, new Point(20, 20)); // image1
g.DrawImageUnscaled(transparentImg, new Point(140, 20)); // image2
g.DrawImageUnscaled(transparentImg, movingPicturePosition); // image3
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
var r = new Rectangle(movingPicturePosition, transparentImg.Size);
if (r.Contains(e.Location))
{
isMoving = true;
offset = new Point(movingPicturePosition.X - e.X, movingPicturePosition.Y - e.Y);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (isMoving)
{
movingPicturePosition = e.Location;
movingPicturePosition.Offset(offset);
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isMoving = false;
}
}
This code will do the trick:
using (Graphics g = Graphics.FromImage(pictureBox1.Image))
{
g.DrawImage(pictureBox2.Image,
(int)((pictureBox1.Image.Width - pictureBox2.Image.Width) / 2),
(int)((pictureBox1.Image.Height - pictureBox2.Image.Height) / 2));
g.Save();
pictureBox1.Refresh();
}
It will draw the image from pictureBox2 on the existing image of pictureBox1.
For starters, set the BackColor property of PictureBox3 to Transparent. This should work in almost all cases.
You should also use an image with a transparent background instead of white so you do not have the white borders around your purple circle. (Recommended image format: PNG)
Update
Following the replies I got, it appears setting the BackColor to Transparent doesn't work. In that case, it's best you handle the Paint event of the PictureBox and do the painting of the new image yourself as Albin suggested.
You might do some hack by overriding OnPaint and stuff, example here.
But I'd recommend to merge the pictures in pictureBox2 and 3 into a single image before displaying them in a single pictureBox.

Categories

Resources