How to erase rectangle drawn in paint event from picture box? c# - c#

I know there are many questions on this, but I just can't get it to work. I have this event:
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.DrawRectangle(new Pen(selectionBrush, 1), selectionRectangle);
}
It works as it should. Draws a colored rectangle over the image I put inside picture box. But after I draw that rectangle, I want to erase it. I basically use it as selection area for cropping the image. Is there a way that I can erase the rectangle that I have drawn? Thanks.
Here is where I want to erase the rectangle:
private void button1_Click(object sender, EventArgs e)
{
//here are some examples of what I have tried
pictureBox1.Invalidate();
Invalidate();
}

Your Paint routine has a call to DrawRectangle. Then you invalidate the rectangle. At that point, your paint routine will get called again, and, if your code to draw the rectangle is still there, it will get redrawn. You need to make it so the DrawRectangle call no longer gets called once you don't need it any more (with an if statement or something).
You also probably want to inflate the size of the invalidation rectangle by one pixel all around to make sure you don't leave any bread crumbs behind

Related

Drawing rectangles on picture box

So I'm trying to automate drawing a bunch of rectangles over an image. I've mostly figured out how to draw them, but the problem I'm running into is that I only seem to be able to get them to actually be drawn when I interact with the picture box.
namespace myGUI
{
public partial class formPicture : Form
{
public formPicture()
{
InitializeComponent();
pbImage.Image = Image.FromFile(#"../../Images/myImage.bmp");
// Doesn't Work
var g = pbImage.CreateGraphics();
g.DrawRectangle(new Pen(Color.Red, 5), 500, 200, 20, 20);
}
private void formPicture_Shown(object sender, EventArgs e)
{
// Doesn't Work
var g = pbImage.CreateGraphics();
g.DrawRectangle(new Pen(Color.Red, 5), 500, 200, 20, 20);
}
private void pbImage_Click(object sender, EventArgs e)
{
// Works
var g = pbImage.CreateGraphics();
g.DrawRectangle(new Pen(Color.Red, 5), 500, 200, 20, 20);
}
}
}
The pbImage_Click() call successfully draws the rectangle on my picture box. The other two instances of trying to draw the rectangle don't seem to result in anything.
I have no idea why it would work in one case, but not the others? I've tried invalidating the graphics, that didn't work. I've tried adding it to the Paint event, that didn't work. I've tried adding it to the validated event, the visible event, the loaded event, pretty much any other event that I can think of such that once the GUI was active it might actually result in the rectangle being drawn.
The only time it seems to work is Click or MouseClick (I haven't tried other interactive events, such as MouseUp or MouseDown, but I presume those would work as well. Besides, the whole point is that I want it to show up automatically.)
NEVER call CreateGraphics. If you want to draw on a control, handle the Paint event of that control and use the e.Graphics property provided. If the drawing needs to change, store the data that describes the drawing in one or more fields, then read those fields in the Paint event handler. If you need to force the drawing to change, modify those fields and then call Invalidate on the control. Ideally, pass an argument to that Invalidate method that describes the smallest area that has or might have changed. Here's one I and a friend prepared earlier.
Note that WinForms controls are painted and repainted quite often, so any drawing done outside the Paint event handler is likely to be wiped. That's exactly what's happening in the cases that you say are not working. The drawing is being done but is then wiped. By doing your drawing in the Paint event handler, you ensure that it is reinstated every time it is wiped, so it appears permanent.

How to make picturebox change image smooth and fast

I got a picture box that got an original image in my program. When i hover with my mouse over it it changes picture to another picture and when i leave it changes back.
But..
There is such a delay to change to the right picture if i hover over it or not. It takes like 1 second before it changes, What should i change to improve the speed of the change? This is the code i am using at the moment:
private void pictureBox1_MouseHover(object sender, EventArgs e)
{
pictureBox1.Image = ABC_Bok.Properties.Resources.BokVänsterhörn_1;
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
pictureBox1.Image = ABC_Bok.Properties.Resources.BokVänsterhörnet;
}
This is the third time today that I've seen this issue. MouseHover is raised when the mouse pointer STOPS OVER a control. If you want something to happen as soon as the mouse pointer goes over the control then you want MouseEnter, just as you're using MouseLeave for the change back again.

draw and remove a line with gdi+

I owned complex drawing code with GDI+ which draws something like a chart on a user control.
If the user clicks with control pressed, a vertical marker line in dash style should be shown.
Now I look for a way to extend the drawing code without touching the complex drawing code.
I created a marker class which attaches to the mouse-up event of the user control.
In the eventhandler a check against (ModifierKeys == Keys.Control) is done.
If the user holds the control key and click with the left mouse button the draw method of the marker class is called with the Graphics object of the usercontrol as a parameter.
The current behaviour is that for each click a new line is drawn, but the line should be deleted and a new one should be drawn.
How can i erase the drawed line?
Do I have to redraw the comlete content of the user control?
You cannot delete a drawn line because there is no way to restore the underlying graphics.
What you could do is either:
Redraw the entire graph (without the line)
or
Stack a second transparent usercontrol on top and use that to display the line. Removing and drawing it when needed.
The answer here is clearly yes. With GDI+ you just draw directly on a bitmap buffer, so if you want to undo a previous drawing operation you can do one of those things (depending on the complexity of the issue and performance):
restore the bytes that have been changed on the bitmap buffer
reload a previous state of the drawing bitmap
A simple solution would be to have 2 bitmaps (something like that is usually called double buffering). One that is shown currently (and contains the final state) and one that is used for preview only. The preview one is always a copy of the first one - just with current modifications.
So basic algorithm for this simple implementation:
start with two bitmaps (blank but identical sizes) [named A and B]
if the user draws a line always make a copy of the bitmap A in B and draw on B - show B
if the user finishes the line then make a copy of B in A and again - show B
So always show the preview bitmap, which is just a modified bitmap of the original one.
Here is an example programming code in C# (assuming all events are connected and the preview Bitmap, B, is the picture box itself (which is just named pictureBox1 here):
Bitmap bmp;
bool isDrawing;
Point previous;
void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isDrawing = true;
previous = e.Location;
}
void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
isDrawing = false;
}
void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (isDrawing)
{
using (Graphics g = Graphics.FromImage(bmp))
{
double wf = (double)bmp.Width / (double)pictureBox1.Width;
double hf = (double)bmp.Height / (double)pictureBox1.Height;
g.ScaleTransform((float)wf, (float)hf);
g.DrawLine(Pens.Black, e.Location, previous);
}
pictureBox1.Refresh();
previous = e.Location;
}
}
This code will do everything to display drawing a straight line from a point to another by simply pressing the left mouse button.

