c#系统托盘图标保存位图的问题

本文关键字:问题 位图 保存 系统托盘图标 | 更新日期: 2023-09-27 18:03:44

我正在尝试编辑位图并将其用作我的系统托盘图标的图标。我想知道是否有一种方法可以编辑它并使用它,而不必将其保存为本地文件,因为这似乎很混乱,并在。exe的根目录中留下一个。ico文件。我的代码如下

//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分钟运行一次更新系统托盘图标,它必须传递图标,所以我可以计算出何时必须关闭流。

任何帮助将非常感激,因为这把我难住了。

c#系统托盘图标保存位图的问题

这个问题解决起来比你制造它要简单。没有理由将位图写入磁盘上的文件。您可以简单地忽略对Save方法的调用。

GetHIcon方法是真正的技巧,因为它允许您将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();
}

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

Edit:修改了上面的代码示例,以解决最终会使应用程序崩溃的GDI对象泄漏。有多快取决于计时器被设置为滴答的间隔(或者无论你如何决定图标应该在你的应用程序中改变)。

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

如果你不知道这样做,你就会有内存泄漏。为了修复它,你必须P/Invoke Win32函数来销毁GDI图标对象(DestroyIcon)并显式调用它。

请确保您的应用程序这样做,无论如何,在适当的地方,以确保旧的图标被销毁,并释放相关的内存!