c# Panel line overwriting - c#

Inside the Paint event for panel, I have a code, that should draw a blue line between 2 points.
private void panel1_Paint(object sender, PaintEventArgs e)
{
panel1.AllowDrop = true;
listBox1.AllowDrop = true;
if (!s.IsEmpty && !f.IsEmpty)
{
e.Graphics.DrawLine(new Pen(Color.Blue, 5f), f, s);
s = Point.Empty;
f = Point.Empty;
}
}
Im Invalidating the panel in SetPoint method:
void setPoint(Point p)
{
if (f.IsEmpty)
f = p;
else
{
s = p;
panel1.Invalidate();
}
}
That is triggered by clicking on a button.
It will draw a line, but the problem is, that when one line already exists. It will overwrite it. I thought problem is in Invalidate. But I dont know how to fix it because Refresh() or Update() Doesn't work.
What I'm doing wrong?

You need to save all your points in some structure.
In Paint method you will loop through the structure and draw all the lines.
That's because when Paint is activated it redraws all the control once again, and it can't "remember" what was there before, it is only doing what you wrote inside.

Related

Inputbox block the system.drawing

I am trying to code this function on a form: User click on the form, a inputbox asks user to input a name, and a circle is drawn on the place in the form where the user clicks. One issue now I faces is that circle is now draw at the place where the inputbox show up. I actually have a function to repaint every circle on the form, but it still does not work. Here is my code:
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
string ProvinceName;
System.Drawing.SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
System.Drawing.Graphics formGraphics;
formGraphics = this.CreateGraphics();
formGraphics.FillEllipse(myBrush, new Rectangle(e.X, e.Y, 10, 10));
ProvinceName = Microsoft.VisualBasic.Interaction.InputBox("郡名", "", "无名",100,100);
provinces.Add(new province(ProvinceName, e.X, e.Y));
listBox1.SelectedIndex = provinces.Count - 1;
myBrush.Dispose();
formGraphics.Dispose();
PaintMap();// This is the function repaint every recorded clicked locations.
}
Just drawing it is not enough. Every time the form is redrawn it will need to be painted again. The first step would be to override OnPaint
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// paint your circles here, when they need to be persisted
// e.Graphics.DrawRectangle(redPen, r);
}
Obviously you will need to keep track of what needs to be drawn, and when it no longer needs to be drawn, however this should get you started
I used Bipmap to store the paint and then use paint event to repaint the form. The problem is solved. I think when I directly use "System.Drawing, I paint on the inputbox.

Small problems when dynamically resizing a picturebox (tooltip delay, 'blinking')

Help please elegantly solve a couple of problems in my small project. I'm developing a small program in c # (WinForms), which uses pictureboxes instead of buttons. I added a small feature like an 'animation' to them: when you mouse over them they decrease in size, when the mouse goes away they return to their original state. Actually, I have two problems here:
If the mouse is brought to the very edge, the picturebox will be decreased, but if the mouse is out of the current size of the picturebox, it's size will be returned back. And so on. Such a kind of 'blinking' turns out.
And more importantly, I have tooltips attached to these pictureboxes. And if you move the mouse over the picturebox, it will decrease in size and the tooltip will not be called. It will take to move the cursor a little without going beyond the picturebox so the tooltip will appear. And this behavior is counterintuitive.
Here's the code:
private void IconReduce(PictureBox picturebox)
{
originalLocation = picturebox.Location;
originalSize = picturebox.Size;
picturebox.Location = new Point(picturebox.Location.X + 2, picturebox.Location.Y + 2);
picturebox.Size = new Size(picturebox.Size.Width - 4, picturebox.Size.Height - 4);
}
private void IconNormal(PictureBox picturebox)
{
picturebox.Location = new Point(originalLocation.X, originalLocation.Y);
picturebox.Size = new Size(originalSize.Width, originalSize.Height);
}
private void pb_MouseEnter(object sender, EventArgs e)
{
IconReduce(sender as PictureBox);
}
private void pb_MouseLeave(object sender, EventArgs e)
{
IconNormal(sender as PictureBox);
}

Brush print is not consecutive

I'm trying to implement the Brushing function to my Paint project.
My idea is everywhen I move and press mouse left button on canvas, I'll add a ellipse to Free-brush (like MSPaint)
Everything was good until I move mouse faster. >> the brush print is separated.
Can anyone explain to me and give me some hints to solve this?
Here is my code:
Point _startPoint, _endPoint;
private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(MyCanvas);
Ellipse MyBrush_Ellipse = new Ellipse();
MyBrushing.CreateBrush(_cl1, _cl2, ref MyBrush_Ellipse, Mybrush_type);
Canvas.SetTop(MyBrush_Ellipse, _startPoint.Y);
Canvas.SetLeft(MyBrush_Ellipse, _startPoint.X);
}
private void MyCanvas_MouseMove(object sender, MouseEventArgs e)
{
_endPoint = e.GetPosition(MyCanvas);
if (e.LeftButton == MouseButtonState.Pressed)
{
Ellipse MyBrush_Ellipse = new Ellipse();
MyBrushing.CreateBrush(_cl1, _cl2, ref MyBrush_Ellipse, Mybrush_type);
Canvas.SetTop(MyBrush_Ellipse, _endPoint.Y);
Canvas.SetLeft(MyBrush_Ellipse, _endPoint.X);
MyCanvas.Children.Add(MyBrush_Ellipse);
MyCanvas.CaptureMouse();
_myUndoRedo.PushToStackForBrush(MyBrush_Ellipse);
}
}
private void MyCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
MyCanvas.ReleaseMouseCapture();
}
The mouse is not moving constantly over the screen. When moving faster from A to B the mouse actually does not neccessarily move over every part of the screen in between.
To solve your problem draw a line instead of drawing an ellipse at the mouse's position. Therefore you have to store the point the mouse has been before. After a movement draw a line from the stored, last known point to the actual point.