how to get the drawing graphic on picture box in c#

I have created a PictureBox in a panel. I drew some graphics on PictureBox.
I want to get those graphics on button clicking. How can I do that?
Check this link. In particular the 46.9 How do I programmatically load, modify and save a bitmap? section of that page.
You'll get the idea even though the code sample is in VB.
Good luck!
I think what you want is You have some graphics drawn over a PictureBox and you want a Image of those graphics on the click of a Button,isn't it.I am not sure if this'll work but try it;
private void ButtonGetImage_Click(object sender, EventArgs e)
{
if (SourcePictureBox.Image != null)//Just to make sure it's not empty.
{
Bitmap graphic = new Bitmap(SourcePictureBox.Image);
{
//Add some logic to modify Image if you want.
graphic.Save(#"F:\Image.bmp");//An appropriate path to save the file.
graphic.Dispose();
}
}
}

Controlling the visibility of a Bitmap in .NET

I am trying to create this simple application in c#: when the user double clicks on specific location in the form, a little circle will be drawn. By one click, if the current location is marked by a circle - the circle will be removed.
I am trying to do this by simply register the MouseDoubleClick and MouseClick events, and to draw the circle from a .bmp file the following way:
private void MouseDoubleClick (object sender, MouseEventArgs e)
{
Graphics g = this.CreateGraphics();
Bitmap myImage = (Bitmap)Bitmap.FromFile("Circle.bmp");
g.DrawImage(myImage, e.X, e.Y);
}
My problem is that I dont know how to make the circle unvisible when the user clicks its location: I know how to check if the selected location contains a circle (by managing a list of all the locations containig circles...), but I dont know how exactly to delete it.
Another question: should I call the method this.CreateGraphics() everytime the user double-clicks a location, as I wrote in my code snippet, or should I call it once on initialization?
My personal preference is to put my images in instances of the Picturebox class. Reason being, I can simply call each Picturebox's Hide() function (or set 'Visible` to false).
What you're doing is drawing directly onto the window's client area, which technically isn't wrong but normally should be done in the form's Paint handler. If at some point you decide you don't want your circle to be visible anymore, you can call the form's Invalidate() method which triggers the Paint event. There, you explicitly do not draw your circle, and so to the user, the circle disappears.
The nice thing about a Picturebox is that it's persistent - you put your image into it and optionally draw on that image, but you only need to draw once. If you use the Paint handler technique, your drawing code gets called each time the form needs to redraw itself.
Edit:
Here's some code that illustrates my Paint handler information:
private void Form_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(); // clear any and all circles being drawn
if (CircleIsVisible)
{
e.Graphics.DrawEllipse( ... ); // OR, DrawImage( ) as in your example
}
}
private void MouseDoubleClick (object sender, MouseEventArgs e)
{
CircleIsVisible = true;
Invalidate(); // triggers Paint event
}
If you're drawing bitmaps, I would load the bitmap once and store it as a class variable. This way you don't need to hit the hard drive each time you want to draw. Dispose of the bitmap when you dispose of your class (in this case, your window).
I thinks you should clear all of the image you draw before your next double click.
Such as Graphics.Clear().
On the other hand, you should not to create Graphics object or dispose it every time.
If you have simple background color you could use Graphics.DrawEllipse to draw Circles and then just change circle color to the background color. Also you need to have a Collection of all circles you draw so you can access any circle that you've drawn.

Categories

Resources