The problem is simpler to solve than you're making it. There is no reason to write the bitmap out to a file on disk. You can simply omit the call to the Save
method.
The GetHIcon
method is the real trick, as it allows you to convert a Bitmap
into an Icon
, and you've already found that one.
Here's my sample code. I added a NotifyIcon
and Timer
control to a form, and wired up the event handlers in the obvious manner. rnd
is a class-level instance of Random
, just for testing purposes.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool DestroyIcon(IntPtr hIcon);
private void timer1_Tick(object sender, EventArgs e)
{
Icon icon;
// Create a temporary new Bitmap with the size of a notification icon.
using (Bitmap bmp = new Bitmap(SystemInformation.SmallIconSize.Width, SystemInformation.SmallIconSize.Height))
{
// Fill the temporary bitmap with a random number.
using (Graphics g = Graphics.FromImage(bmp))
{
g.DrawString(rnd.Next().ToString(),
SystemFonts.MessageBoxFont,
SystemBrushes.ControlText,
0.0F, 0.0F);
}
// Convert this bitmap to an icon.
icon = Icon.FromHandle(bmp.GetHicon());
}
// Update the notification icon to use our new icon,
// and destroy the old icon so we don't leak memory.
Icon oldIcon = notifyIcon1.Icon;
notifyIcon1.Icon = icon;
DestroyIcon(oldIcon.Handle);
oldIcon.Dispose();
}
Works perfectly, no temporary files required.
Edit: Modified the above code sample to solve a GDI object leak that would eventually bring your application to its knees. How quickly would depend on the interval at which the Timer was set to tick (or however you're determining that the icon should change in your app).
It turns out that when you call the Dispose
method on an icon that was created using Icon.FromHandle
, the associated native GDI object is not destroyed. I think that's a bug in the WinForms implementation since it defies programmer expectations, but apparently Icon.FromHandle
does not assume ownership of the handle. To be fair, the documentation does say this in the "Remarks" section, but who reads that?
If you don't know to do this, you've got a memory leak on your hands. To fix it, you have to P/Invoke the Win32 function for destroying a GDI icon object (DestroyIcon
) and call it explicitly.
Please make sure that your application does this, however and wherever appropriate, to ensure that the old icons get destroyed and the associated memory is freed!