Inputbox block the system.drawing - c#

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.

Related

Visual Studio C# pictureBox - drawing in From constructor doesn't show up

I have the problem that I want to draw on a pictureBox with an image loaded before the user gets to see it. The drawing in principle works, but if I do it in the constructor it doesn't show up. It does work if I call the same function with a button.
public Form1()
{
InitializeComponent();
draw();
}
public void draw()
{
pictureBox1.Refresh();
Graphics g = pictureBox1.CreateGraphics();
Rectangle rect = new Rectangle(new Point(20, 20), new Size(40, 40));
rect.Offset(8, 8);
g.DrawEllipse(new Pen(Brushes.Black, 2), rect);
g.Dispose();
}
private void button1_Click(object sender, EventArgs e)
{
draw();
}
I would have assumed that the circle would show up when the Form loads but it only does when I press the button. The code itself gets executed, as tested with a Message box.
The control paints itself in its Paint event, so as soon as it's shown on screen (ie, after your code), it will paint itself in dull gray as normal.
If you want to custom paint a control, any control, you either override its OnPaint function or subscribe to its exposed Paint event.
A hint should be the fact that you had to create your own Graphics object, as opposed to using the object constructed during normal painting operations, that also includes proper clipping handling.

WinForms - How do I run a function with PaintEventArgs when the form is loaded?

I'm trying to understand the graphics, and in the Graphics.FromImage documentation, it has this as an example:
private void FromImageImage(PaintEventArgs e)
{
// Create image.
Image imageFile = Image.FromFile("SampImag.jpg");
// Create graphics object for alteration.
Graphics newGraphics = Graphics.FromImage(imageFile);
// Alter image.
newGraphics.FillRectangle(new SolidBrush(Color.Black), 100, 50, 100, 100);
// Draw image to screen.
e.Graphics.DrawImage(imageFile, new PointF(0.0F, 0.0F));
// Dispose of graphics object.
newGraphics.Dispose();
}
I'm new to C# and Windows Forms and am struggling to understand how this all fits together. How is this code run, say when the form first loads or when a button is pressed?
Maybe this will help. I have an example of both drawing on Paint events but also drawing on top of an existing Image. I created a form with two picture boxes. One for each case. pictureBox1 has an event handler for the .Paint event, while pictureBox2 is only drawn when a button is pressed.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
pictureBox1.BackColor=Color.Black;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
// The code below will draw on the surface of pictureBox1
// It gets triggered automatically by Windows, or by
// calling .Invalidate() or .Refresh() on the picture box.
DrawGraphics(e.Graphics, pictureBox1.ClientRectangle);
}
private void toolStripButton1_Click(object sender, EventArgs e)
{
// The code below will draw on an existing image shown in pictureBox2
var img = new Bitmap(pictureBox2.Image);
var g = Graphics.FromImage(img);
DrawGraphics(g, pictureBox2.ClientRectangle);
pictureBox2.Image=img;
}
void DrawGraphics(Graphics g, Rectangle target)
{
// draw a red rectangle around the moon
g.DrawRectangle(Pens.Red, 130, 69, 8, 8);
}
}
So when you launch the application a red rectangle appears on the left only, because the button hasn't been pressed yet.
and when the button is pressed, the red rectangle appears on top of the image displayed in pictureBox2.
Nothing dramatic, but it does the job. So depending on the mode of operation you need (user graphics, or image annotations) use the example code to understand how to do it.

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.

How to keep graphics when resizing C# form

I am working on a program where I need to draw rectangle graphics onto the form itself, when I click the form. I created code to do this (below), but when I resize the form the rectangles are deleted.
How do I retain the drawn rectangles when the form is resized?
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
Graphics g = this.CreateGraphics();
Pen Haitham = new Pen(Color.Silver, 2);
g.FillRectangle(Haitham.Brush, new Rectangle(e.X, e.Y, 50, 50));
}
You could do this instead:
private List<Point> _points = new List<Point>();
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
foreach(Point point in _points)
{
using (Pen Haitham = new Pen(Color.Silver, 2))
{
e.Graphics.FillRectangle(Haitham.Brush, new Rectangle(point.X, point.Y, 50, 50));
}
}
}
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
_points.Add(new Point(e.X, e.Y));
Invalidate(); // could be optimized to invalidate only the future rectangle draw
}
In Windows with Winforms (or native Windows), you supposed to override OnPaint and do almost all your paint logic there.
Note with WPF, it would be different, you would compose a scene adding elements to it (here you would add a Rectangle shape to a Canvas for example).
You must do the "Graphics" things in the "Paint" event. Then you can see your rectangle always, because the event fires whenever windows needed to invalidate the paintings.
Cheers
I'm not too terribly familiar with graphics, but I am assuming that you would need to put all of your drawing objects into a container and have them redrawn when the form is sized. You might need to recall all of your paining objects in the sizeChanged event.

How to assign a click event handler to part of a drawn rectangle?

Imagine I use the .NET graphic classes to draw a rectangle.
How could I then assign an event so that if the user clicks a certain point, or a certain point range, something happens (a click event handler)?
I was reading CLR via C# and the event section, and I thought of this scenario from what I had read.
A code example of this would really improve my understanding of events in C#/.NET.
Thanks
You can assign Click event handler to control whose surface will be used to draw rectangle.
Here is a small example:
When you click on form inside of rectangle it will be drawn with red border when you click outside it will be drawn with black border.
public partial class Form1 : Form
{
private Rectangle rect;
private Pen pen = Pens.Black;
public Form1()
{
InitializeComponent();
rect = new Rectangle(10, 10, Width - 30, Height - 60);
Click += Form1_Click;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(pen, rect);
}
void Form1_Click(object sender, EventArgs e)
{
Point cursorPos = this.PointToClient(Cursor.Position);
if (rect.Contains(cursorPos))
{
pen = Pens.Red;
}
else
{
pen = Pens.Black;
}
Invalidate();
}
}
PointToClient method translates cursor coordinates to control-relative coordinates. I.e. if you cursor is at (screenX, screenY) position on the screen it can be at (formX, formY) position relatively to form's top-left corner. We need to call it to bring cursor position into coordinate system used by our rectangle.
Invalidate method makes control to redraw itself. In our case it triggers OnPaint event handler to redraw rectangle with a new border color.

Categories