[Mono-winforms-list] System.Windows.Forms.Form:PaintEventHandleris called only when you increase the form

Jonathan Gilbert 2a5gjx302 at sneakemail.com
Wed Nov 2 19:29:33 EST 2005


At 10:18 AM 02/11/2005 -0500, Robert Havens wrote:
[snip]
> [..] But DO NOT paint from anywhere else.

To the best of my knowledge, the use of 'Refresh()' or code such as:

using (Graphics g = base.CreateGraphics())
{
  g.DrawWhatever(..);
  ...
}

..is not only legal but considered best practice for applications whose
display changes frequently. While GUI widgets cannot be altered outside of
the UI thread, System.Drawing has no such restriction and places only a few
requirements, mostly of the form that two threads may not be using the same
object concurrently. Mono has supported painting by means of
CreateGraphics() or Refresh() for a long time, and I regularly test
applications of mine which use this technique.

The reason these methods of painting are preferable to Refresh() is that
the message used by Invalidate() goes onto the same queue as any other
window message, including keyboard & mouse events. If it takes long enough
to repaint the display for more than one subsequent input event to be
generated, the system quickly degenerates with increasingly large numbers
of input events separating the paint messages. The framerate needlessly
drops, essentially to zero given busy enough input. Using Refresh() or
CreateGraphics(), on the other hand, provides for immediate lag-free update
of the display.

In general, also, Refresh() is preferable to CreateGraphics() for anything
other than simple bitmap blitting because it respects
ControlStyles.DoubleBuffer, passing a Graphics to the OnPaint event which
draws off-screen.

In the specific case of the OnSizeChanged event, it is probably better to
use Invalidate() unless you have some special reason to force a full
repaint on every single mouse movement. If you can draw quickly enough,
doing so could produce an aesthetically pleasing animated scaling effect.
If you aren't concerned so much with that, though, you will use far less
CPU time by using Invalidate() (or, better, by having the framework call it
for you by setting ControlStyles.ResizeRedraw when the control is created).

Jonathan Gilbert


More information about the Mono-winforms-list mailing list