Override paint method doesn't work correctly - c#

I am trying to draw a rectangle on PictureBox without using Paint event of picturebox,So i override the Onpaint method :
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics dc = pictureBox1.CreateGraphics();
Pen bPen=new Pen(Color.Blue,3);
dc.DrawRectangle(bPen,0,0,50,50);
}
}
But the rectangle doesn't appear in first time ,but when i change the size of form using mouse my rectangle is appeared why ?!!!

I understand that you do not want to use the Paint event of the PictureBox. Your code wouldn't work since the form gets rendered before its containing elements.
I offer you a solution: draw on a bitmap and then insert that bitmap into the PictureBox through its Image public member.
private void loadDrawing(){
Bitmap map = new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height);
var graph = Graphics.FromImage(map);
graph.DrawRectangle(new Pen(Color.Blue, 3), 0, 0, 50, 50);
pictureBox1.Image = map;
}
Let's say you want to make the Rectangle to show up upon load:
private void Form1_Load(object sender, EventArgs e)
{
loadDrawing();
}

The problem is that you override OnPaint method of the form instead of Paint event of the PictureBox. Form's OnPaint happens, when the form needs repainting, and that's independent of what happens with the PictureBox.
Implement OnPaint event of the PictureBox and then you will not have to create Graphics object manually - simply use one provided in the event arguments.
private void Form1_Load(object sender, EventArgs e)
{
// No need to do that
// pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(10, 10, 20, 20));
}
Edit: (in response to comments)
If you want to update the paintbox periodically, do the following:
Keep the data required to draw the scene somewhere in the form, possibly as a private field
Use these data to draw the scene in Paint event of the PictureBox
When you need to update the scene, modify the data accordingly, and then call the Invalidate method of the PictureBox. It will cause the Paint event to fire and the scene will be redrawn.
Remember though, that all calls to UI methods from the threads has to be synchronized to the main UI thread (otherwise they won't work or cause problems).

You are overriding the paint method of the form, while you paint the PictureBox. That isn't how it is meant to be. The PictureBox will still do it's own rendering.
If you really want to do painting of the PictureBox, implement the Paint event of the PictureBox or create a custom control where you draw a rectangle, and a picture.

After you draw the form refresh the form using this :-
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics dc = pictureBox1.CreateGraphics();
Pen bPen=new Pen(Color.Blue,3);
dc.DrawRectangle(bPen,0,0,50,50);
this.Refresh() ;
}

Related

How do I raise an event when a WPF control ( Image control) is redrawn?

I have a winforms paint event handler that handles the paint event for a picturebox. As the paint event description says, "...the event is fired when the control is redrawn". I do not quite understand this and I wish to raise the same event in WPF on an Image control. But I can't find any such events. Here is the winforms code
How do I do this in WPF??
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (pictureBox1.Image != null)
{
if (temprect != new Rectangle())
{
e.Graphics.DrawRectangle(new Pen(selectionBrush, 2), temprect);
}
}
else
{
using (Font myFont = new Font("Arial", 40, FontStyle.Bold))
{
e.Graphics.DrawString("No Image", myFont, Brushes.LightGray,
new Point(pictureBox1.Width / 2 - 132, pictureBox1.Height / 2 - 50));
}
}
}
I have already converted all the code within the event Hanlder to WPF using DrawingContext class. Now, I only need help on the event that I can raise "when the Image control is redrawn".
WPF doesn't use WinForm's on-demand mode painting. The OnRender method of a UIElement is called by the layout system whenever it wants the element to "redraw" itself. You can override this method in your class:
public class YourElement : FrameworkElement
{
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
}
}
If you want to re-render the element explicitly you could call the InvalidateVisual() method.

Drawing Graphics not working on Form load event

private void DrawIt()
{
System.Drawing.Graphics graphics = this.CreateGraphics();
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(
50, 50, 150, 150);
graphics.DrawRectangle(System.Drawing.Pens.Red, rectangle);
}
private void Form1_Load(object sender, EventArgs e)
{
DrawIt();
}
private void button1_Click(object sender, EventArgs e)
{
DrawIt();
}
when putting the 'DrawIt' method in a button event it works, but in a form load event it doesn't, why?
Change Load event to Paint.
If you want redraw your form use this.Refresh();
When you are in Paint method use:
private void mForm_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillEllipse(...);
}
The Load event is run before the Form is drawn. So anything you draw is overwritten by the Form.
Call your DrawIt method from an event which fires after the Form has loaded.
You need to an event to trigger DrawIt(). You can use a panel or sth else. Then write an OnClik event. Your drawing will start after a click.
if vb6 just add call to your sub or function in Form_Activate
Instead of using Form_Load event use Form_Shown event. That should work.

Deleting graphics

I am trying to delete all the graphics on a group box when pressing a button, but I cannot figure it out how. Adding a new background to the group box seems slow, I want to make it faster.
Moreover, I've read about the Invalidate() method, but it doesn't do what I need.
The piece of code I am talking about :
private void button1_Click(object sender, EventArgs e)
{
groupBox0.Invalidate();
}
private void groupBox0_Paint(object sender, PaintEventArgs e)
{
Graphics graphObj = groupBox0.CreateGraphics();
Pen mypen = new Pen(System.Drawing.Color.Red, 2);
graphObj.DrawRectangle(mypen, 0, 0, 10, 10);
}
When I run the code it does nothing, the graphics are still there. What can I do or change ?

