I\'m using Windows Forms. For a long time, pictureBox.Invalidate();
worked to make the screen be redrawn. However, it now doesn\'t work and I\'m not sure why.
Invalidate()
only "invalidates" the control or form (marks it for repainting), but does not force a redraw. It will be redrawn as soon as the application gets around to repainting again when there are no more messages to process in the message queue. If you want to force a repaint, you can use Refresh()
.
Invalidate
or Refresh
will do the same thing in this case, and force a redraw (eventually). If you're not seeing anything redrawn (ever), then that means either nothing has been drawn at all in DrawWorldBox
or whatever has been drawn has been drawn off the visible part of the PictureBox's image.
Make sure (using breakpoints or logging or stepping through the code, as you prefer) that something is being is being added to selectionRectangles
, and that at least one of those rectangles covers the visible part of the PictureBox. Also make sure the pen you're drawing with doesn't happen to be the same color as the background.
To understand this you have to have some understanding of the way this works at the OS level.
Windows controls are drawn in response to a WM_PAINT
message. When they receive this message, they draw whichever part of themselves has been invalidated. Specific controls can be invalidated, and specific regions of controls can be invalidated, this is all done to minimize the amount of repainting that's done.
Eventually, Windows will see that some controls need repainting and issue WM_PAINT
messages to them. But it only does this after all other messages have been processed, which means that Invalidate
does not force an immediate redraw. Refresh
technically should, but isn't always reliable. (UPDATE: This is because Refresh
is virtual
and there are certain controls in the wild that override this method with an incorrect implementation.)
There is one method that does force an immediate paint by issuing a WM_PAINT
message, and that is Control.Update. So if you want to force an immediate redraw, you use:
control.Invalidate();
control.Update();
This will always redraw the control, no matter what else is happening, even if the UI is still processing messages. Literally, I believe it uses the SendMessage
API instead of PostMessage
which forces painting to be done synchronously instead of tossing it at the end of a long message queue.