0

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.)

gunr2171
  • 16,104
  • 25
  • 61
  • 88
INCyr
  • 15
  • 4
  • 1
    Subscribe to the PictureBox's `Paint` event and move `.DrawRectangle()` there (so it becomes `e.Graphics.DrawRectangle(...)`). Remove it from anywhere else. -- Don't use `CreateGraphics()` to draw on a Control's surface. – Jimi Aug 09 '22 at 00:42
  • 1
    May be useful: [How to use the Paint event to draw shapes at mouse coordinates](https://stackoverflow.com/a/53708936/7444103) – Jimi Aug 09 '22 at 00:47

1 Answers1

1

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.

John
  • 3,057
  • 1
  • 4
  • 10
  • I was basing the call to CreateGraphics() on the answer to this question: https://stackoverflow.com/questions/13595585/drawing-multiple-rectangles-c-sharp. I had tried to use the Paint event, but it wasn't working - but changing it to e.Graphics.DrawRectangle() worked. Thanks. – INCyr Aug 09 '22 at 14:22
  • Okay, follow up question. I actually want to draw ~60 rectangles at various locations, with various rotations. Using e.Graphics seems to allow me to draw a single rectangle, but doesn't seem to scale to multiple rectangles. My current Paint event looks something like this: `for(int i = 0; i < numRects; i++) { e.Graphics.RotateTransform(angle[i]); e.Graphics.DrawRectangle(PEN, X, Y, W, H);}` – INCyr Aug 09 '22 at 14:30
  • Nevermind, figured out the multiple rectangles. Thanks again. – INCyr Aug 09 '22 at 14:50
  • _I was basing the call to CreateGraphics() on the answer to this question_ - yup, terrible advice! – TaW Aug 10 '22 at 12:01