Link to home
Start Free TrialLog in
Avatar of koossa
koossa

asked on

Graphics and Bitmap High CPU with VB.net

I have a picturebox on my Windows form.  Form's windowstate = maximize
Picturebox Dock = fill

Here is my code .

Public Class Form1

  Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    Dim MyBmp As Bitmap
    If PictureBox1.Image Is Nothing Then
      MyBmp = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    Else
      MyBmp = New Bitmap(PictureBox1.Image)
    End If
    Dim MyGraphics As Graphics = Graphics.FromImage(MyBmp)
    MyGraphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
    MyGraphics.DrawEllipse(Pens.Blue, e.X - 50, e.Y - 50, 100, 100)
    MyGraphics.Dispose()
    PictureBox1.Image = MyBmp
  End Sub
End Class

Open in new window



When I draw circles on the form using the code above, the drawing gets very sticky and the CPU is rising.

What can I do to make it softer on the resources?

I know I can draw using Graphics.FromHwnd(picturebox1.handle), but when something moves over the form it wipes the drawing on that region.


Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Option #1
Public Class Form1

    Private Radius As Integer = 50
    Private GP As New System.Drawing.Drawing2D.GraphicsPath

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        Dim rc As New Rectangle(e.Location, New Size(1, 1))
        rc.Inflate(Radius, Radius)
        GP.AddEllipse(rc)
        PictureBox1.Refresh()
    End Sub

    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
        e.Graphics.DrawPath(Pens.Blue, GP)
    End Sub

End Class

Open in new window

Option #2:
Public Class Form1

    Private Radius As Integer = 50
    Private BMP As Bitmap = Nothing
    Private G As Graphics

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        If IsNothing(BMP) Then
            BMP = New Bitmap(PictureBox1.Width, PictureBox1.Height)
            G = Graphics.FromImage(BMP)
            PictureBox1.Image = BMP
        End If
        Dim rc As New Rectangle(e.Location, New Size(1, 1))
        rc.Inflate(Radius, Radius)
        G.DrawEllipse(Pens.Blue, rc)
        PictureBox1.Refresh()
    End Sub

End Class

Open in new window

Avatar of koossa
koossa

ASKER

Thank you for the 2 options.

They are both still a bit sticky.

Is n't there a way to draw it as fast as the following code ?

[code]
Public Class Form1

  Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    'Dim MyBmp As Bitmap
    'If PictureBox1.Image Is Nothing Then
    '  MyBmp = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    'Else
    '  MyBmp = New Bitmap(PictureBox1.Image)
    'End If
    Dim MyGraphics As Graphics = Graphics.FromHwnd(PictureBox1.Handle)
    MyGraphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
    MyGraphics.DrawEllipse(Pens.Blue, e.X - 50, e.Y - 50, 100, 100)
    MyGraphics.Dispose()
    'PictureBox1.Image = MyBmp
  End Sub
End Class
[/code]
Will the circles only be drawn when the mouse button is down?

If so, then you can use CreateGraphics() to draw directly to the screen and only update the actual PictureBox with Refresh() when the mouse is let go:
Public Class Form1

    Private Radius As Integer = 50
    Private BMP As Bitmap = Nothing
    Private G As Graphics
    Private tmpG As Graphics

    Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            Cursor.Clip = PictureBox1.RectangleToScreen(PictureBox1.ClientRectangle)
            tmpG = PictureBox1.CreateGraphics
        End If
    End Sub

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        If e.Button = Windows.Forms.MouseButtons.Left Then
            If IsNothing(BMP) Then
                BMP = New Bitmap(PictureBox1.Width, PictureBox1.Height)
                G = Graphics.FromImage(BMP)
                PictureBox1.Image = BMP
            End If
            Dim rc As New Rectangle(e.Location, New Size(1, 1))
            rc.Inflate(Radius, Radius)
            G.DrawEllipse(Pens.Blue, rc)
            tmpG.DrawEllipse(Pens.Blue, rc)
        End If
    End Sub

    Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
        If e.Button = Windows.Forms.MouseButtons.Left Then
            tmpG.Dispose()
            Cursor.Clip = Nothing
            PictureBox1.Refresh()
        End If
    End Sub

End Class

Open in new window

Avatar of koossa

ASKER

Thank you very much for your replies
I don't understand the code, but it's supposed to draw when the mouse are moving (it's for children)

I have changed your code and it is working, but I don't know if it is correct, I have only removed the Picturebox1.refresh()

Public Class Form1

  Private Radius As Integer = 50
  Private BMP As Bitmap = Nothing
  Private G As Graphics
  Private tmpG As Graphics

  'Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
  '  If e.Button = Windows.Forms.MouseButtons.Left Then
  '    Cursor.Clip = PictureBox1.RectangleToScreen(PictureBox1.ClientRectangle)
  '    tmpG = PictureBox1.CreateGraphics
  '  End If
  'End Sub

  Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    'If e.Button = Windows.Forms.MouseButtons.Left Then
    tmpG = PictureBox1.CreateGraphics
    If IsNothing(BMP) Then
      BMP = New Bitmap(PictureBox1.Width, PictureBox1.Height)
      G = Graphics.FromImage(BMP)
      PictureBox1.Image = BMP
    End If
    Dim rc As New Rectangle(e.Location, New Size(1, 1))
    rc.Inflate(Radius, Radius)
    G.DrawEllipse(Pens.Blue, rc)
    tmpG.DrawEllipse(Pens.Blue, rc)
    tmpG.Dispose()
    Cursor.Clip = Nothing
    'PictureBox1.Refresh()

    'End If
  End Sub

  'Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
  '  If e.Button = Windows.Forms.MouseButtons.Left Then
  '    tmpG.Dispose()
  '    Cursor.Clip = Nothing
  '    PictureBox1.Refresh()
  '  End If
  'End Sub

End Class

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial