0

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 ?!!!

Sam Axe
  • 33,313
  • 9
  • 55
  • 89
Ehsan Akbar
  • 6,977
  • 19
  • 96
  • 180
  • I believe that OnPaint triggers before the initialization of the PictureBox – Gabe Jun 02 '14 at 07:45
  • @Baldrick i did ,but doesn't work – Ehsan Akbar Jun 02 '14 at 07:46
  • 2
    Guys, this is OnPaint *of the form*, not of the picturebox. It is mostly independent of the picturebox's paint events. OnPaint should be implementation of Paint event of PictureBox in this case. – Spook Jun 02 '14 at 07:53

4 Answers4

2

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();
}
Gabe
  • 961
  • 1
  • 10
  • 23
1

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:

  1. Keep the data required to draw the scene somewhere in the form, possibly as a private field
  2. Use these data to draw the scene in Paint event of the PictureBox
  3. 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).

Spook
  • 25,318
  • 18
  • 90
  • 167
  • ,my problem is i have a rail map that should be drawn in first time when the form is loaded ,and i have a thread that read the trains location and i have to show this trains on my map ,my problem is i have to refresh my map for every movement of trains , – Ehsan Akbar Jun 02 '14 at 07:53
  • @EA: Then you have redraw (at least partially) every time you change the picture of the movements. – Patrick Hofman Jun 02 '14 at 07:55
  • @EA Do it as I said and then invoke picturebox.Invalidate() in the threads (remember, that you have to forward this call to the main UI thread). By the way, have you even tried my solution? – Spook Jun 02 '14 at 07:55
  • 1
    As Spook later commented, if you call `Invalidate()` on the PictureBox, it will can the `Paint` again and redraw the entire or partial picture. – Patrick Hofman Jun 02 '14 at 07:59
  • @Spook i trid ,it works ,and my shape appears ,when i use your method ,i can't move some object on picturebox ,because of that i want to use Onpaint method – Ehsan Akbar Jun 02 '14 at 08:00
  • Ok thanks @Spook,but what does it mean that you said **that all calls to UI methods from the threads has to be synchronized to the main UI thread ** – Ehsan Akbar Jun 02 '14 at 08:07
  • @EA This means, that simply calling `picturebox.Invalidate()` from separate thread either won't work or will cause some problems, because UI controls are not prepared to work in multi-threaded environment. All calls to UI from separate threads should be synchronized to main UI thread using the Invoke method of the control. Read more: http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c – Spook Jun 02 '14 at 08:09
0

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.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
-1

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() ; 
    }
Pratik Singhal
  • 6,283
  • 10
  • 55
  • 97
  • 1
    This is not a proper way to solve this problem, but only a workaround. Painting of the picturebox should not happen in OnPaint method *of the form*. – Spook Jun 02 '14 at 07:59