I'm losing GDI objects somewhere

Cynewulf

Member
Joined
Feb 18, 2004
Messages
5
Ive written some code which creates a bitmap, draws on the bitmap using GDI+ and copies it to a notification icon control (NF1).
It updates this bitmap (to draw a rotating swirly thing) in a timer loop (every 25ms).

Problem is, I seem to be losing GDI objects. As far as I can tell the only place where this could be happening is in icn = Icon.FromHandle(b.GetHicon).

Anyone any ideas how I can prevent this from happening?

(Note : The application loses about 3-4Kb per second)

Code:
   Dim ang As Integer = 0
   Dim s As Integer = 4
   Dim a As Double = 0

   Dim bbrsh As SolidBrush
   Dim wbrsh As SolidBrush
   Dim b As Bitmap
   Dim g As Graphics
   Dim r As Rectangle

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      bbrsh = New SolidBrush(Color.Black)
      wbrsh = New SolidBrush(Color.White)
      b = New Bitmap(16, 16)
      g = Graphics.FromImage(b)
      r = New Rectangle(0 - s, 0 - s, b.Width - 1 + (s * 2), b.Height - 1 + (s * 2))

      Me.Visible = False
   End Sub

   Private Sub timerTick_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timerTick.Tick
      DoNotificationIcon(NF1)

      a = a + 0.15
      ang += 8 + Int(14 * Math.Sin(a))
      If ang > 180 Then ang -= 180
      If ang < 0 Then ang += 180
   End Sub

   Private Sub DoNotificationIcon(ByVal nf As NotifyIcon)
      Dim icn As Icon

      g.FillPie(bbrsh, r, 0 + ang, 90)
      g.FillPie(bbrsh, r, -180 + ang, 90)

      g.FillPie(wbrsh, r, 90 + ang, 90)
      g.FillPie(wbrsh, r, -90 + ang, 90)

      icn = Icon.FromHandle(b.GetHicon)
      nf.Icon = icn
      icn.Dispose()
   End Sub

!EDIT! :
Ive narrowed it down to the line "icn = Icon.FromHandle(b.GetHicon)".
It creates a new icon each time around. Im just not sure how to prevent this from happening. Anyone?
 
Last edited by a moderator:
GDI+ objects shouldnt be form-scoped variables. They should only have very short lifetimes, otherwise youll find Windows disposing of them after a while. You should create and dispose of them all within one render cycle.

By the way.. if a system tray icon started doing that to me, Id terminate the process and remove any trace of the application from my system.
 
icn = Icon.FromHandle(b.GetHicon)
nf.Icon = icn
icn.Dispose()



hmmm, you create an icon, set nf.Icon to that icon, then dispose of the same icon. How is it working at all?
 
Originally posted by divil
GDI+ objects shouldnt be form-scoped variables. They should only have very short lifetimes, otherwise youll find Windows disposing of them after a while. You should create and dispose of them all within one render cycle.
I originally had all of my objects declared locally but I think the leak was even worse.

Originally posted by divil By the way.. if a system tray icon started doing that to me, Id terminate the process and remove any trace of the application from my system.
Well it wasnt designed for real use. Its just a conceptual test :)

Originally posted by mdpotter hmmm, you create an icon, set nf.Icon to that icon, then dispose of the same icon. How is it working at all?
It works because Icon.FromHandle(b.GetHicon) creates a copy of the icon rather than just setting a pointer. Which I think is the problem actually :/
 
Heres the modified code with the objects declared locally. The leak is still present...

Code:
   Dim ang As Integer = 0
   Dim s As Integer = 4
   Dim a As Double = 0

   Private Sub timerTick_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles timerTick.Tick
      DoNotificationIcon(NF1)

      a = a + 0.15
      ang += 8 + Int(14 * Math.Sin(a))
      If ang > 180 Then ang -= 180
      If ang < 0 Then ang += 180
   End Sub

   Private Sub DoNotificationIcon(ByVal nf As NotifyIcon)
      Dim b As Bitmap
      Dim g As Graphics
      Dim r As Rectangle

      b = New Bitmap(16, 16)
      g = Graphics.FromImage(b)
      r = New Rectangle(0 - s, 0 - s, b.Width - 1 + (s * 2), b.Height - 1 + (s * 2))

      g.FillPie(New SolidBrush(Color.Black), r, 0 + ang, 90)
      g.FillPie(New SolidBrush(Color.Black), r, -180 + ang, 90)

      g.FillPie(New SolidBrush(Color.White), r, 90 + ang, 90)
      g.FillPie(New SolidBrush(Color.White), r, -90 + ang, 90)

      nf.Icon = Icon.FromHandle(b.GetHicon)

      g.Dispose()
      b.Dispose()
   End Sub

I guess the line I need a replacement for is nf.Icon = icn.FromHandle(b.GetHicon).
I need a variant where it sets a pointer instead of creating a new instance of the icon.
Bit stumped really :/

*EDIT* Slight mod to code to remove unnecessary icn object
 
Last edited by a moderator:
Back
Top