VB.Net BufferedGraphics transparent background

graphics, vb.net

Solution

The buffer you get from BufferedGraphics is not useful, it has the wrong pixel format. You want to create your own buffer, one that can support transparency. Which requires a 32bpp format. Make it Format32bppPArgb to make it as fast as possible. Rewriting this code with some additional support for resizing the form and all flicker eliminated:

Public Class Form1

    Private backBuffer As Bitmap

    Public Sub New()
        InitializeComponent()
        Me.DoubleBuffered = True
        Me.ResizeRedraw = True
    End Sub

    Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
        MyBase.OnResize(e)
        Dim newBuffer = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
        If backBuffer IsNot Nothing Then
            Using gr As Graphics = Graphics.FromImage(newBuffer)
                gr.DrawImage(backBuffer, Point.Empty)
            End Using
            backBuffer.Dispose()
        End If
        backBuffer = newBuffer
    End Sub

    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
        MyBase.OnMouseMove(e)
        If e.Button = Windows.Forms.MouseButtons.Left Then
            Using gr As Graphics = Graphics.FromImage(backBuffer)
                gr.FillEllipse(New SolidBrush(Color.Blue), CInt(e.X - (100 / 2)), CInt(e.Y - (100 / 2)), 100, 100)
            End Using
            Me.Invalidate()
        End If
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        e.Graphics.DrawImage(backBuffer, Point.Empty)
        MyBase.OnPaint(e)
    End Sub
End Class

Problem

I am using BufferedGraphics to draw some stuff and then I draw it on to a user control. This is the code: ``` Private context As BufferedGraphicsContext Private grafx As BufferedGraphics Private Sub PaintDoc_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True) Me.UpdateStyles() context = BufferedGraphicsManager.Current context.MaximumBuffer = New Size(Me.Width + 1, Me.Height + 1) grafx = context.Allocate(Me.CreateGraphics, New Rectangle(0, 0, Me.Width, Me.Height)) grafx.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear grafx.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality grafx.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality grafx.Graphics.Clear(Color.Transparent) End Sub Private Sub PaintDoc_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove If e.Button = Windows.Forms.MouseButtons.Left Then grafx.Graphics.FillEllipse(New SolidBrush(DrawColorFinal), CInt(e.x - (BrushWidth / 2)), CInt(e.y - (BrushWidth / 2)), BrushWidth, BrushWidth) Me.Invalidate() End If End Sub Private Sub PaintDoc_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint grafx.Render(e.Graphics) End Sub ``` The problem is that the grafx doesn't have a transparent background as it sould, but a black background. Any ideas why? UPDATE: Thanks to Hans Passant the problem solved and here is the final code that also supports a fast multilayer image drawing: ``` Public Class PaintDoc Public backBuffer(1) As Bitmap Public bufferGraphics(1) As Graphics Public layerIndex As Integer = 0 Private Sub PaintDoc_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Me.SetStyle(ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint Or ControlStyles.AllPaintingInWmPaint, True) Me.UpdateStyles() For i As Integer = 0 To backBuffer.Length - 1 backBuffer(i) = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb) bufferGraphics(i) = Graphics.FromImage(backBuffer(i)) bufferGraphics(i).InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear bufferGraphics(i).PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality bufferGraphics(i).SmoothingMode = Drawing2D.SmoothingMode.HighQuality Next End Sub Private Sub PaintDoc_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove If e.Button = Windows.Forms.MouseButtons.Left Then bufferGraphics(layerIndex).FillEllipse(New SolidBrush(DrawColorFinal), CInt(e.X - (BrushWidth / 2)), CInt(e.Y - (BrushWidth / 2)), BrushWidth, BrushWidth) Me.Invalidate() End If End Sub Private Sub PaintDoc_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint e.Graphics.Clear(Color.Transparent) For i As Integer = 0 To backBuffer.Length - 1 e.Graphics.DrawImage(backBuffer(i), Point.Empty) Next End Sub Private Sub PaintDoc_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize For i As Integer = 0 To backBuffer.Length - 1 Dim newBuffer As Bitmap = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb) If backBuffer(i) IsNot Nothing Then Using gr As Graphics = Graphics.FromImage(newBuffer) gr.DrawImage(backBuffer(i), Point.Empty) End Using backBuffer(i) = Nothing End If backBuffer(i) = newBuffer Next End Sub End Class ```

Original source