Jump to content
Xtreme .Net Talk

Recommended Posts

Posted (edited)

I've 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)

 

  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! :

I've narrowed it down to the line "icn = Icon.FromHandle(b.GetHicon)".

It creates a new icon each time around. I'm just not sure how to prevent this from happening. Anyone?

Edited by Cynewulf
  • *Gurus*
Posted

GDI+ objects shouldn't be form-scoped variables. They should only have very short lifetimes, otherwise you'll 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, I'd terminate the process and remove any trace of the application from my system.

MVP, Visual Developer - .NET

 

Now you see why evil will always triumph - because good is dumb.

 

My free .NET Windows Forms Controls and Articles

Posted

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?

Posted
GDI+ objects shouldn't be form-scoped variables. They should only have very short lifetimes, otherwise you'll 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, I'd terminate the process and remove any trace of the application from my system.

Well it wasn't designed for real use. It's 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 :/

Posted (edited)

Here's the modified code with the objects declared locally. The leak is still present...

 

   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

Edited by Cynewulf

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...