2013-03-14 83 views
0

我正在尝试编辑位图并将其用作系统托盘图标的图标。我想知道是否有办法编辑它并使用它,而不必将其另存为本地文件,因为这看起来很麻烦,并将.ico文件保存在.exe的根目录中。我拥有的代码如下。为系统托盘图标保存位图的问题C#

//To Save icon to disk 
bitmap.Save("icon.ico", System.Drawing.Imaging.ImageFormat.Icon); 
Icon createdIcon = Icon.FromHandle(bitmap.GetHicon()); 
bitmap.Dispose(); 
return createdIcon; 

有没有更优雅的方式来做到这一点,将它保存为内部资源?或在一个内存流?另一件事是,这个函数每5分钟运行一次来​​更新系统托盘图标,并且它必须通过图标,这样我才能解决什么时候我必须关闭流。

任何帮助将不胜感激,因为这让我难住。

回答

1

该问题比解决问题要简单得多。没有理由将位图写入磁盘上的文件。您可以简单地省略对Save方法的调用。

GetHIcon method是真正的伎俩,因为它允许您将Bitmap转换为Icon,并且您已经找到了一个。

这是我的示例代码。我将一个NotifyIconTimer控件添加到窗体中,并以明显的方式连接了事件处理程序。 rndRandom的类级别实例,仅用于测试目的。

[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(); 
} 

完美地工作,不需要临时文件。

编辑:修改上面的代码示例来解决GDI对象泄漏,最终会使您的应用程序瘫痪。取决于计时器设置为打勾的时间间隔(或者您确定图标应该在您的应用程序中更改)的速度有多快。

事实证明,当您使用Icon.FromHandle创建的图标调用Dispose方法时,关联的本地GDI对象不会被销毁。我认为这是WinForms实现中的一个错误,因为它无视程序员的期望,但显然Icon.FromHandle并不是而是假定句柄的所有权。公平地说,文档确实在“备注”部分说明了这一点,但谁读了?

如果你不知道这样做,你的手上就有内存泄漏。要修复它,你必须P/Invoke Win32函数销毁一个GDI图标对象(DestroyIcon)并明确地调用它。

请确保您的应用程序执行此操作(无论何时适用),以确保旧图标被破坏并释放关联的内存!