DIfference between PaintEventArgs.Graphics and Graphics.FromHwnd in Drawing

Latest
//combination of pictureBox1.Invalidate(); and pictureBox1.Update();
pictureBox1.Refresh();
After pictureBox1.Refresh(); , it will trigger pictureBox1_Paint
Following code will have the icon remain on the picture box.
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (checkBox1.Checked)
{
e.Graphics.DrawIcon(IconCamera, rect);
}
}
Following code NOT! it will draw the icon and clear it soon after it was drawn in Paint (that why have my old question)
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics graphic = Graphics.FromHwnd(pictureBox1.Handle);
if (checkBox1.Checked)
{
graphic.DrawIcon(IconCamera, rect);
}
}
I thought these two graphics are same but it seem like they are not same.
May I know what is the difference of Graphics of PaintEventArgs of
pictureBox1 and Graphics from handle of pictureBox1?
Why DrawIcon on pictureBox1 Paint event with Graphics from handle of
pictureBox1 will disappear in Paint event but not in the function I
declared? thanks
Old Question
When I checked the checkbox then I will draw icon on the picture box,
Graphics graphic = Graphics.FromHwnd(pictureBox1.Handle);
if (checkBox1.CheckState.ToString() == "Checked")
{
Icon IconCamera = new Icon("cam.ico");
Rectangle rect = new Rectangle(100, 100, 32, 32);
graphic.DrawIcon(IconCamera, rect);
}
BUT After the picture box refresh,
pictureBox1.Refresh();
the drawn icon will disappear.
May I know what picturebox event OR else can I make use to put in the drawing icon code to maintain or always auto redraw the icon even after the picture box refresh()? thanks. I tried Paint and Validating of picturebox1 cannot work.
The best is to use two calls one after each other:
pictureBox1.Invalidate();
pictureBox1.Update();
This will force the picturebox to be redrawn.
Then I subscribe for Paint event, which is signalled when previous two lines of code are called (in case of redrawing the picturebox). Here I do the all the drawings.
In your case it would be something like this:
public void Paint(PaintEventArgs e)
{
if (checkBox1.Checked)
{
Rectangle rect = new Rectangle(100, 100, 32, 32);
Icon IconCamera = new Icon("cam.ico");
e.Graphics.DrawIcon(IconCamera, rect);
}
}
Then, subscribe for event CheckedChanged of checkBox1, and call there that two redrawing commands from the begin of this post.
It causes, that when user change the checked state of checkBox1, pictureBox1 will be forced to be redrawn and the icon will be drawn according to checkBox1 state.
You can avoid using a Graphics object and find another way. I don't know if you are forced in using an icon, but you can try to use a Label this way.
label1.Image = "yourImage.bmp" // you can use a bitmap
There here come your statement.
if(checkBox1.Checked) {
label1.Visible = true;
label1.Location = new Point(x, y); // your coordinate
}
Then you can handle checkBox1_CheckedChanged and code:
Void checkBox1_CheckedChanged(object sender, EventArgs e) {
if(!checkBox1.Checked) {
label1.Visible = false;
}
}
Hope this could help.

Draggable text or shapes on an image in C# or VB.NET

I'm trying to create a Winforms application using either C# or VB.NET that will allow me to place text or a shape on top of an existing image inside a picturebox and have that text or shape draggable with the mouse. For example, if I want to place a 90X90 square on the image, I would enter 90 in a 'width' textbox, 90 in a 'height' textbox and click on the image and it would be drawn on top of the existing image. Then I can position it by moving the mouse where I want it to be exactly. There could be other steps if required (like clicking a 'insert rectangle' button that starts the process). I've tried a few ideas like calling a routine that resets the picturebox to it's original image and draws the shape when the 'mouse move' event is raised, but that is obviously too slow. Should this be done in the paint event of the picturebox, and if so, could someone point me in the right direction of how to do it? Is this possible, or am I oversimplifying the idea?
Thanks in advance for your help.
Below is a very naive example of how to paint a draggable rectangle inside a parent control.
public class Draggable : PictureBox
{
Rectangle shapeBounds;
bool isDragging;
Point dragPoint;
public Draggable()
{
InitializeComponent();
shapeBounds = new Rectangle(10, 10, 30, 30);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (shapeBounds.Contains(e.Location))
{
isDragging = true;
dragPoint = new Point(
e.Location.X - shapeBounds.Location.X,
e.Location.Y - shapeBounds.Location.Y);
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
isDragging = false;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (isDragging)
{
Point p = new Point(
e.Location.X - dragPoint.X,
e.Location.Y - dragPoint.Y);
shapeBounds = new Rectangle(p, shapeBounds.Size);
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillRectangle(Brushes.Red, shapeBounds);
}
}

Categories