[...]
So, is there a simple way of wiring my OnPaint method (which works fine)
to be triggered off a repaint of PictureBox1 instead of Form1? If so,
how do I do it?
It seems to me that you actually have two different issues. One is, where
to do the drawing? That is, where does your drawing code go? The other
is, how do you cause the drawing to occur?
With respect to the first question...
The PictureBox class is not for people who want to do their own drawing.
It's a convenient control to which you can attach an existing Image, and
let the control itself deal with a variety of display issues. Such as,
when to draw, if and how to scale the image, that sort of thing.
You _could_ certainly derive a new class from PictureBox and override the
OnPaint() method, but that would be sort of pointless. You can easily do
the same thing deriving from the Control class, without having all the
extra PictureBox functionality dragged along.
You could also handle the PictureBox's Paint event, but again it would be
pointless, for the same reasons.
The reason for deriving from PictureBox would be if you want to use and
extend or override functionality that is specific to the PictureBox
class. So far I haven't seen anything that would suggest that's what
you're doing or what you want.
So where should you do the drawing? IMHO, it depends on what your UI is
like, which I don't know. If you intend to manage all of the drawing
inside the form, then drawing in the form class would be a reasonable
place. If, however, you want to be able to use the VS Designer to
implement and maintain the user interface, and you want to be able to
manipulate where you custom drawing happens as part of that maintenance,
then you will probably want to create a custom Control-derived class.
That way, you'll get a custom control added to your Designer toolbox that
you can drag and drop, placing it wherever you like.
Creating a custom control is very simple, practically the same as creating
a new form class. Just add a new item to the project (using the
Project/Add New Item... menu or the Solution Explorer), and select "Custom
Control" from the template list. This will create a new class derived
from Control. In that class, you can override OnPaint() where you want to
draw.
Of course, you will want to move any other code related to managing the
graphics into that control class, or somewhere related to it. That's a
broader design question, and frankly it's much harder to answer those
questions in a newsgroup like this. Providing good advice on design
generally requires a lot of background knowledge of the problem being
solved, and not only is that background knowledge difficult to express in
this context, so too is explaining how a good design would work.
Suffice to say, a good design makes it easy to put all your pieces
together. Conversely, if you're having trouble putting the pieces
together, you should rethink the design.
Now, finally...there's the question of how to cause the drawing to occur.
The basic mechanism is invalidation of the control. In this context
"invalidation" means something very specific: to communicate to Windows
that an area of the control no longer has valid graphics and needs to be
redrawn. You use the Control.Invalidate() method to do this.
I've already explained that in this thread, and I believe that the various
links that have been posted, by myself and others, also explain it
reasonably well. The basic idea is this though: you don't draw in direct
reaction to changes in the data; you design your drawing code so that it
can always draw whatever the current state of the data is, and you
invalidate the control in reaction to changes to data.
Since you're using the BufferedGraphics class, it seems to me that this
should be especially simple. When you change the BufferedGraphics by
drawing to it, you need to call Invalidate() on whatever control it is
that you are drawing to (the Form class inherits Control as well). If you
know specifically what area of the BufferedGraphics has changed, you can
use that information to restrict the invalidated area, passing a rectangle
to the Invalidate() method so that only the part that changed winds up
getting redrawn.
Pete