0

I've used double-buffering for some .NET Compact Framework controls that are entirely user-drawn, but I'm having trouble figuring out how I can use double-buffering for a control that inherits from another control and paints over it.

I have a control based on DataGrid, that paints over the headers.

My OnPaint method is:

Protected Overrides Sub OnPaint(ByVal pe as System.Windows.Forms.PaintEventArgs)
    MyBase.OnPaint(pe)
    CustomPaintHeaders(pe.Graphics)
End Sub

CustomPaintHeaders just paints on top of the basic DataGrid headers with some custom drawing. Occassionally, I get flickering where I see the basic DataGrid headers get painted, but without my custom-drawn stuff on top.

Is it possible to use double-buffering, and have the painting that's done by MyBase.OnPaint applied to the buffer image?

Edit: As mentioned in my comment, I am able to do double buffering using this code:

Protected Overrides Sub OnPaint(ByVal pe as System.Windows.Forms.PaintEventArgs)
    Using currentRender as Bitmap = New Bitmap(Me.Width, Me.Height)
        Using gr as Graphics = Graphics.FromImage(currentRender)
            CustomPaintHeaders(gr)
            CustomPaintRows(gr)
        End Using
    End Using
End Sub

Private Sub CustomPaintHeaders(ByVal graphics as Graphics)

    'Custom drawing stuff in place of DataGrid column headers

End Sub

'TEMP - draws rectangle in place of grid rows
Private Sub CustomPaintRows(ByVal graphics as Graphics)
    graphics.DrawRectangle(New Pen(Me.ForeColor), 0, 20, Me.Width, Me.Height) 
End Sub

And this works fine without flickering, but I'd like to avoid having to implement CustomPaintRows, and just let DataGrid's OnPaint handle that part for me, and then draw over it's headers with my CustomPaintHeaders method.

derekj
  • 47
  • 2
  • 8

1 Answers1

0

Double-buffering in the CF is a manual process, so I would assume that your base class holds an Image or Bitmap onto which it is drawing? It depends on exactly how you're doing your painting but you can either make that Image protected or you can do something slightly more complex like this:

protected virtual void OnPaint(graphics bufferGraphics) { } 

void OnPaint(PaintEventArgs pe)
{
    var buffer = new Bitmap(this.Width, this.Height);
    var bufferGraphics = Graphics.FromImage(buffer);

    // do base painting here
    bufferGraphics.DrawString(....);
    // etc.

    // let any child paint into the buffer
    OnPaint(bufferGraphics);

    // paint the buffer to the screen
    pe.Graphics.DrawImage(buffer, 0, 0);
}

Then in your child, simply override the new OnPaint and do what you want with the incoming Graphics object, which paints onto the buffer, not the screen.

If you want the child to be able to completely override base painting, just move the base painting logic into the virtual method.

ctacke
  • 66,480
  • 18
  • 94
  • 155
  • My control inherits System.Windows.Forms.DataGrid. I'm not sure how DataGrid does it's drawing. – derekj Aug 15 '14 at 20:24
  • My control inherits System.Windows.Forms.DataGrid. I'm not sure how DataGrid does it's drawing. I can do double buffering successfully, similar to how you did above, using a new Bitmap and doing using a Graphics object from that, when using my CustomPaintHeaders method and a CustomPaintRows method (which currently just draws a white Rectangle in place of the grid). Is there a way to make DataGrid's normal OnPaint paint to a buffer image though? (so I can just call that and CustomPaintHeaders, and not have to go and actually implement CustomPaintRows) – derekj Aug 15 '14 at 20:30
  • And you've already looked at some of the resources specifically for formatting CF DataGrids? http://www.codeproject.com/Articles/20268/NET-CF-Custom-DataGrid-Formatting – ctacke Aug 15 '14 at 23:59
  • Yes, I actually used that page to help me make certain whole rows colored differently based on different conditions. – derekj Aug 18 '14 at 17:03
  • Didn't figure out how to apply painting from MyBase.OnPaint to buffer, but I decided to just resolve my issue the easy way - do my custom header painting with double buffering, and set RowHeadersVisible = False and made row painting start below my custom headers. – derekj Aug 18 '14 at 17:32