Cynewulf Posted February 18, 2004 Posted February 18, 2004 (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 February 18, 2004 by Cynewulf Quote
*Gurus* divil Posted February 18, 2004 *Gurus* Posted February 18, 2004 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. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
mdpotter Posted February 18, 2004 Posted February 18, 2004 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? Quote
Cynewulf Posted February 19, 2004 Author Posted February 19, 2004 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 :/ Quote
Cynewulf Posted February 19, 2004 Author Posted February 19, 2004 (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 February 19, 2004 by Cynewulf Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.