views:

285

answers:

3

I have run into a strange problem when using Graphics.DrawImage.

When using e.Graphics.DrawImage(Image, Point) in OnPaint to paint a bitmap 'buffer' on the control, it appears that parts of the image are omitted. The buffer is populated in a helper method which draws directly onto the Bitmap using a Graphics constructed from it. When the control paints, the cached bitmap is drawn on the control.

Nothing appears to be omitted on the bitmap itself, because when I saved the bitmap to disc and examined it, it was all there. (see images below)

This is what the bitmap buffer looks like:
buffer

This what appears on the control:
displayed value

This is all I am doing in OnPaint:

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    if (this.bufferInvalid)
    {
        this.UpdateBuffer();
    }

    if (this.buffer != null)
    {
        e.Graphics.DrawImage(this.buffer, Point.Empty);
    }
}
+1  A: 

You could try a couple of different things.

  • post the code to "UpdateBuffer"
  • do a bitmap.save (i.e. buffer.save) after the updatebuffer call and check what the bitmap looks like.
  • ensure that all controls have been drawn first and that no controls are being drawn transparent etc..
  • take the code of "onpaint" and "update buffer" and put it in a separate project testing to see if it works.
  • take out "base.onpaint" and check what happens
  • try a call to bitmap.drawimageunscaled instead of bitmap.drawimage
  • try using new point(0,0) instead of point.empty (a loooong shot but ya never know...)

Tons of options for debugging this, just a matter of narrowing it down.

TryCatch
+2  A: 

When OnPaint is called, Windows has an invalid region that it allows painting into, and everything else is clipped. When you want a rectangular control to be updated, you should call InvalidateRect in the Windows API to make sure the entire rectangle is part of the invalid region. OnPaint will be called automatically whenever there is any part of the control that is invalid.

Mark Ransom
Thanks! All I needed to do was call `Control.Refresh()` (which invalidates and redraws the entire control).
Zach Johnson
Control.Invalidate() is almost always better than Control.Refresh().
danbystrom
A: 

Check out the System.Windows.Forms.ControlStyles.ResizeRedraw

knockNrod