Form icon

DavyEFC

Well-known member
Joined
Dec 17, 2010
Messages
51
Programming Experience
5-10
I was looking how to flash a form to alert the user when i came across the following code. Thought it could look good with a little modification. However, when i run the code in the IDE it works perfectly (alternating the icon in the taskbar), but running from the compiled .exe then the icon does not change, static! Any ideas as this has me beat...

VB.NET:
    Private Sub tmrAlert_Tick(...) Handles tmrAlert.Tick
        Static a As Boolean
        '------------------
        a = Not a
        If a = True Then
            Me.Icon = My.Resources.events
        Else
            Me.Icon = My.Resources.warning
        End If
    End Sub
 
I was looking how to flash a form to alert the user when i came across the following code. Thought it could look good with a little modification. However, when i run the code in the IDE it works perfectly (alternating the icon in the taskbar), but running from the compiled .exe then the icon does not change, static! Any ideas as this has me beat...

VB.NET:
    Private Sub tmrAlert_Tick(...) Handles tmrAlert.Tick
        Static a As Boolean
        '------------------
        a = Not a
        If a = True Then
            Me.Icon = My.Resources.events
        Else
            Me.Icon = My.Resources.warning
        End If
    End Sub
When you run your program in Visual Studio, it compiles your application and runs the exe file, same as you running the exe file yourself outside of Visual Studio so there's got to be something going on with your code that's causing this to not work as you would expect. The code you've posted doesn't show where the issue would be as I'm not able to reproduce the problem on my end:
Public Class Form1

    Private m_IconSwitchBool As Boolean

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        m_IconSwitchBool = Not m_IconSwitchBool
        Me.Icon = Icon.FromHandle(If(m_IconSwitchBool, My.Resources.BringToFrontHS, My.Resources.drive_disk).GetHicon())
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Timer1.Stop()
    End Sub

    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Timer1.Interval = 1000I '1 Second
        m_IconSwitchBool = True
    End Sub

    Private Sub Form1_Shown(sender As Object, e As System.EventArgs) Handles Me.Shown
        Timer1.Start()
    End Sub

End Class
Note both of the images I've loaded into the Resources are bitmaps, so I had to cast the bitmap objects to an icon object.
 
You should retrieve those Resources objects only once and assign to class variables, and dispose the two when done with them. As it is you are creating many GDI objects and not disposing them.
That does not relate to the icon not changing, though, just a reminder :)
 
You should retrieve those Resources objects only once and assign to class variables, and dispose the two when done with them. As it is you are creating many GDI objects and not disposing them.
That does not relate to the icon not changing, though, just a reminder :)
I can't find anything on MSDN that explains how the My.Resources.<bitmap> works internally, I always thought that when the application starts it instantiates each of those images and when you call My.Resources.ImageName it passes a reference to the image which would mean if you dispose of the image you can not use that image anymore. Doesn't help that every example I can find simply shows assigning the image from the My.Resources directly without storing it in an intermediary variable.
Ultimately I'll have to create a project and play with it, but it would be nice to see a document or something from MS that would explain how that really works.
 
JB said:
I can't find anything on MSDN that explains how the My.Resources.<bitmap> works internally, I always thought that when the application starts it instantiates each of those images and when you call My.Resources.ImageName it passes a reference to the image which would mean if you dispose of the image you can not use that image anymore.
Do you get the same image object every time?
Dim same = My.Resources.img Is My.Resources.img

I never get the same image object.
As for documentation, take a look at the generated code, for an image resource it does this:
                Dim obj As Object = ResourceManager.GetObject("thename", resourceCulture)
                Return CType(obj,System.Drawing.Bitmap)
help said:
If you call the GetObject method multiple times with the same name parameter, do not depend on the return value being a reference to the same object. This is because the GetObject method can return a reference to an existing resource object in a cache, or can reload the resource and return a reference to a new resource object.
About "existing resource object in a cache", I'm not sure what that means. Looking at the internal code it indirectly leads to ResourceSet.GetObject. Documentation for that gives away nothing, the internal code does look like it keeps a HashTable of resources, but back to the practical code I posted that looks to not be true. I said indirectly though, what is between is a lookup for the ResourceSet, maybe the case is ResourceManager returns a new set object each time? I tested out some practical code for that too, getting the ResourceSet object and used its GetObject two times, also then two different image objects is returned. So what gives? For some reason I figured I would try a different type of resource also, now a simple string. My.Resources (ResourceManager.GetString) still returns new objects, but the funny thing is when I get and use my own ResourceSet multiple calls to its GetObject/GetString (that actually both calls same internal method) returns the same string object! I've yet to discover exactly why there is a difference, but the evidence is clear about this.
JB said:
every example I can find simply shows assigning the image from the My.Resources directly without storing it in an intermediary variable
Yes, fine as long as you clean up each. Here when toggling between two images multiple times it makes sense to keep only two objects.
 
Do you get the same image object every time?
Dim same = My.Resources.img Is My.Resources.img

I never get the same image object.
As for documentation, take a look at the generated code, for an image resource it does this:
                Dim obj As Object = ResourceManager.GetObject("thename", resourceCulture)
                Return CType(obj,System.Drawing.Bitmap)

About "existing resource object in a cache", I'm not sure what that means. Looking at the internal code it indirectly leads to ResourceSet.GetObject. Documentation for that gives away nothing, the internal code does look like it keeps a HashTable of resources, but back to the practical code I posted that looks to not be true. I said indirectly though, what is between is a lookup for the ResourceSet, maybe the case is ResourceManager returns a new set object each time? I tested out some practical code for that too, getting the ResourceSet object and used its GetObject two times, also then two different image objects is returned. So what gives? For some reason I figured I would try a different type of resource also, now a simple string. My.Resources (ResourceManager.GetString) still returns new objects, but the funny thing is when I get and use my own ResourceSet multiple calls to its GetObject/GetString (that actually both calls same internal method) returns the same string object! I've yet to discover exactly why there is a difference, but the evidence is clear about this.

Yes, fine as long as you clean up each. Here when toggling between two images multiple times it makes sense to keep only two objects.
Learn something new everyday.
And no, none of the examples I can find online mention anything about cleaning up these image objects, not even the MS ones on MSDN. Tisk tisk to them.
 
Back
Top