Can't get DrawLine to work when triggered by a button press.

this code works just fine when it's in a different delegate, but doesn't work when it's triggered by a button. "Draw_Click" is a button called "Draw" and it's supposed to make a drawing on the screen based on a pre-made array of points.
private void Draw_Click(object sender, EventArgs e)
{
Graphics myInstance = this.CreateGraphics();
for (int t = 0; t <= numberOfPoints - 1; t++)
{
myInstance.DrawLine(pen, spiroArray[0, t], spiroArray[1, t], spiroArray[0, t + 1], spiroArray[1, t + 1]);
}
}
But when I have this same code in this class, it works fine (minus the myInstance line).
private void Form1_Paint(object sender, PaintEventArgs e)
{
}
I use "e" instead of "myInstance" just to make this question as brief as possible.
Basically, what's so special about Form1_Paint? Shouldn't I be able to make it draw something even outside that special Form1Paint class? If I use that Form1_Paint, I don't have control over when it does the drawing. I'm basically trying to have it update the drawing as the user changes parameters, etc.
The error is "Error 1 The name 'DrawLine' does not exist in the current context"
Thanks for any help.
I am not sure I am getting your question correctly, because if I read your question and code the way I think, the error you should be getting is that "pen" does not exist in the current context. If you use that same code to draw, it will work on either the button_click or the form_paint events. "this" will still refer to the form, and using it to instantiate a graphics object will give you access to draw anywhere in the form. From either the button click handler or the form paint method. However, the only think I can see that would fail is if you never defined the pen. Here is the code I used, and it drew a red line when the form first came up, and then drew a black line when I clicked on the button I had put on the same form.
private void button1_Click(object sender, EventArgs e)
{
Graphics myInstance = this.CreateGraphics();
myInstance.DrawLine(Pens.Black, 15, 10, 25, 20);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics myInstance = this.CreateGraphics();
myInstance.DrawLine(Pens.Red, 10, 10, 20, 20);
}
There has to be something that is not coming across right in the statement of your question.

Drawing rectangle does not work in Windows Forms

The program should draw a rectangle on click. But it does not. Maybe some problem with my understanding of delegates. What's the catch?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace forms1
{
public partial class MainForm : Form
{
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//this.Paint+= new PaintEventHandler(MujPaintHandler);
this.Click += new EventHandler(MujClickHandler);
}
public void MujPaintHandler(object sender,PaintEventArgs e)
{
Graphics gfx=e.Graphics;
gfx.FillRectangle(new SolidBrush(Color.DarkViolet),100,100,200,200);
}
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.Paint+= new PaintEventHandler(MujPaintHandler);
}
}
}
The code you've written works for me, but your form's window has to be big enough to show the rectangle.
Diagnostically, the first thing I'd check is whether the title of the form changes to "aaaaa". If it does, then you know the click handler is being called - but maybe you've got a problem with the paint handler. If it doesn't, then for some reason your click handler isn't being called.
Note that this isn't the normal way you'd draw a rectangle on a click in Windows Forms, but I'm assuming this is just a learning exercise.
Try forcing a redraw after assigning the event handler:
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.Paint+= new PaintEventHandler(MujPaintHandler);
this.Invalidate();
}
Also, if you click twice, the event handler gets assigned twice, which is not something you want.
Maybe you have to force a redraw. Does the rect appear if you move the window? Just call the PaintHandler after click.
I think you are only attaching the Paint event handler. You are not invoking the Paint event.
Try this
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.Paint+= new PaintEventHandler(MujPaintHandler);
this.Invalidate();
}
It will only draw the rectangle if it happens to be inside the area that is invalidated to update the text that you change.
When you change the text, it creates a message that the text has to be redrawn, which will call the Paint event to do the drawing. The event will have a Graphics object that is clipped to the rectangle that needs to be redrawn to update the text, so only the part of the rectangle that intersects with the text will be drawn.
You have to cause a redraw that covers the entire rectangle, so the easiest is to cause the whole window to be redrawn:
this.Invalidate();
Note that you should not hook up the Paint event from the Click event handler. That means that the event will be hooked up one more time each click, so after five clicks the Paint event handler will be called five times every time something needs to be redrawn.
Looking at your code, I understand that you are trying to add an eventhandler for paint event on Click... You would also need to invoke the paint event.. Here is a sample code where I am assigning the Paint EventHandler on a button click and raising the paint event on the click as you are doing
public Form1()
{
InitializeComponent();
this.Click += new EventHandler(MujClickHandler);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey)
{
MessageBox.Show(e.KeyCode.ToString());
}
}
private void Form1_Load(object sender, EventArgs e)
{
//this.Paint += new PaintEventHandler(MujPaintHandler);
}
public void MujPaintHandler(object sender,PaintEventArgs e)
{
Graphics gfx=e.Graphics;
gfx.FillRectangle(new SolidBrush(Color.DarkViolet),100,100,200,200);
}
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.RaisePaintEvent(this, new PaintEventArgs(this.CreateGraphics(), this.RectangleToClient(new Rectangle())));
}
private void button1_Click(object sender, EventArgs e)
{
this.Paint += new PaintEventHandler(MujPaintHandler);
}

Categories